Lines Matching +full:mpm +full:- +full:pin +full:- +full:count

1 // SPDX-License-Identifier: GPL-2.0-only
4 * Copyright (c) 2010-2020, The Linux Foundation. All rights reserved.
26 * This is the driver for Qualcomm MPM (MSM Power Manager) interrupt controller,
28 * Sitting in always-on domain, MPM monitors the wakeup interrupts when SoC is
30 * doesn't directly access physical MPM registers though. Instead, the access
37 * ownership and dump vMPM into physical MPM registers. On wakeup, AP is woken
38 * up by a MPM pin/interrupt, and RPM will copy STATUS registers into vMPM.
44 * +--------------------------------+
46 * +--------------------------------+
48 * +--------------------------------+
50 * +--------------------------------+
52 * +--------------------------------+
54 * +--------------------------------+
56 * +--------------------------------+
58 * +--------------------------------+
60 * +--------------------------------+
72 /* MPM pin map to GIC hwirq */
74 int pin; member
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() local
113 unsigned int index = pin / 32; in qcom_mpm_enable_irq()
114 unsigned int shift = pin % 32; 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() local
160 unsigned int index = pin / 32; in qcom_mpm_set_type()
161 unsigned int shift = pin % 32; in qcom_mpm_set_type()
178 if (!d->parent_data) in qcom_mpm_set_type()
191 .name = "mpm",
202 static struct mpm_gic_map *get_mpm_gic_map(struct qcom_mpm_priv *priv, int pin) in get_mpm_gic_map() argument
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()
208 if (maps[i].pin == pin) in get_mpm_gic_map()
218 struct qcom_mpm_priv *priv = domain->host_data; in qcom_mpm_alloc()
222 irq_hw_number_t pin; in qcom_mpm_alloc() local
226 ret = irq_domain_translate_twocell(domain, fwspec, &pin, &type); in qcom_mpm_alloc()
230 if (pin == GPIO_NO_WAKE_IRQ) in qcom_mpm_alloc()
233 ret = irq_domain_set_hwirq_and_chip(domain, virq, pin, in qcom_mpm_alloc()
238 map = get_mpm_gic_map(priv, pin); in qcom_mpm_alloc()
240 return irq_domain_disconnect_hierarchy(domain->parent, virq); in qcom_mpm_alloc()
248 parent_fwspec.fwnode = domain->parent->fwnode; in qcom_mpm_alloc()
251 parent_fwspec.param[1] = map->hwirq; in qcom_mpm_alloc()
273 for (i = 0; i < priv->reg_stride; i++) { in qcom_mpm_handler()
274 raw_spin_lock_irqsave(&priv->lock, flags); in qcom_mpm_handler()
278 raw_spin_unlock_irqrestore(&priv->lock, flags); in qcom_mpm_handler()
281 unsigned int pin = 32 * i + j; in qcom_mpm_handler() local
282 struct irq_desc *desc = irq_resolve_mapping(priv->domain, pin); in qcom_mpm_handler()
283 struct irq_data *d = &desc->irq_data; in qcom_mpm_handler()
286 irq_set_irqchip_state(d->irq, in qcom_mpm_handler()
301 for (i = 0; i < priv->reg_stride; i++) in mpm_pd_power_off()
305 ret = mbox_send_message(priv->mbox_chan, NULL); in mpm_pd_power_off()
326 struct device *dev = &pdev->dev; in qcom_mpm_init()
338 return -ENOMEM; in qcom_mpm_init()
340 ret = of_property_read_u32(np, "qcom,mpm-pin-count", &pin_cnt); in qcom_mpm_init()
342 dev_err(dev, "failed to read qcom,mpm-pin-count: %d\n", ret); in qcom_mpm_init()
346 priv->reg_stride = DIV_ROUND_UP(pin_cnt, 32); in qcom_mpm_init()
348 ret = of_property_count_u32_elems(np, "qcom,mpm-pin-map"); in qcom_mpm_init()
350 dev_err(dev, "failed to read qcom,mpm-pin-map: %d\n", ret); in qcom_mpm_init()
355 dev_err(dev, "invalid qcom,mpm-pin-map\n"); in qcom_mpm_init()
356 return -EINVAL; in qcom_mpm_init()
359 priv->map_cnt = ret / 2; in qcom_mpm_init()
360 priv->maps = devm_kcalloc(dev, priv->map_cnt, sizeof(*priv->maps), in qcom_mpm_init()
362 if (!priv->maps) in qcom_mpm_init()
363 return -ENOMEM; in qcom_mpm_init()
365 for (i = 0; i < priv->map_cnt; i++) { in qcom_mpm_init()
366 u32 pin, hwirq; in qcom_mpm_init() local
368 of_property_read_u32_index(np, "qcom,mpm-pin-map", i * 2, &pin); in qcom_mpm_init()
369 of_property_read_u32_index(np, "qcom,mpm-pin-map", i * 2 + 1, &hwirq); in qcom_mpm_init()
371 if (gic_hwirq_is_mapped(priv->maps, i, hwirq)) { in qcom_mpm_init()
372 dev_warn(dev, "failed to map pin %d as GIC hwirq %d is already mapped\n", in qcom_mpm_init()
373 pin, hwirq); in qcom_mpm_init()
377 priv->maps[i].pin = pin; in qcom_mpm_init()
378 priv->maps[i].hwirq = hwirq; in qcom_mpm_init()
381 raw_spin_lock_init(&priv->lock); in qcom_mpm_init()
384 msgram_np = of_parse_phandle(np, "qcom,rpm-msg-ram", 0); in qcom_mpm_init()
393 priv->base = devm_ioremap(dev, res.start, resource_size(&res)); in qcom_mpm_init()
395 if (!priv->base) in qcom_mpm_init()
396 return -ENOMEM; in qcom_mpm_init()
399 priv->base = devm_platform_ioremap_resource(pdev, 0); in qcom_mpm_init()
400 if (IS_ERR(priv->base)) in qcom_mpm_init()
401 return PTR_ERR(priv->base); in qcom_mpm_init()
404 for (i = 0; i < priv->reg_stride; i++) { in qcom_mpm_init()
416 genpd = &priv->genpd; in qcom_mpm_init()
417 genpd->flags = GENPD_FLAG_IRQ_SAFE; in qcom_mpm_init()
418 genpd->power_off = mpm_pd_power_off; in qcom_mpm_init()
420 genpd->name = devm_kasprintf(dev, GFP_KERNEL, "%s", dev_name(dev)); in qcom_mpm_init()
421 if (!genpd->name) in qcom_mpm_init()
422 return -ENOMEM; in qcom_mpm_init()
436 priv->mbox_client.dev = dev; in qcom_mpm_init()
437 priv->mbox_chan = mbox_request_channel(&priv->mbox_client, 0); in qcom_mpm_init()
438 if (IS_ERR(priv->mbox_chan)) { in qcom_mpm_init()
439 ret = PTR_ERR(priv->mbox_chan); in qcom_mpm_init()
446 dev_err(dev, "failed to find MPM parent domain\n"); in qcom_mpm_init()
447 ret = -ENXIO; in qcom_mpm_init()
451 priv->domain = irq_domain_create_hierarchy(parent_domain, in qcom_mpm_init()
454 if (!priv->domain) { in qcom_mpm_init()
455 dev_err(dev, "failed to create MPM domain\n"); in qcom_mpm_init()
456 ret = -ENOMEM; in qcom_mpm_init()
460 irq_domain_update_bus_token(priv->domain, DOMAIN_BUS_WAKEUP); in qcom_mpm_init()
472 irq_domain_remove(priv->domain); in qcom_mpm_init()
474 mbox_free_channel(priv->mbox_chan); in qcom_mpm_init()
481 IRQCHIP_MATCH("qcom,mpm", qcom_mpm_init)