162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only OR MIT
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Apple SoC PMGR device power state driver
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright The Asahi Linux Contributors
662306a36Sopenharmony_ci */
762306a36Sopenharmony_ci
862306a36Sopenharmony_ci#include <linux/bitops.h>
962306a36Sopenharmony_ci#include <linux/bitfield.h>
1062306a36Sopenharmony_ci#include <linux/err.h>
1162306a36Sopenharmony_ci#include <linux/of.h>
1262306a36Sopenharmony_ci#include <linux/of_address.h>
1362306a36Sopenharmony_ci#include <linux/platform_device.h>
1462306a36Sopenharmony_ci#include <linux/pm_domain.h>
1562306a36Sopenharmony_ci#include <linux/regmap.h>
1662306a36Sopenharmony_ci#include <linux/mfd/syscon.h>
1762306a36Sopenharmony_ci#include <linux/reset-controller.h>
1862306a36Sopenharmony_ci#include <linux/module.h>
1962306a36Sopenharmony_ci
2062306a36Sopenharmony_ci#define APPLE_PMGR_RESET        BIT(31)
2162306a36Sopenharmony_ci#define APPLE_PMGR_AUTO_ENABLE  BIT(28)
2262306a36Sopenharmony_ci#define APPLE_PMGR_PS_AUTO      GENMASK(27, 24)
2362306a36Sopenharmony_ci#define APPLE_PMGR_PS_MIN       GENMASK(19, 16)
2462306a36Sopenharmony_ci#define APPLE_PMGR_PARENT_OFF   BIT(11)
2562306a36Sopenharmony_ci#define APPLE_PMGR_DEV_DISABLE  BIT(10)
2662306a36Sopenharmony_ci#define APPLE_PMGR_WAS_CLKGATED BIT(9)
2762306a36Sopenharmony_ci#define APPLE_PMGR_WAS_PWRGATED BIT(8)
2862306a36Sopenharmony_ci#define APPLE_PMGR_PS_ACTUAL    GENMASK(7, 4)
2962306a36Sopenharmony_ci#define APPLE_PMGR_PS_TARGET    GENMASK(3, 0)
3062306a36Sopenharmony_ci
3162306a36Sopenharmony_ci#define APPLE_PMGR_FLAGS        (APPLE_PMGR_WAS_CLKGATED | APPLE_PMGR_WAS_PWRGATED)
3262306a36Sopenharmony_ci
3362306a36Sopenharmony_ci#define APPLE_PMGR_PS_ACTIVE    0xf
3462306a36Sopenharmony_ci#define APPLE_PMGR_PS_CLKGATE   0x4
3562306a36Sopenharmony_ci#define APPLE_PMGR_PS_PWRGATE   0x0
3662306a36Sopenharmony_ci
3762306a36Sopenharmony_ci#define APPLE_PMGR_PS_SET_TIMEOUT 100
3862306a36Sopenharmony_ci#define APPLE_PMGR_RESET_TIME 1
3962306a36Sopenharmony_ci
4062306a36Sopenharmony_cistruct apple_pmgr_ps {
4162306a36Sopenharmony_ci	struct device *dev;
4262306a36Sopenharmony_ci	struct generic_pm_domain genpd;
4362306a36Sopenharmony_ci	struct reset_controller_dev rcdev;
4462306a36Sopenharmony_ci	struct regmap *regmap;
4562306a36Sopenharmony_ci	u32 offset;
4662306a36Sopenharmony_ci	u32 min_state;
4762306a36Sopenharmony_ci};
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_ci#define genpd_to_apple_pmgr_ps(_genpd) container_of(_genpd, struct apple_pmgr_ps, genpd)
5062306a36Sopenharmony_ci#define rcdev_to_apple_pmgr_ps(_rcdev) container_of(_rcdev, struct apple_pmgr_ps, rcdev)
5162306a36Sopenharmony_ci
5262306a36Sopenharmony_cistatic int apple_pmgr_ps_set(struct generic_pm_domain *genpd, u32 pstate, bool auto_enable)
5362306a36Sopenharmony_ci{
5462306a36Sopenharmony_ci	int ret;
5562306a36Sopenharmony_ci	struct apple_pmgr_ps *ps = genpd_to_apple_pmgr_ps(genpd);
5662306a36Sopenharmony_ci	u32 reg;
5762306a36Sopenharmony_ci
5862306a36Sopenharmony_ci	ret = regmap_read(ps->regmap, ps->offset, &reg);
5962306a36Sopenharmony_ci	if (ret < 0)
6062306a36Sopenharmony_ci		return ret;
6162306a36Sopenharmony_ci
6262306a36Sopenharmony_ci	/* Resets are synchronous, and only work if the device is powered and clocked. */
6362306a36Sopenharmony_ci	if (reg & APPLE_PMGR_RESET && pstate != APPLE_PMGR_PS_ACTIVE)
6462306a36Sopenharmony_ci		dev_err(ps->dev, "PS %s: powering off with RESET active\n",
6562306a36Sopenharmony_ci			genpd->name);
6662306a36Sopenharmony_ci
6762306a36Sopenharmony_ci	reg &= ~(APPLE_PMGR_AUTO_ENABLE | APPLE_PMGR_FLAGS | APPLE_PMGR_PS_TARGET);
6862306a36Sopenharmony_ci	reg |= FIELD_PREP(APPLE_PMGR_PS_TARGET, pstate);
6962306a36Sopenharmony_ci
7062306a36Sopenharmony_ci	dev_dbg(ps->dev, "PS %s: pwrstate = 0x%x: 0x%x\n", genpd->name, pstate, reg);
7162306a36Sopenharmony_ci
7262306a36Sopenharmony_ci	regmap_write(ps->regmap, ps->offset, reg);
7362306a36Sopenharmony_ci
7462306a36Sopenharmony_ci	ret = regmap_read_poll_timeout_atomic(
7562306a36Sopenharmony_ci		ps->regmap, ps->offset, reg,
7662306a36Sopenharmony_ci		(FIELD_GET(APPLE_PMGR_PS_ACTUAL, reg) == pstate), 1,
7762306a36Sopenharmony_ci		APPLE_PMGR_PS_SET_TIMEOUT);
7862306a36Sopenharmony_ci	if (ret < 0)
7962306a36Sopenharmony_ci		dev_err(ps->dev, "PS %s: Failed to reach power state 0x%x (now: 0x%x)\n",
8062306a36Sopenharmony_ci			genpd->name, pstate, reg);
8162306a36Sopenharmony_ci
8262306a36Sopenharmony_ci	if (auto_enable) {
8362306a36Sopenharmony_ci		/* Not all devices implement this; this is a no-op where not implemented. */
8462306a36Sopenharmony_ci		reg &= ~APPLE_PMGR_FLAGS;
8562306a36Sopenharmony_ci		reg |= APPLE_PMGR_AUTO_ENABLE;
8662306a36Sopenharmony_ci		regmap_write(ps->regmap, ps->offset, reg);
8762306a36Sopenharmony_ci	}
8862306a36Sopenharmony_ci
8962306a36Sopenharmony_ci	return ret;
9062306a36Sopenharmony_ci}
9162306a36Sopenharmony_ci
9262306a36Sopenharmony_cistatic bool apple_pmgr_ps_is_active(struct apple_pmgr_ps *ps)
9362306a36Sopenharmony_ci{
9462306a36Sopenharmony_ci	u32 reg = 0;
9562306a36Sopenharmony_ci
9662306a36Sopenharmony_ci	regmap_read(ps->regmap, ps->offset, &reg);
9762306a36Sopenharmony_ci	/*
9862306a36Sopenharmony_ci	 * We consider domains as active if they are actually on, or if they have auto-PM
9962306a36Sopenharmony_ci	 * enabled and the intended target is on.
10062306a36Sopenharmony_ci	 */
10162306a36Sopenharmony_ci	return (FIELD_GET(APPLE_PMGR_PS_ACTUAL, reg) == APPLE_PMGR_PS_ACTIVE ||
10262306a36Sopenharmony_ci		(FIELD_GET(APPLE_PMGR_PS_TARGET, reg) == APPLE_PMGR_PS_ACTIVE &&
10362306a36Sopenharmony_ci		 reg & APPLE_PMGR_AUTO_ENABLE));
10462306a36Sopenharmony_ci}
10562306a36Sopenharmony_ci
10662306a36Sopenharmony_cistatic int apple_pmgr_ps_power_on(struct generic_pm_domain *genpd)
10762306a36Sopenharmony_ci{
10862306a36Sopenharmony_ci	return apple_pmgr_ps_set(genpd, APPLE_PMGR_PS_ACTIVE, true);
10962306a36Sopenharmony_ci}
11062306a36Sopenharmony_ci
11162306a36Sopenharmony_cistatic int apple_pmgr_ps_power_off(struct generic_pm_domain *genpd)
11262306a36Sopenharmony_ci{
11362306a36Sopenharmony_ci	return apple_pmgr_ps_set(genpd, APPLE_PMGR_PS_PWRGATE, false);
11462306a36Sopenharmony_ci}
11562306a36Sopenharmony_ci
11662306a36Sopenharmony_cistatic int apple_pmgr_reset_assert(struct reset_controller_dev *rcdev, unsigned long id)
11762306a36Sopenharmony_ci{
11862306a36Sopenharmony_ci	struct apple_pmgr_ps *ps = rcdev_to_apple_pmgr_ps(rcdev);
11962306a36Sopenharmony_ci	unsigned long flags;
12062306a36Sopenharmony_ci
12162306a36Sopenharmony_ci	spin_lock_irqsave(&ps->genpd.slock, flags);
12262306a36Sopenharmony_ci
12362306a36Sopenharmony_ci	if (ps->genpd.status == GENPD_STATE_OFF)
12462306a36Sopenharmony_ci		dev_err(ps->dev, "PS 0x%x: asserting RESET while powered down\n", ps->offset);
12562306a36Sopenharmony_ci
12662306a36Sopenharmony_ci	dev_dbg(ps->dev, "PS 0x%x: assert reset\n", ps->offset);
12762306a36Sopenharmony_ci	/* Quiesce device before asserting reset */
12862306a36Sopenharmony_ci	regmap_update_bits(ps->regmap, ps->offset, APPLE_PMGR_FLAGS | APPLE_PMGR_DEV_DISABLE,
12962306a36Sopenharmony_ci			   APPLE_PMGR_DEV_DISABLE);
13062306a36Sopenharmony_ci	regmap_update_bits(ps->regmap, ps->offset, APPLE_PMGR_FLAGS | APPLE_PMGR_RESET,
13162306a36Sopenharmony_ci			   APPLE_PMGR_RESET);
13262306a36Sopenharmony_ci
13362306a36Sopenharmony_ci	spin_unlock_irqrestore(&ps->genpd.slock, flags);
13462306a36Sopenharmony_ci
13562306a36Sopenharmony_ci	return 0;
13662306a36Sopenharmony_ci}
13762306a36Sopenharmony_ci
13862306a36Sopenharmony_cistatic int apple_pmgr_reset_deassert(struct reset_controller_dev *rcdev, unsigned long id)
13962306a36Sopenharmony_ci{
14062306a36Sopenharmony_ci	struct apple_pmgr_ps *ps = rcdev_to_apple_pmgr_ps(rcdev);
14162306a36Sopenharmony_ci	unsigned long flags;
14262306a36Sopenharmony_ci
14362306a36Sopenharmony_ci	spin_lock_irqsave(&ps->genpd.slock, flags);
14462306a36Sopenharmony_ci
14562306a36Sopenharmony_ci	dev_dbg(ps->dev, "PS 0x%x: deassert reset\n", ps->offset);
14662306a36Sopenharmony_ci	regmap_update_bits(ps->regmap, ps->offset, APPLE_PMGR_FLAGS | APPLE_PMGR_RESET, 0);
14762306a36Sopenharmony_ci	regmap_update_bits(ps->regmap, ps->offset, APPLE_PMGR_FLAGS | APPLE_PMGR_DEV_DISABLE, 0);
14862306a36Sopenharmony_ci
14962306a36Sopenharmony_ci	if (ps->genpd.status == GENPD_STATE_OFF)
15062306a36Sopenharmony_ci		dev_err(ps->dev, "PS 0x%x: RESET was deasserted while powered down\n", ps->offset);
15162306a36Sopenharmony_ci
15262306a36Sopenharmony_ci	spin_unlock_irqrestore(&ps->genpd.slock, flags);
15362306a36Sopenharmony_ci
15462306a36Sopenharmony_ci	return 0;
15562306a36Sopenharmony_ci}
15662306a36Sopenharmony_ci
15762306a36Sopenharmony_cistatic int apple_pmgr_reset_reset(struct reset_controller_dev *rcdev, unsigned long id)
15862306a36Sopenharmony_ci{
15962306a36Sopenharmony_ci	int ret;
16062306a36Sopenharmony_ci
16162306a36Sopenharmony_ci	ret = apple_pmgr_reset_assert(rcdev, id);
16262306a36Sopenharmony_ci	if (ret)
16362306a36Sopenharmony_ci		return ret;
16462306a36Sopenharmony_ci
16562306a36Sopenharmony_ci	usleep_range(APPLE_PMGR_RESET_TIME, 2 * APPLE_PMGR_RESET_TIME);
16662306a36Sopenharmony_ci
16762306a36Sopenharmony_ci	return apple_pmgr_reset_deassert(rcdev, id);
16862306a36Sopenharmony_ci}
16962306a36Sopenharmony_ci
17062306a36Sopenharmony_cistatic int apple_pmgr_reset_status(struct reset_controller_dev *rcdev, unsigned long id)
17162306a36Sopenharmony_ci{
17262306a36Sopenharmony_ci	struct apple_pmgr_ps *ps = rcdev_to_apple_pmgr_ps(rcdev);
17362306a36Sopenharmony_ci	u32 reg = 0;
17462306a36Sopenharmony_ci
17562306a36Sopenharmony_ci	regmap_read(ps->regmap, ps->offset, &reg);
17662306a36Sopenharmony_ci
17762306a36Sopenharmony_ci	return !!(reg & APPLE_PMGR_RESET);
17862306a36Sopenharmony_ci}
17962306a36Sopenharmony_ci
18062306a36Sopenharmony_ciconst struct reset_control_ops apple_pmgr_reset_ops = {
18162306a36Sopenharmony_ci	.assert		= apple_pmgr_reset_assert,
18262306a36Sopenharmony_ci	.deassert	= apple_pmgr_reset_deassert,
18362306a36Sopenharmony_ci	.reset		= apple_pmgr_reset_reset,
18462306a36Sopenharmony_ci	.status		= apple_pmgr_reset_status,
18562306a36Sopenharmony_ci};
18662306a36Sopenharmony_ci
18762306a36Sopenharmony_cistatic int apple_pmgr_reset_xlate(struct reset_controller_dev *rcdev,
18862306a36Sopenharmony_ci				  const struct of_phandle_args *reset_spec)
18962306a36Sopenharmony_ci{
19062306a36Sopenharmony_ci	return 0;
19162306a36Sopenharmony_ci}
19262306a36Sopenharmony_ci
19362306a36Sopenharmony_cistatic int apple_pmgr_ps_probe(struct platform_device *pdev)
19462306a36Sopenharmony_ci{
19562306a36Sopenharmony_ci	struct device *dev = &pdev->dev;
19662306a36Sopenharmony_ci	struct device_node *node = dev->of_node;
19762306a36Sopenharmony_ci	struct apple_pmgr_ps *ps;
19862306a36Sopenharmony_ci	struct regmap *regmap;
19962306a36Sopenharmony_ci	struct of_phandle_iterator it;
20062306a36Sopenharmony_ci	int ret;
20162306a36Sopenharmony_ci	const char *name;
20262306a36Sopenharmony_ci	bool active;
20362306a36Sopenharmony_ci
20462306a36Sopenharmony_ci	regmap = syscon_node_to_regmap(node->parent);
20562306a36Sopenharmony_ci	if (IS_ERR(regmap))
20662306a36Sopenharmony_ci		return PTR_ERR(regmap);
20762306a36Sopenharmony_ci
20862306a36Sopenharmony_ci	ps = devm_kzalloc(dev, sizeof(*ps), GFP_KERNEL);
20962306a36Sopenharmony_ci	if (!ps)
21062306a36Sopenharmony_ci		return -ENOMEM;
21162306a36Sopenharmony_ci
21262306a36Sopenharmony_ci	ps->dev = dev;
21362306a36Sopenharmony_ci	ps->regmap = regmap;
21462306a36Sopenharmony_ci
21562306a36Sopenharmony_ci	ret = of_property_read_string(node, "label", &name);
21662306a36Sopenharmony_ci	if (ret < 0) {
21762306a36Sopenharmony_ci		dev_err(dev, "missing label property\n");
21862306a36Sopenharmony_ci		return ret;
21962306a36Sopenharmony_ci	}
22062306a36Sopenharmony_ci
22162306a36Sopenharmony_ci	ret = of_property_read_u32(node, "reg", &ps->offset);
22262306a36Sopenharmony_ci	if (ret < 0) {
22362306a36Sopenharmony_ci		dev_err(dev, "missing reg property\n");
22462306a36Sopenharmony_ci		return ret;
22562306a36Sopenharmony_ci	}
22662306a36Sopenharmony_ci
22762306a36Sopenharmony_ci	ps->genpd.flags |= GENPD_FLAG_IRQ_SAFE;
22862306a36Sopenharmony_ci	ps->genpd.name = name;
22962306a36Sopenharmony_ci	ps->genpd.power_on = apple_pmgr_ps_power_on;
23062306a36Sopenharmony_ci	ps->genpd.power_off = apple_pmgr_ps_power_off;
23162306a36Sopenharmony_ci
23262306a36Sopenharmony_ci	ret = of_property_read_u32(node, "apple,min-state", &ps->min_state);
23362306a36Sopenharmony_ci	if (ret == 0 && ps->min_state <= APPLE_PMGR_PS_ACTIVE)
23462306a36Sopenharmony_ci		regmap_update_bits(regmap, ps->offset, APPLE_PMGR_FLAGS | APPLE_PMGR_PS_MIN,
23562306a36Sopenharmony_ci				   FIELD_PREP(APPLE_PMGR_PS_MIN, ps->min_state));
23662306a36Sopenharmony_ci
23762306a36Sopenharmony_ci	active = apple_pmgr_ps_is_active(ps);
23862306a36Sopenharmony_ci	if (of_property_read_bool(node, "apple,always-on")) {
23962306a36Sopenharmony_ci		ps->genpd.flags |= GENPD_FLAG_ALWAYS_ON;
24062306a36Sopenharmony_ci		if (!active) {
24162306a36Sopenharmony_ci			dev_warn(dev, "always-on domain %s is not on at boot\n", name);
24262306a36Sopenharmony_ci			/* Turn it on so pm_genpd_init does not fail */
24362306a36Sopenharmony_ci			active = apple_pmgr_ps_power_on(&ps->genpd) == 0;
24462306a36Sopenharmony_ci		}
24562306a36Sopenharmony_ci	}
24662306a36Sopenharmony_ci
24762306a36Sopenharmony_ci	/* Turn on auto-PM if the domain is already on */
24862306a36Sopenharmony_ci	if (active)
24962306a36Sopenharmony_ci		regmap_update_bits(regmap, ps->offset, APPLE_PMGR_FLAGS | APPLE_PMGR_AUTO_ENABLE,
25062306a36Sopenharmony_ci				   APPLE_PMGR_AUTO_ENABLE);
25162306a36Sopenharmony_ci
25262306a36Sopenharmony_ci	ret = pm_genpd_init(&ps->genpd, NULL, !active);
25362306a36Sopenharmony_ci	if (ret < 0) {
25462306a36Sopenharmony_ci		dev_err(dev, "pm_genpd_init failed\n");
25562306a36Sopenharmony_ci		return ret;
25662306a36Sopenharmony_ci	}
25762306a36Sopenharmony_ci
25862306a36Sopenharmony_ci	ret = of_genpd_add_provider_simple(node, &ps->genpd);
25962306a36Sopenharmony_ci	if (ret < 0) {
26062306a36Sopenharmony_ci		dev_err(dev, "of_genpd_add_provider_simple failed\n");
26162306a36Sopenharmony_ci		return ret;
26262306a36Sopenharmony_ci	}
26362306a36Sopenharmony_ci
26462306a36Sopenharmony_ci	of_for_each_phandle(&it, ret, node, "power-domains", "#power-domain-cells", -1) {
26562306a36Sopenharmony_ci		struct of_phandle_args parent, child;
26662306a36Sopenharmony_ci
26762306a36Sopenharmony_ci		parent.np = it.node;
26862306a36Sopenharmony_ci		parent.args_count = of_phandle_iterator_args(&it, parent.args, MAX_PHANDLE_ARGS);
26962306a36Sopenharmony_ci		child.np = node;
27062306a36Sopenharmony_ci		child.args_count = 0;
27162306a36Sopenharmony_ci		ret = of_genpd_add_subdomain(&parent, &child);
27262306a36Sopenharmony_ci
27362306a36Sopenharmony_ci		if (ret == -EPROBE_DEFER) {
27462306a36Sopenharmony_ci			of_node_put(parent.np);
27562306a36Sopenharmony_ci			goto err_remove;
27662306a36Sopenharmony_ci		} else if (ret < 0) {
27762306a36Sopenharmony_ci			dev_err(dev, "failed to add to parent domain: %d (%s -> %s)\n",
27862306a36Sopenharmony_ci				ret, it.node->name, node->name);
27962306a36Sopenharmony_ci			of_node_put(parent.np);
28062306a36Sopenharmony_ci			goto err_remove;
28162306a36Sopenharmony_ci		}
28262306a36Sopenharmony_ci	}
28362306a36Sopenharmony_ci
28462306a36Sopenharmony_ci	/*
28562306a36Sopenharmony_ci	 * Do not participate in regular PM; parent power domains are handled via the
28662306a36Sopenharmony_ci	 * genpd hierarchy.
28762306a36Sopenharmony_ci	 */
28862306a36Sopenharmony_ci	pm_genpd_remove_device(dev);
28962306a36Sopenharmony_ci
29062306a36Sopenharmony_ci	ps->rcdev.owner = THIS_MODULE;
29162306a36Sopenharmony_ci	ps->rcdev.nr_resets = 1;
29262306a36Sopenharmony_ci	ps->rcdev.ops = &apple_pmgr_reset_ops;
29362306a36Sopenharmony_ci	ps->rcdev.of_node = dev->of_node;
29462306a36Sopenharmony_ci	ps->rcdev.of_reset_n_cells = 0;
29562306a36Sopenharmony_ci	ps->rcdev.of_xlate = apple_pmgr_reset_xlate;
29662306a36Sopenharmony_ci
29762306a36Sopenharmony_ci	ret = devm_reset_controller_register(dev, &ps->rcdev);
29862306a36Sopenharmony_ci	if (ret < 0)
29962306a36Sopenharmony_ci		goto err_remove;
30062306a36Sopenharmony_ci
30162306a36Sopenharmony_ci	return 0;
30262306a36Sopenharmony_cierr_remove:
30362306a36Sopenharmony_ci	of_genpd_del_provider(node);
30462306a36Sopenharmony_ci	pm_genpd_remove(&ps->genpd);
30562306a36Sopenharmony_ci	return ret;
30662306a36Sopenharmony_ci}
30762306a36Sopenharmony_ci
30862306a36Sopenharmony_cistatic const struct of_device_id apple_pmgr_ps_of_match[] = {
30962306a36Sopenharmony_ci	{ .compatible = "apple,pmgr-pwrstate" },
31062306a36Sopenharmony_ci	{}
31162306a36Sopenharmony_ci};
31262306a36Sopenharmony_ci
31362306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, apple_pmgr_ps_of_match);
31462306a36Sopenharmony_ci
31562306a36Sopenharmony_cistatic struct platform_driver apple_pmgr_ps_driver = {
31662306a36Sopenharmony_ci	.probe = apple_pmgr_ps_probe,
31762306a36Sopenharmony_ci	.driver = {
31862306a36Sopenharmony_ci		.name = "apple-pmgr-pwrstate",
31962306a36Sopenharmony_ci		.of_match_table = apple_pmgr_ps_of_match,
32062306a36Sopenharmony_ci	},
32162306a36Sopenharmony_ci};
32262306a36Sopenharmony_ci
32362306a36Sopenharmony_ciMODULE_AUTHOR("Hector Martin <marcan@marcan.st>");
32462306a36Sopenharmony_ciMODULE_DESCRIPTION("PMGR power state driver for Apple SoCs");
32562306a36Sopenharmony_ci
32662306a36Sopenharmony_cimodule_platform_driver(apple_pmgr_ps_driver);
327