0001
0002
0003
0004
0005
0006 #include <linux/of.h>
0007 #include <linux/platform_device.h>
0008 #include <linux/pm_domain.h>
0009 #include <linux/slab.h>
0010
0011 #include <soc/tegra/bpmp.h>
0012 #include <soc/tegra/bpmp-abi.h>
0013
0014 struct tegra_powergate_info {
0015 unsigned int id;
0016 char *name;
0017 };
0018
0019 struct tegra_powergate {
0020 struct generic_pm_domain genpd;
0021 struct tegra_bpmp *bpmp;
0022 unsigned int id;
0023 };
0024
0025 static inline struct tegra_powergate *
0026 to_tegra_powergate(struct generic_pm_domain *genpd)
0027 {
0028 return container_of(genpd, struct tegra_powergate, genpd);
0029 }
0030
0031 static int tegra_bpmp_powergate_set_state(struct tegra_bpmp *bpmp,
0032 unsigned int id, u32 state)
0033 {
0034 struct mrq_pg_request request;
0035 struct tegra_bpmp_message msg;
0036 int err;
0037
0038 memset(&request, 0, sizeof(request));
0039 request.cmd = CMD_PG_SET_STATE;
0040 request.id = id;
0041 request.set_state.state = state;
0042
0043 memset(&msg, 0, sizeof(msg));
0044 msg.mrq = MRQ_PG;
0045 msg.tx.data = &request;
0046 msg.tx.size = sizeof(request);
0047
0048 err = tegra_bpmp_transfer(bpmp, &msg);
0049 if (err < 0)
0050 return err;
0051 else if (msg.rx.ret < 0)
0052 return -EINVAL;
0053
0054 return 0;
0055 }
0056
0057 static int tegra_bpmp_powergate_get_state(struct tegra_bpmp *bpmp,
0058 unsigned int id)
0059 {
0060 struct mrq_pg_response response;
0061 struct mrq_pg_request request;
0062 struct tegra_bpmp_message msg;
0063 int err;
0064
0065 memset(&request, 0, sizeof(request));
0066 request.cmd = CMD_PG_GET_STATE;
0067 request.id = id;
0068
0069 memset(&response, 0, sizeof(response));
0070
0071 memset(&msg, 0, sizeof(msg));
0072 msg.mrq = MRQ_PG;
0073 msg.tx.data = &request;
0074 msg.tx.size = sizeof(request);
0075 msg.rx.data = &response;
0076 msg.rx.size = sizeof(response);
0077
0078 err = tegra_bpmp_transfer(bpmp, &msg);
0079 if (err < 0)
0080 return PG_STATE_OFF;
0081 else if (msg.rx.ret < 0)
0082 return -EINVAL;
0083
0084 return response.get_state.state;
0085 }
0086
0087 static int tegra_bpmp_powergate_get_max_id(struct tegra_bpmp *bpmp)
0088 {
0089 struct mrq_pg_response response;
0090 struct mrq_pg_request request;
0091 struct tegra_bpmp_message msg;
0092 int err;
0093
0094 memset(&request, 0, sizeof(request));
0095 request.cmd = CMD_PG_GET_MAX_ID;
0096
0097 memset(&response, 0, sizeof(response));
0098
0099 memset(&msg, 0, sizeof(msg));
0100 msg.mrq = MRQ_PG;
0101 msg.tx.data = &request;
0102 msg.tx.size = sizeof(request);
0103 msg.rx.data = &response;
0104 msg.rx.size = sizeof(response);
0105
0106 err = tegra_bpmp_transfer(bpmp, &msg);
0107 if (err < 0)
0108 return err;
0109 else if (msg.rx.ret < 0)
0110 return -EINVAL;
0111
0112 return response.get_max_id.max_id;
0113 }
0114
0115 static char *tegra_bpmp_powergate_get_name(struct tegra_bpmp *bpmp,
0116 unsigned int id)
0117 {
0118 struct mrq_pg_response response;
0119 struct mrq_pg_request request;
0120 struct tegra_bpmp_message msg;
0121 int err;
0122
0123 memset(&request, 0, sizeof(request));
0124 request.cmd = CMD_PG_GET_NAME;
0125 request.id = id;
0126
0127 memset(&response, 0, sizeof(response));
0128
0129 memset(&msg, 0, sizeof(msg));
0130 msg.mrq = MRQ_PG;
0131 msg.tx.data = &request;
0132 msg.tx.size = sizeof(request);
0133 msg.rx.data = &response;
0134 msg.rx.size = sizeof(response);
0135
0136 err = tegra_bpmp_transfer(bpmp, &msg);
0137 if (err < 0 || msg.rx.ret < 0)
0138 return NULL;
0139
0140 return kstrdup(response.get_name.name, GFP_KERNEL);
0141 }
0142
0143 static inline bool tegra_bpmp_powergate_is_powered(struct tegra_bpmp *bpmp,
0144 unsigned int id)
0145 {
0146 return tegra_bpmp_powergate_get_state(bpmp, id) != PG_STATE_OFF;
0147 }
0148
0149 static int tegra_powergate_power_on(struct generic_pm_domain *domain)
0150 {
0151 struct tegra_powergate *powergate = to_tegra_powergate(domain);
0152 struct tegra_bpmp *bpmp = powergate->bpmp;
0153
0154 return tegra_bpmp_powergate_set_state(bpmp, powergate->id,
0155 PG_STATE_ON);
0156 }
0157
0158 static int tegra_powergate_power_off(struct generic_pm_domain *domain)
0159 {
0160 struct tegra_powergate *powergate = to_tegra_powergate(domain);
0161 struct tegra_bpmp *bpmp = powergate->bpmp;
0162
0163 return tegra_bpmp_powergate_set_state(bpmp, powergate->id,
0164 PG_STATE_OFF);
0165 }
0166
0167 static struct tegra_powergate *
0168 tegra_powergate_add(struct tegra_bpmp *bpmp,
0169 const struct tegra_powergate_info *info)
0170 {
0171 struct tegra_powergate *powergate;
0172 bool off;
0173 int err;
0174
0175 off = !tegra_bpmp_powergate_is_powered(bpmp, info->id);
0176
0177 powergate = devm_kzalloc(bpmp->dev, sizeof(*powergate), GFP_KERNEL);
0178 if (!powergate)
0179 return ERR_PTR(-ENOMEM);
0180
0181 powergate->id = info->id;
0182 powergate->bpmp = bpmp;
0183
0184 powergate->genpd.name = kstrdup(info->name, GFP_KERNEL);
0185 powergate->genpd.power_on = tegra_powergate_power_on;
0186 powergate->genpd.power_off = tegra_powergate_power_off;
0187
0188 err = pm_genpd_init(&powergate->genpd, NULL, off);
0189 if (err < 0) {
0190 kfree(powergate->genpd.name);
0191 return ERR_PTR(err);
0192 }
0193
0194 return powergate;
0195 }
0196
0197 static void tegra_powergate_remove(struct tegra_powergate *powergate)
0198 {
0199 struct generic_pm_domain *genpd = &powergate->genpd;
0200 struct tegra_bpmp *bpmp = powergate->bpmp;
0201 int err;
0202
0203 err = pm_genpd_remove(genpd);
0204 if (err < 0)
0205 dev_err(bpmp->dev, "failed to remove power domain %s: %d\n",
0206 genpd->name, err);
0207
0208 kfree(genpd->name);
0209 }
0210
0211 static int
0212 tegra_bpmp_probe_powergates(struct tegra_bpmp *bpmp,
0213 struct tegra_powergate_info **powergatesp)
0214 {
0215 struct tegra_powergate_info *powergates;
0216 unsigned int max_id, id, count = 0;
0217 unsigned int num_holes = 0;
0218 int err;
0219
0220 err = tegra_bpmp_powergate_get_max_id(bpmp);
0221 if (err < 0)
0222 return err;
0223
0224 max_id = err;
0225
0226 dev_dbg(bpmp->dev, "maximum powergate ID: %u\n", max_id);
0227
0228 powergates = kcalloc(max_id + 1, sizeof(*powergates), GFP_KERNEL);
0229 if (!powergates)
0230 return -ENOMEM;
0231
0232 for (id = 0; id <= max_id; id++) {
0233 struct tegra_powergate_info *info = &powergates[count];
0234
0235 info->name = tegra_bpmp_powergate_get_name(bpmp, id);
0236 if (!info->name || info->name[0] == '\0') {
0237 num_holes++;
0238 continue;
0239 }
0240
0241 info->id = id;
0242 count++;
0243 }
0244
0245 dev_dbg(bpmp->dev, "holes: %u\n", num_holes);
0246
0247 *powergatesp = powergates;
0248
0249 return count;
0250 }
0251
0252 static int tegra_bpmp_add_powergates(struct tegra_bpmp *bpmp,
0253 struct tegra_powergate_info *powergates,
0254 unsigned int count)
0255 {
0256 struct genpd_onecell_data *genpd = &bpmp->genpd;
0257 struct generic_pm_domain **domains;
0258 struct tegra_powergate *powergate;
0259 unsigned int i;
0260 int err;
0261
0262 domains = kcalloc(count, sizeof(*domains), GFP_KERNEL);
0263 if (!domains)
0264 return -ENOMEM;
0265
0266 for (i = 0; i < count; i++) {
0267 powergate = tegra_powergate_add(bpmp, &powergates[i]);
0268 if (IS_ERR(powergate)) {
0269 err = PTR_ERR(powergate);
0270 goto remove;
0271 }
0272
0273 dev_dbg(bpmp->dev, "added power domain %s\n",
0274 powergate->genpd.name);
0275 domains[i] = &powergate->genpd;
0276 }
0277
0278 genpd->num_domains = count;
0279 genpd->domains = domains;
0280
0281 return 0;
0282
0283 remove:
0284 while (i--) {
0285 powergate = to_tegra_powergate(domains[i]);
0286 tegra_powergate_remove(powergate);
0287 }
0288
0289 kfree(genpd->domains);
0290 return err;
0291 }
0292
0293 static void tegra_bpmp_remove_powergates(struct tegra_bpmp *bpmp)
0294 {
0295 struct genpd_onecell_data *genpd = &bpmp->genpd;
0296 unsigned int i = genpd->num_domains;
0297 struct tegra_powergate *powergate;
0298
0299 while (i--) {
0300 dev_dbg(bpmp->dev, "removing power domain %s\n",
0301 genpd->domains[i]->name);
0302 powergate = to_tegra_powergate(genpd->domains[i]);
0303 tegra_powergate_remove(powergate);
0304 }
0305 }
0306
0307 static struct generic_pm_domain *
0308 tegra_powergate_xlate(struct of_phandle_args *spec, void *data)
0309 {
0310 struct generic_pm_domain *domain = ERR_PTR(-ENOENT);
0311 struct genpd_onecell_data *genpd = data;
0312 unsigned int i;
0313
0314 for (i = 0; i < genpd->num_domains; i++) {
0315 struct tegra_powergate *powergate;
0316
0317 powergate = to_tegra_powergate(genpd->domains[i]);
0318 if (powergate->id == spec->args[0]) {
0319 domain = &powergate->genpd;
0320 break;
0321 }
0322 }
0323
0324 return domain;
0325 }
0326
0327 int tegra_bpmp_init_powergates(struct tegra_bpmp *bpmp)
0328 {
0329 struct device_node *np = bpmp->dev->of_node;
0330 struct tegra_powergate_info *powergates;
0331 struct device *dev = bpmp->dev;
0332 unsigned int count, i;
0333 int err;
0334
0335 err = tegra_bpmp_probe_powergates(bpmp, &powergates);
0336 if (err < 0)
0337 return err;
0338
0339 count = err;
0340
0341 dev_dbg(dev, "%u power domains probed\n", count);
0342
0343 err = tegra_bpmp_add_powergates(bpmp, powergates, count);
0344 if (err < 0)
0345 goto free;
0346
0347 bpmp->genpd.xlate = tegra_powergate_xlate;
0348
0349 err = of_genpd_add_provider_onecell(np, &bpmp->genpd);
0350 if (err < 0) {
0351 dev_err(dev, "failed to add power domain provider: %d\n", err);
0352 tegra_bpmp_remove_powergates(bpmp);
0353 }
0354
0355 free:
0356 for (i = 0; i < count; i++)
0357 kfree(powergates[i].name);
0358
0359 kfree(powergates);
0360 return err;
0361 }