blob: 4d06e76ff5e5ca57ba3f8d50e72de3bf8776a23c [file] [log] [blame]
Mark Kettenis97187d52022-01-10 20:58:44 +01001// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright (C) 2021 Mark Kettenis <kettenis@openbsd.org>
4 */
5
6#include <common.h>
7#include <asm/io.h>
8#include <dm.h>
Mark Kettenis81fafbb2022-01-22 20:38:17 +01009#include <dm/device-internal.h>
Mark Kettenis97187d52022-01-10 20:58:44 +010010#include <linux/err.h>
11#include <linux/bitfield.h>
12#include <power-domain-uclass.h>
Mark Kettenis81fafbb2022-01-22 20:38:17 +010013#include <reset-uclass.h>
Mark Kettenis97187d52022-01-10 20:58:44 +010014#include <regmap.h>
15#include <syscon.h>
16
Mark Kettenis81fafbb2022-01-22 20:38:17 +010017#define APPLE_PMGR_RESET BIT(31)
18#define APPLE_PMGR_DEV_DISABLE BIT(10)
19#define APPLE_PMGR_WAS_CLKGATED BIT(9)
20#define APPLE_PMGR_WAS_PWRGATED BIT(8)
Mark Kettenis97187d52022-01-10 20:58:44 +010021#define APPLE_PMGR_PS_ACTUAL GENMASK(7, 4)
Mark Kettenis81fafbb2022-01-22 20:38:17 +010022#define APPLE_PMGR_PS_TARGET GENMASK(3, 0)
23
24#define APPLE_PMGR_FLAGS (APPLE_PMGR_WAS_CLKGATED | APPLE_PMGR_WAS_PWRGATED)
Mark Kettenis97187d52022-01-10 20:58:44 +010025
26#define APPLE_PMGR_PS_ACTIVE 0xf
27#define APPLE_PMGR_PS_PWRGATE 0x0
28
29#define APPLE_PMGR_PS_SET_TIMEOUT_US 100
30
31struct apple_pmgr_priv {
32 struct regmap *regmap;
33 u32 offset; /* offset within regmap for this domain */
34};
35
Mark Kettenis81fafbb2022-01-22 20:38:17 +010036static int apple_reset_of_xlate(struct reset_ctl *reset_ctl,
37 struct ofnode_phandle_args *args)
38{
39 if (args->args_count != 0)
40 return -EINVAL;
41
42 return 0;
43}
44
45static int apple_reset_request(struct reset_ctl *reset_ctl)
46{
47 return 0;
48}
49
50static int apple_reset_free(struct reset_ctl *reset_ctl)
51{
52 return 0;
53}
54
55static int apple_reset_assert(struct reset_ctl *reset_ctl)
56{
57 struct apple_pmgr_priv *priv = dev_get_priv(reset_ctl->dev->parent);
58
59 regmap_update_bits(priv->regmap, priv->offset,
60 APPLE_PMGR_FLAGS | APPLE_PMGR_DEV_DISABLE,
61 APPLE_PMGR_DEV_DISABLE);
62 regmap_update_bits(priv->regmap, priv->offset,
63 APPLE_PMGR_FLAGS | APPLE_PMGR_RESET,
64 APPLE_PMGR_RESET);
65
66 return 0;
67}
68
69static int apple_reset_deassert(struct reset_ctl *reset_ctl)
70{
71 struct apple_pmgr_priv *priv = dev_get_priv(reset_ctl->dev->parent);
72
73 regmap_update_bits(priv->regmap, priv->offset,
74 APPLE_PMGR_FLAGS | APPLE_PMGR_RESET, 0);
75 regmap_update_bits(priv->regmap, priv->offset,
76 APPLE_PMGR_FLAGS | APPLE_PMGR_DEV_DISABLE, 0);
77
78 return 0;
79}
80
81struct reset_ops apple_reset_ops = {
82 .of_xlate = apple_reset_of_xlate,
83 .request = apple_reset_request,
84 .rfree = apple_reset_free,
85 .rst_assert = apple_reset_assert,
86 .rst_deassert = apple_reset_deassert,
87};
88
89static struct driver apple_reset_driver = {
90 .name = "apple_reset",
91 .id = UCLASS_RESET,
92 .ops = &apple_reset_ops,
93};
94
Mark Kettenis97187d52022-01-10 20:58:44 +010095static int apple_pmgr_request(struct power_domain *power_domain)
96{
97 return 0;
98}
99
100static int apple_pmgr_rfree(struct power_domain *power_domain)
101{
102 return 0;
103}
104
105static int apple_pmgr_ps_set(struct power_domain *power_domain, u32 pstate)
106{
107 struct apple_pmgr_priv *priv = dev_get_priv(power_domain->dev);
108 uint reg;
109
110 regmap_update_bits(priv->regmap, priv->offset, APPLE_PMGR_PS_TARGET,
111 FIELD_PREP(APPLE_PMGR_PS_TARGET, pstate));
112
113 return regmap_read_poll_timeout(
114 priv->regmap, priv->offset, reg,
115 (FIELD_GET(APPLE_PMGR_PS_ACTUAL, reg) == pstate), 1,
116 APPLE_PMGR_PS_SET_TIMEOUT_US);
117}
118
119static int apple_pmgr_on(struct power_domain *power_domain)
120{
121 return apple_pmgr_ps_set(power_domain, APPLE_PMGR_PS_ACTIVE);
122}
123
124static int apple_pmgr_off(struct power_domain *power_domain)
125{
126 return 0;
127}
128
129static int apple_pmgr_of_xlate(struct power_domain *power_domain,
130 struct ofnode_phandle_args *args)
131{
132 if (args->args_count != 0) {
133 debug("Invalid args_count: %d\n", args->args_count);
134 return -EINVAL;
135 }
136
137 return 0;
138}
139
140static const struct udevice_id apple_pmgr_ids[] = {
141 { .compatible = "apple,pmgr-pwrstate" },
142 { /* sentinel */ }
143};
144
145static int apple_pmgr_probe(struct udevice *dev)
146{
147 struct apple_pmgr_priv *priv = dev_get_priv(dev);
Mark Kettenis81fafbb2022-01-22 20:38:17 +0100148 struct udevice *child;
Mark Kettenis97187d52022-01-10 20:58:44 +0100149 int ret;
150
151 ret = dev_power_domain_on(dev);
152 if (ret)
153 return ret;
154
155 priv->regmap = syscon_get_regmap(dev->parent);
156 if (IS_ERR(priv->regmap))
157 return PTR_ERR(priv->regmap);
158
159 ret = dev_read_u32(dev, "reg", &priv->offset);
160 if (ret < 0)
161 return ret;
162
Mark Kettenis81fafbb2022-01-22 20:38:17 +0100163 device_bind(dev, &apple_reset_driver, "apple_reset", NULL,
164 dev_ofnode(dev), &child);
165
Mark Kettenis97187d52022-01-10 20:58:44 +0100166 return 0;
167}
168
169struct power_domain_ops apple_pmgr_ops = {
170 .request = apple_pmgr_request,
171 .rfree = apple_pmgr_rfree,
172 .on = apple_pmgr_on,
173 .off = apple_pmgr_off,
174 .of_xlate = apple_pmgr_of_xlate,
175};
176
177U_BOOT_DRIVER(apple_pmgr) = {
178 .name = "apple_pmgr",
179 .id = UCLASS_POWER_DOMAIN,
180 .of_match = apple_pmgr_ids,
181 .ops = &apple_pmgr_ops,
182 .probe = apple_pmgr_probe,
183 .priv_auto = sizeof(struct apple_pmgr_priv),
184};