Files
2026-08-24 10:03:24 +08:00

123 lines
2.3 KiB
C

// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
/*
* Copyright (c) 2019 Amlogic, Inc. All rights reserved.
*/
#include <linux/slab.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/of_platform.h>
#include "watch-key-private.h"
int __of_watchkey_parse(struct amlogic_watchkey *wk, struct device_node *np)
{
int ret;
ret = of_property_read_string(np, "wk-name", &wk->name);
if (ret)
return ret;
ret = of_property_read_u32(np, "wk-id", &wk->id);
if (ret)
return ret;
ret = of_property_read_u32(np, "wk-type", &wk->type);
if (ret)
return ret;
ret = of_property_read_u32(np, "wk-code", &wk->code);
if (ret)
return ret;
wk->report_event = of_property_read_bool(np, "wk-report-event");
return 0;
}
static int __of_watchkey_get(struct amlogic_watchkey *wk, struct device_node *np)
{
struct platform_device *pdev;
struct device_node *node;
int ret;
node = of_parse_phandle(np, "watch-key", 0);
if (!node)
return -ENODEV;
ret = __of_watchkey_parse(wk, node);
if (ret)
goto node_put_out;
pdev = of_find_device_by_node(node->parent);
if (!pdev) {
ret = -ENODEV;
goto node_put_out;
}
if (!pdev->dev.driver) {
ret = -EPROBE_DEFER;
goto node_put_out;
}
wk->dev = &pdev->dev;
return 0;
node_put_out:
of_node_put(node);
return ret;
}
void of_amlogic_watchkey_put(struct amlogic_watchkey *wk)
{
if (IS_ERR_OR_NULL(wk))
return;
of_node_put(wk->dev->of_node);
put_device(wk->dev);
kfree(wk);
}
EXPORT_SYMBOL_GPL(of_amlogic_watchkey_put);
struct amlogic_watchkey *of_amlogic_watchkey_get(struct device *dev)
{
struct amlogic_watchkey *wk;
int ret;
wk = kzalloc(sizeof(*wk), GFP_KERNEL);
if (!wk)
return ERR_PTR(-ENOMEM);
ret = __of_watchkey_get(wk, dev->of_node);
if (ret)
goto free_out;
return wk;
free_out:
kfree(wk);
return ERR_PTR(ret);
}
EXPORT_SYMBOL_GPL(of_amlogic_watchkey_get);
static void devm_watchkey_get_free(void *wk)
{
of_amlogic_watchkey_put(wk);
}
struct amlogic_watchkey *devm_of_amlogic_watchkey_get(struct device *dev)
{
struct amlogic_watchkey *wk;
int ret;
wk = of_amlogic_watchkey_get(dev);
if (IS_ERR(wk))
return wk;
ret = devm_add_action_or_reset(dev, devm_watchkey_get_free, wk);
if (ret)
return ERR_PTR(ret);
return wk;
}
EXPORT_SYMBOL_GPL(devm_of_amlogic_watchkey_get);