Lines Matching +full:rpm +full:- +full:msg +full:- +full:ram

1 // SPDX-License-Identifier: GPL-2.0-only
4 * Copyright (c) 2010-2020, The Linux Foundation. All rights reserved.
27 * which is commonly found on Qualcomm SoCs built on the RPM architecture.
28 * Sitting in always-on domain, MPM monitors the wakeup interrupts when SoC is
32 * AP and RPM. This piece of memory is called 'vMPM' in the driver.
36 * driver sends a mailbox notification to RPM, which will take over the vMPM
38 * up by a MPM pin/interrupt, and RPM will copy STATUS registers into vMPM.
44 * +--------------------------------+
46 * +--------------------------------+
48 * +--------------------------------+
50 * +--------------------------------+
52 * +--------------------------------+
54 * +--------------------------------+
56 * +--------------------------------+
58 * +--------------------------------+
60 * +--------------------------------+
93 unsigned int offset = (reg * priv->reg_stride + index + 2) * 4; in qcom_mpm_read()
95 return readl_relaxed(priv->base + offset); in qcom_mpm_read()
101 unsigned int offset = (reg * priv->reg_stride + index + 2) * 4; in qcom_mpm_write()
103 writel_relaxed(val, priv->base + offset); in qcom_mpm_write()
111 struct qcom_mpm_priv *priv = d->chip_data; in qcom_mpm_enable_irq()
112 int pin = d->hwirq; in qcom_mpm_enable_irq()
117 raw_spin_lock_irqsave(&priv->lock, flags); in qcom_mpm_enable_irq()
123 raw_spin_unlock_irqrestore(&priv->lock, flags); in qcom_mpm_enable_irq()
130 if (d->parent_data) in qcom_mpm_mask()
138 if (d->parent_data) in qcom_mpm_unmask()
147 raw_spin_lock_irqsave(&priv->lock, flags); in mpm_set_type()
153 raw_spin_unlock_irqrestore(&priv->lock, flags); in mpm_set_type()
158 struct qcom_mpm_priv *priv = d->chip_data; in qcom_mpm_set_type()
159 int pin = d->hwirq; in qcom_mpm_set_type()
178 if (!d->parent_data) in qcom_mpm_set_type()
204 struct mpm_gic_map *maps = priv->maps; in get_mpm_gic_map()
207 for (i = 0; i < priv->map_cnt; i++) { in get_mpm_gic_map()
218 struct qcom_mpm_priv *priv = domain->host_data; in qcom_mpm_alloc()
237 return irq_domain_disconnect_hierarchy(domain->parent, virq); in qcom_mpm_alloc()
245 parent_fwspec.fwnode = domain->parent->fwnode; in qcom_mpm_alloc()
248 parent_fwspec.param[1] = map->hwirq; in qcom_mpm_alloc()
261 /* Triggered by RPM when system resumes from deep sleep */
270 for (i = 0; i < priv->reg_stride; i++) { in qcom_mpm_handler()
271 raw_spin_lock_irqsave(&priv->lock, flags); in qcom_mpm_handler()
275 raw_spin_unlock_irqrestore(&priv->lock, flags); in qcom_mpm_handler()
279 struct irq_desc *desc = irq_resolve_mapping(priv->domain, pin); in qcom_mpm_handler()
280 struct irq_data *d = &desc->irq_data; in qcom_mpm_handler()
283 irq_set_irqchip_state(d->irq, in qcom_mpm_handler()
298 for (i = 0; i < priv->reg_stride; i++) in mpm_pd_power_off()
301 /* Notify RPM to write vMPM into HW */ in mpm_pd_power_off()
302 ret = mbox_send_message(priv->mbox_chan, NULL); in mpm_pd_power_off()
323 struct device *dev = &pdev->dev; in qcom_mpm_init()
335 return -ENOMEM; in qcom_mpm_init()
337 ret = of_property_read_u32(np, "qcom,mpm-pin-count", &pin_cnt); in qcom_mpm_init()
339 dev_err(dev, "failed to read qcom,mpm-pin-count: %d\n", ret); in qcom_mpm_init()
343 priv->reg_stride = DIV_ROUND_UP(pin_cnt, 32); in qcom_mpm_init()
345 ret = of_property_count_u32_elems(np, "qcom,mpm-pin-map"); in qcom_mpm_init()
347 dev_err(dev, "failed to read qcom,mpm-pin-map: %d\n", ret); in qcom_mpm_init()
352 dev_err(dev, "invalid qcom,mpm-pin-map\n"); in qcom_mpm_init()
353 return -EINVAL; in qcom_mpm_init()
356 priv->map_cnt = ret / 2; in qcom_mpm_init()
357 priv->maps = devm_kcalloc(dev, priv->map_cnt, sizeof(*priv->maps), in qcom_mpm_init()
359 if (!priv->maps) in qcom_mpm_init()
360 return -ENOMEM; in qcom_mpm_init()
362 for (i = 0; i < priv->map_cnt; i++) { in qcom_mpm_init()
365 of_property_read_u32_index(np, "qcom,mpm-pin-map", i * 2, &pin); in qcom_mpm_init()
366 of_property_read_u32_index(np, "qcom,mpm-pin-map", i * 2 + 1, &hwirq); in qcom_mpm_init()
368 if (gic_hwirq_is_mapped(priv->maps, i, hwirq)) { in qcom_mpm_init()
374 priv->maps[i].pin = pin; in qcom_mpm_init()
375 priv->maps[i].hwirq = hwirq; in qcom_mpm_init()
378 raw_spin_lock_init(&priv->lock); in qcom_mpm_init()
380 /* If we have a handle to an RPM message ram partition, use it. */ in qcom_mpm_init()
381 msgram_np = of_parse_phandle(np, "qcom,rpm-msg-ram", 0); in qcom_mpm_init()
390 priv->base = devm_ioremap(dev, res.start, resource_size(&res)); in qcom_mpm_init()
392 if (!priv->base) in qcom_mpm_init()
393 return -ENOMEM; in qcom_mpm_init()
396 priv->base = devm_platform_ioremap_resource(pdev, 0); in qcom_mpm_init()
397 if (IS_ERR(priv->base)) in qcom_mpm_init()
398 return PTR_ERR(priv->base); in qcom_mpm_init()
401 for (i = 0; i < priv->reg_stride; i++) { in qcom_mpm_init()
413 genpd = &priv->genpd; in qcom_mpm_init()
414 genpd->flags = GENPD_FLAG_IRQ_SAFE; in qcom_mpm_init()
415 genpd->power_off = mpm_pd_power_off; in qcom_mpm_init()
417 genpd->name = devm_kasprintf(dev, GFP_KERNEL, "%s", dev_name(dev)); in qcom_mpm_init()
418 if (!genpd->name) in qcom_mpm_init()
419 return -ENOMEM; in qcom_mpm_init()
433 priv->mbox_client.dev = dev; in qcom_mpm_init()
434 priv->mbox_chan = mbox_request_channel(&priv->mbox_client, 0); in qcom_mpm_init()
435 if (IS_ERR(priv->mbox_chan)) { in qcom_mpm_init()
436 ret = PTR_ERR(priv->mbox_chan); in qcom_mpm_init()
444 ret = -ENXIO; in qcom_mpm_init()
448 priv->domain = irq_domain_create_hierarchy(parent_domain, in qcom_mpm_init()
451 if (!priv->domain) { in qcom_mpm_init()
453 ret = -ENOMEM; in qcom_mpm_init()
457 irq_domain_update_bus_token(priv->domain, DOMAIN_BUS_WAKEUP); in qcom_mpm_init()
469 irq_domain_remove(priv->domain); in qcom_mpm_init()
471 mbox_free_channel(priv->mbox_chan); in qcom_mpm_init()