firmware: ti_sci: Add support to get TISCI handle using of_phandle

TISCI has been updated to have support for Resource management(like
interrupts etc..). And there can be multiple device instances of a
resource type in a SoC. So every driver corresponding to a resource type
should get a TISCI handle so that it can make TISCI calls. And each
DT node corresponding to a device should exist under its corresponding
bus node as per the SoC architecture.

But existing apis in TISCI library assumes that all TISCI users are
child nodes of TISCI. Which is not true in the above case. So introduce
(devm_)ti_sci_get_by_phandle() apis that can be used by TISCI users
to get TISCI handle using of phandle property.

Signed-off-by: Grygorii Strashko <grygorii.strashko@ti.com>
Signed-off-by: Lokesh Vutla <lokeshvutla@ti.com>
Acked-by: Nishanth Menon <nm@ti.com>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
This commit is contained in:
Grygorii Strashko 2019-04-30 15:42:17 +05:30 committed by Marc Zyngier
parent 89626d4bad
commit 905c30477f
2 changed files with 100 additions and 0 deletions

View File

@ -1764,6 +1764,89 @@ const struct ti_sci_handle *devm_ti_sci_get_handle(struct device *dev)
}
EXPORT_SYMBOL_GPL(devm_ti_sci_get_handle);
/**
* ti_sci_get_by_phandle() - Get the TI SCI handle using DT phandle
* @np: device node
* @property: property name containing phandle on TISCI node
*
* NOTE: The function does not track individual clients of the framework
* and is expected to be maintained by caller of TI SCI protocol library.
* ti_sci_put_handle must be balanced with successful ti_sci_get_by_phandle
* Return: pointer to handle if successful, else:
* -EPROBE_DEFER if the instance is not ready
* -ENODEV if the required node handler is missing
* -EINVAL if invalid conditions are encountered.
*/
const struct ti_sci_handle *ti_sci_get_by_phandle(struct device_node *np,
const char *property)
{
struct ti_sci_handle *handle = NULL;
struct device_node *ti_sci_np;
struct ti_sci_info *info;
struct list_head *p;
if (!np) {
pr_err("I need a device pointer\n");
return ERR_PTR(-EINVAL);
}
ti_sci_np = of_parse_phandle(np, property, 0);
if (!ti_sci_np)
return ERR_PTR(-ENODEV);
mutex_lock(&ti_sci_list_mutex);
list_for_each(p, &ti_sci_list) {
info = list_entry(p, struct ti_sci_info, node);
if (ti_sci_np == info->dev->of_node) {
handle = &info->handle;
info->users++;
break;
}
}
mutex_unlock(&ti_sci_list_mutex);
of_node_put(ti_sci_np);
if (!handle)
return ERR_PTR(-EPROBE_DEFER);
return handle;
}
EXPORT_SYMBOL_GPL(ti_sci_get_by_phandle);
/**
* devm_ti_sci_get_by_phandle() - Managed get handle using phandle
* @dev: Device pointer requesting TISCI handle
* @property: property name containing phandle on TISCI node
*
* NOTE: This releases the handle once the device resources are
* no longer needed. MUST NOT BE released with ti_sci_put_handle.
* The function does not track individual clients of the framework
* and is expected to be maintained by caller of TI SCI protocol library.
*
* Return: 0 if all went fine, else corresponding error.
*/
const struct ti_sci_handle *devm_ti_sci_get_by_phandle(struct device *dev,
const char *property)
{
const struct ti_sci_handle *handle;
const struct ti_sci_handle **ptr;
ptr = devres_alloc(devm_ti_sci_release, sizeof(*ptr), GFP_KERNEL);
if (!ptr)
return ERR_PTR(-ENOMEM);
handle = ti_sci_get_by_phandle(dev_of_node(dev), property);
if (!IS_ERR(handle)) {
*ptr = handle;
devres_add(dev, ptr);
} else {
devres_free(ptr);
}
return handle;
}
EXPORT_SYMBOL_GPL(devm_ti_sci_get_by_phandle);
static int tisci_reboot_handler(struct notifier_block *nb, unsigned long mode,
void *cmd)
{

View File

@ -217,6 +217,10 @@ struct ti_sci_handle {
const struct ti_sci_handle *ti_sci_get_handle(struct device *dev);
int ti_sci_put_handle(const struct ti_sci_handle *handle);
const struct ti_sci_handle *devm_ti_sci_get_handle(struct device *dev);
const struct ti_sci_handle *ti_sci_get_by_phandle(struct device_node *np,
const char *property);
const struct ti_sci_handle *devm_ti_sci_get_by_phandle(struct device *dev,
const char *property);
#else /* CONFIG_TI_SCI_PROTOCOL */
@ -236,6 +240,19 @@ const struct ti_sci_handle *devm_ti_sci_get_handle(struct device *dev)
return ERR_PTR(-EINVAL);
}
static inline
const struct ti_sci_handle *ti_sci_get_by_phandle(struct device_node *np,
const char *property)
{
return ERR_PTR(-EINVAL);
}
static inline
const struct ti_sci_handle *devm_ti_sci_get_by_phandle(struct device *dev,
const char *property)
{
return ERR_PTR(-EINVAL);
}
#endif /* CONFIG_TI_SCI_PROTOCOL */
#endif /* __TISCI_PROTOCOL_H */