• Home
  • Raw
  • Download

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

1 // SPDX-License-Identifier: GPL-2.0-only
4 * Copyright (c) 2010-2020, The Linux Foundation. All rights reserved.
25 * This is the driver for Qualcomm MPM (MSM Power Manager) interrupt controller,
27 * Sitting in always-on domain, MPM monitors the wakeup interrupts when SoC is
29 * doesn't directly access physical MPM registers though. Instead, the access
36 * ownership and dump vMPM into physical MPM registers. On wakeup, AP is woken
37 * up by a MPM pin/interrupt, and RPM will copy STATUS registers into vMPM.
40 * vMPM register map:
43 * +--------------------------------+
45 * +--------------------------------+
47 * +--------------------------------+
49 * +--------------------------------+
51 * +--------------------------------+
53 * +--------------------------------+
55 * +--------------------------------+
57 * +--------------------------------+
59 * +--------------------------------+
71 /* MPM pin map to GIC hwirq */
73 int pin; member
92 unsigned int offset = (reg * priv->reg_stride + index + 2) * 4; in qcom_mpm_read()
94 return readl_relaxed(priv->base + offset); in qcom_mpm_read()
100 unsigned int offset = (reg * priv->reg_stride + index + 2) * 4; in qcom_mpm_write()
102 writel_relaxed(val, priv->base + offset); in qcom_mpm_write()
110 struct qcom_mpm_priv *priv = d->chip_data; in qcom_mpm_enable_irq()
111 int pin = d->hwirq; in qcom_mpm_enable_irq() local
112 unsigned int index = pin / 32; in qcom_mpm_enable_irq()
113 unsigned int shift = pin % 32; in qcom_mpm_enable_irq()
116 raw_spin_lock_irqsave(&priv->lock, flags); in qcom_mpm_enable_irq()
122 raw_spin_unlock_irqrestore(&priv->lock, flags); in qcom_mpm_enable_irq()
129 if (d->parent_data) in qcom_mpm_mask()
137 if (d->parent_data) in qcom_mpm_unmask()
146 raw_spin_lock_irqsave(&priv->lock, flags); in mpm_set_type()
152 raw_spin_unlock_irqrestore(&priv->lock, flags); in mpm_set_type()
157 struct qcom_mpm_priv *priv = d->chip_data; in qcom_mpm_set_type()
158 int pin = d->hwirq; in qcom_mpm_set_type() local
159 unsigned int index = pin / 32; in qcom_mpm_set_type()
160 unsigned int shift = pin % 32; in qcom_mpm_set_type()
177 if (!d->parent_data) in qcom_mpm_set_type()
190 .name = "mpm",
201 static struct mpm_gic_map *get_mpm_gic_map(struct qcom_mpm_priv *priv, int pin) in get_mpm_gic_map() argument
203 struct mpm_gic_map *maps = priv->maps; in get_mpm_gic_map()
206 for (i = 0; i < priv->map_cnt; i++) { in get_mpm_gic_map()
207 if (maps[i].pin == pin) in get_mpm_gic_map()
217 struct qcom_mpm_priv *priv = domain->host_data; in qcom_mpm_alloc()
220 struct mpm_gic_map *map; in qcom_mpm_alloc() local
221 irq_hw_number_t pin; in qcom_mpm_alloc() local
225 ret = irq_domain_translate_twocell(domain, fwspec, &pin, &type); in qcom_mpm_alloc()
229 ret = irq_domain_set_hwirq_and_chip(domain, virq, pin, in qcom_mpm_alloc()
234 map = get_mpm_gic_map(priv, pin); in qcom_mpm_alloc()
235 if (map == NULL) in qcom_mpm_alloc()
236 return irq_domain_disconnect_hierarchy(domain->parent, virq); in qcom_mpm_alloc()
244 parent_fwspec.fwnode = domain->parent->fwnode; in qcom_mpm_alloc()
247 parent_fwspec.param[1] = map->hwirq; in qcom_mpm_alloc()
269 for (i = 0; i < priv->reg_stride; i++) { in qcom_mpm_handler()
270 raw_spin_lock_irqsave(&priv->lock, flags); in qcom_mpm_handler()
274 raw_spin_unlock_irqrestore(&priv->lock, flags); in qcom_mpm_handler()
277 unsigned int pin = 32 * i + j; in qcom_mpm_handler() local
278 struct irq_desc *desc = irq_resolve_mapping(priv->domain, pin); in qcom_mpm_handler()
279 struct irq_data *d = &desc->irq_data; in qcom_mpm_handler()
282 irq_set_irqchip_state(d->irq, in qcom_mpm_handler()
297 for (i = 0; i < priv->reg_stride; i++) in mpm_pd_power_off()
301 ret = mbox_send_message(priv->mbox_chan, NULL); in mpm_pd_power_off()
322 struct device *dev = &pdev->dev; in qcom_mpm_init()
332 return -ENOMEM; in qcom_mpm_init()
334 ret = of_property_read_u32(np, "qcom,mpm-pin-count", &pin_cnt); in qcom_mpm_init()
336 dev_err(dev, "failed to read qcom,mpm-pin-count: %d\n", ret); in qcom_mpm_init()
340 priv->reg_stride = DIV_ROUND_UP(pin_cnt, 32); in qcom_mpm_init()
342 ret = of_property_count_u32_elems(np, "qcom,mpm-pin-map"); in qcom_mpm_init()
344 dev_err(dev, "failed to read qcom,mpm-pin-map: %d\n", ret); in qcom_mpm_init()
349 dev_err(dev, "invalid qcom,mpm-pin-map\n"); in qcom_mpm_init()
350 return -EINVAL; in qcom_mpm_init()
353 priv->map_cnt = ret / 2; in qcom_mpm_init()
354 priv->maps = devm_kcalloc(dev, priv->map_cnt, sizeof(*priv->maps), in qcom_mpm_init()
356 if (!priv->maps) in qcom_mpm_init()
357 return -ENOMEM; in qcom_mpm_init()
359 for (i = 0; i < priv->map_cnt; i++) { in qcom_mpm_init()
360 u32 pin, hwirq; in qcom_mpm_init() local
362 of_property_read_u32_index(np, "qcom,mpm-pin-map", i * 2, &pin); in qcom_mpm_init()
363 of_property_read_u32_index(np, "qcom,mpm-pin-map", i * 2 + 1, &hwirq); in qcom_mpm_init()
365 if (gic_hwirq_is_mapped(priv->maps, i, hwirq)) { in qcom_mpm_init()
366 dev_warn(dev, "failed to map pin %d as GIC hwirq %d is already mapped\n", in qcom_mpm_init()
367 pin, hwirq); in qcom_mpm_init()
371 priv->maps[i].pin = pin; in qcom_mpm_init()
372 priv->maps[i].hwirq = hwirq; in qcom_mpm_init()
375 raw_spin_lock_init(&priv->lock); in qcom_mpm_init()
377 priv->base = devm_platform_ioremap_resource(pdev, 0); in qcom_mpm_init()
378 if (IS_ERR(priv->base)) in qcom_mpm_init()
379 return PTR_ERR(priv->base); in qcom_mpm_init()
381 for (i = 0; i < priv->reg_stride; i++) { in qcom_mpm_init()
393 genpd = &priv->genpd; in qcom_mpm_init()
394 genpd->flags = GENPD_FLAG_IRQ_SAFE; in qcom_mpm_init()
395 genpd->power_off = mpm_pd_power_off; in qcom_mpm_init()
397 genpd->name = devm_kasprintf(dev, GFP_KERNEL, "%s", dev_name(dev)); in qcom_mpm_init()
398 if (!genpd->name) in qcom_mpm_init()
399 return -ENOMEM; in qcom_mpm_init()
413 priv->mbox_client.dev = dev; in qcom_mpm_init()
414 priv->mbox_chan = mbox_request_channel(&priv->mbox_client, 0); in qcom_mpm_init()
415 if (IS_ERR(priv->mbox_chan)) { in qcom_mpm_init()
416 ret = PTR_ERR(priv->mbox_chan); in qcom_mpm_init()
423 dev_err(dev, "failed to find MPM parent domain\n"); in qcom_mpm_init()
424 ret = -ENXIO; in qcom_mpm_init()
428 priv->domain = irq_domain_create_hierarchy(parent_domain, in qcom_mpm_init()
431 if (!priv->domain) { in qcom_mpm_init()
432 dev_err(dev, "failed to create MPM domain\n"); in qcom_mpm_init()
433 ret = -ENOMEM; in qcom_mpm_init()
437 irq_domain_update_bus_token(priv->domain, DOMAIN_BUS_WAKEUP); in qcom_mpm_init()
449 irq_domain_remove(priv->domain); in qcom_mpm_init()
451 mbox_free_channel(priv->mbox_chan); in qcom_mpm_init()
458 IRQCHIP_MATCH("qcom,mpm", qcom_mpm_init)