162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci *
462306a36Sopenharmony_ci * Authors:
562306a36Sopenharmony_ci * Alexander Aring <aar@pengutronix.de>
662306a36Sopenharmony_ci *
762306a36Sopenharmony_ci * Based on: net/wireless/sysfs.c
862306a36Sopenharmony_ci */
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ci#include <linux/device.h>
1162306a36Sopenharmony_ci#include <linux/rtnetlink.h>
1262306a36Sopenharmony_ci
1362306a36Sopenharmony_ci#include <net/cfg802154.h>
1462306a36Sopenharmony_ci
1562306a36Sopenharmony_ci#include "core.h"
1662306a36Sopenharmony_ci#include "sysfs.h"
1762306a36Sopenharmony_ci#include "rdev-ops.h"
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_cistatic inline struct cfg802154_registered_device *
2062306a36Sopenharmony_cidev_to_rdev(struct device *dev)
2162306a36Sopenharmony_ci{
2262306a36Sopenharmony_ci	return container_of(dev, struct cfg802154_registered_device,
2362306a36Sopenharmony_ci			    wpan_phy.dev);
2462306a36Sopenharmony_ci}
2562306a36Sopenharmony_ci
2662306a36Sopenharmony_ci#define SHOW_FMT(name, fmt, member)					\
2762306a36Sopenharmony_cistatic ssize_t name ## _show(struct device *dev,			\
2862306a36Sopenharmony_ci			     struct device_attribute *attr,		\
2962306a36Sopenharmony_ci			     char *buf)					\
3062306a36Sopenharmony_ci{									\
3162306a36Sopenharmony_ci	return sprintf(buf, fmt "\n", dev_to_rdev(dev)->member);	\
3262306a36Sopenharmony_ci}									\
3362306a36Sopenharmony_cistatic DEVICE_ATTR_RO(name)
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_ciSHOW_FMT(index, "%d", wpan_phy_idx);
3662306a36Sopenharmony_ci
3762306a36Sopenharmony_cistatic ssize_t name_show(struct device *dev,
3862306a36Sopenharmony_ci			 struct device_attribute *attr,
3962306a36Sopenharmony_ci			 char *buf)
4062306a36Sopenharmony_ci{
4162306a36Sopenharmony_ci	struct wpan_phy *wpan_phy = &dev_to_rdev(dev)->wpan_phy;
4262306a36Sopenharmony_ci
4362306a36Sopenharmony_ci	return sprintf(buf, "%s\n", dev_name(&wpan_phy->dev));
4462306a36Sopenharmony_ci}
4562306a36Sopenharmony_cistatic DEVICE_ATTR_RO(name);
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_cistatic void wpan_phy_release(struct device *dev)
4862306a36Sopenharmony_ci{
4962306a36Sopenharmony_ci	struct cfg802154_registered_device *rdev = dev_to_rdev(dev);
5062306a36Sopenharmony_ci
5162306a36Sopenharmony_ci	cfg802154_dev_free(rdev);
5262306a36Sopenharmony_ci}
5362306a36Sopenharmony_ci
5462306a36Sopenharmony_cistatic struct attribute *pmib_attrs[] = {
5562306a36Sopenharmony_ci	&dev_attr_index.attr,
5662306a36Sopenharmony_ci	&dev_attr_name.attr,
5762306a36Sopenharmony_ci	NULL,
5862306a36Sopenharmony_ci};
5962306a36Sopenharmony_ciATTRIBUTE_GROUPS(pmib);
6062306a36Sopenharmony_ci
6162306a36Sopenharmony_ci#ifdef CONFIG_PM_SLEEP
6262306a36Sopenharmony_cistatic int wpan_phy_suspend(struct device *dev)
6362306a36Sopenharmony_ci{
6462306a36Sopenharmony_ci	struct cfg802154_registered_device *rdev = dev_to_rdev(dev);
6562306a36Sopenharmony_ci	int ret = 0;
6662306a36Sopenharmony_ci
6762306a36Sopenharmony_ci	if (rdev->ops->suspend) {
6862306a36Sopenharmony_ci		rtnl_lock();
6962306a36Sopenharmony_ci		ret = rdev_suspend(rdev);
7062306a36Sopenharmony_ci		rtnl_unlock();
7162306a36Sopenharmony_ci	}
7262306a36Sopenharmony_ci
7362306a36Sopenharmony_ci	return ret;
7462306a36Sopenharmony_ci}
7562306a36Sopenharmony_ci
7662306a36Sopenharmony_cistatic int wpan_phy_resume(struct device *dev)
7762306a36Sopenharmony_ci{
7862306a36Sopenharmony_ci	struct cfg802154_registered_device *rdev = dev_to_rdev(dev);
7962306a36Sopenharmony_ci	int ret = 0;
8062306a36Sopenharmony_ci
8162306a36Sopenharmony_ci	if (rdev->ops->resume) {
8262306a36Sopenharmony_ci		rtnl_lock();
8362306a36Sopenharmony_ci		ret = rdev_resume(rdev);
8462306a36Sopenharmony_ci		rtnl_unlock();
8562306a36Sopenharmony_ci	}
8662306a36Sopenharmony_ci
8762306a36Sopenharmony_ci	return ret;
8862306a36Sopenharmony_ci}
8962306a36Sopenharmony_ci
9062306a36Sopenharmony_cistatic SIMPLE_DEV_PM_OPS(wpan_phy_pm_ops, wpan_phy_suspend, wpan_phy_resume);
9162306a36Sopenharmony_ci#define WPAN_PHY_PM_OPS (&wpan_phy_pm_ops)
9262306a36Sopenharmony_ci#else
9362306a36Sopenharmony_ci#define WPAN_PHY_PM_OPS NULL
9462306a36Sopenharmony_ci#endif
9562306a36Sopenharmony_ci
9662306a36Sopenharmony_cistruct class wpan_phy_class = {
9762306a36Sopenharmony_ci	.name = "ieee802154",
9862306a36Sopenharmony_ci	.dev_release = wpan_phy_release,
9962306a36Sopenharmony_ci	.dev_groups = pmib_groups,
10062306a36Sopenharmony_ci	.pm = WPAN_PHY_PM_OPS,
10162306a36Sopenharmony_ci};
10262306a36Sopenharmony_ci
10362306a36Sopenharmony_ciint wpan_phy_sysfs_init(void)
10462306a36Sopenharmony_ci{
10562306a36Sopenharmony_ci	return class_register(&wpan_phy_class);
10662306a36Sopenharmony_ci}
10762306a36Sopenharmony_ci
10862306a36Sopenharmony_civoid wpan_phy_sysfs_exit(void)
10962306a36Sopenharmony_ci{
11062306a36Sopenharmony_ci	class_unregister(&wpan_phy_class);
11162306a36Sopenharmony_ci}
112