Blame view
drivers/irqchip/irq-gic-pm.c
3.52 KB
caab277b1 treewide: Replace... |
1 |
// SPDX-License-Identifier: GPL-2.0-only |
9c8edddfc irqchip/gic: Add ... |
2 3 |
/* * Copyright (C) 2016 NVIDIA CORPORATION, All Rights Reserved. |
9c8edddfc irqchip/gic: Add ... |
4 5 6 7 8 9 10 |
*/ #include <linux/module.h> #include <linux/clk.h> #include <linux/of_device.h> #include <linux/of_irq.h> #include <linux/irqchip/arm-gic.h> #include <linux/platform_device.h> |
9c8edddfc irqchip/gic: Add ... |
11 12 13 14 15 16 17 |
#include <linux/pm_runtime.h> #include <linux/slab.h> struct gic_clk_data { unsigned int num_clocks; const char *const *clocks; }; |
fe00f8900 irqchip/gic-pm: U... |
18 19 20 21 22 |
struct gic_chip_pm { struct gic_chip_data *chip_data; const struct gic_clk_data *clk_data; struct clk_bulk_data *clks; }; |
9c8edddfc irqchip/gic: Add ... |
23 24 |
static int gic_runtime_resume(struct device *dev) { |
fe00f8900 irqchip/gic-pm: U... |
25 26 27 |
struct gic_chip_pm *chip_pm = dev_get_drvdata(dev); struct gic_chip_data *gic = chip_pm->chip_data; const struct gic_clk_data *data = chip_pm->clk_data; |
9c8edddfc irqchip/gic: Add ... |
28 |
int ret; |
fe00f8900 irqchip/gic-pm: U... |
29 30 31 32 |
ret = clk_bulk_prepare_enable(data->num_clocks, chip_pm->clks); if (ret) { dev_err(dev, "clk_enable failed: %d ", ret); |
9c8edddfc irqchip/gic: Add ... |
33 |
return ret; |
fe00f8900 irqchip/gic-pm: U... |
34 |
} |
9c8edddfc irqchip/gic: Add ... |
35 36 |
/* |
fe00f8900 irqchip/gic-pm: U... |
37 |
* On the very first resume, the pointer to chip_pm->chip_data |
9c8edddfc irqchip/gic: Add ... |
38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
* will be NULL and this is intentional, because we do not * want to restore the GIC on the very first resume. So if * the pointer is not valid just return. */ if (!gic) return 0; gic_dist_restore(gic); gic_cpu_restore(gic); return 0; } static int gic_runtime_suspend(struct device *dev) { |
fe00f8900 irqchip/gic-pm: U... |
53 54 55 |
struct gic_chip_pm *chip_pm = dev_get_drvdata(dev); struct gic_chip_data *gic = chip_pm->chip_data; const struct gic_clk_data *data = chip_pm->clk_data; |
9c8edddfc irqchip/gic: Add ... |
56 57 58 |
gic_dist_save(gic); gic_cpu_save(gic); |
fe00f8900 irqchip/gic-pm: U... |
59 |
clk_bulk_disable_unprepare(data->num_clocks, chip_pm->clks); |
9c8edddfc irqchip/gic: Add ... |
60 61 |
return 0; |
9c8edddfc irqchip/gic: Add ... |
62 63 64 65 66 67 |
} static int gic_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; const struct gic_clk_data *data; |
fe00f8900 irqchip/gic-pm: U... |
68 69 |
struct gic_chip_pm *chip_pm; int ret, irq, i; |
9c8edddfc irqchip/gic: Add ... |
70 71 72 73 74 75 76 |
data = of_device_get_match_data(&pdev->dev); if (!data) { dev_err(&pdev->dev, "no device match found "); return -ENODEV; } |
fe00f8900 irqchip/gic-pm: U... |
77 78 79 |
chip_pm = devm_kzalloc(dev, sizeof(*chip_pm), GFP_KERNEL); if (!chip_pm) return -ENOMEM; |
9c8edddfc irqchip/gic: Add ... |
80 81 82 83 84 85 |
irq = irq_of_parse_and_map(dev->of_node, 0); if (!irq) { dev_err(dev, "no parent interrupt found! "); return -EINVAL; } |
fe00f8900 irqchip/gic-pm: U... |
86 87 88 89 90 91 92 93 94 |
chip_pm->clks = devm_kcalloc(dev, data->num_clocks, sizeof(*chip_pm->clks), GFP_KERNEL); if (!chip_pm->clks) return -ENOMEM; for (i = 0; i < data->num_clocks; i++) chip_pm->clks[i].id = data->clocks[i]; ret = devm_clk_bulk_get(dev, data->num_clocks, chip_pm->clks); |
9c8edddfc irqchip/gic: Add ... |
95 96 |
if (ret) goto irq_dispose; |
fe00f8900 irqchip/gic-pm: U... |
97 98 |
chip_pm->clk_data = data; dev_set_drvdata(dev, chip_pm); |
9c8edddfc irqchip/gic: Add ... |
99 100 101 102 103 |
pm_runtime_enable(dev); ret = pm_runtime_get_sync(dev); if (ret < 0) goto rpm_disable; |
fe00f8900 irqchip/gic-pm: U... |
104 |
ret = gic_of_init_child(dev, &chip_pm->chip_data, irq); |
9c8edddfc irqchip/gic: Add ... |
105 106 |
if (ret) goto rpm_put; |
9c8edddfc irqchip/gic: Add ... |
107 108 109 110 111 112 113 114 115 116 117 |
pm_runtime_put(dev); dev_info(dev, "GIC IRQ controller registered "); return 0; rpm_put: pm_runtime_put_sync(dev); rpm_disable: pm_runtime_disable(dev); |
9c8edddfc irqchip/gic: Add ... |
118 119 120 121 122 123 124 125 126 |
irq_dispose: irq_dispose_mapping(irq); return ret; } static const struct dev_pm_ops gic_pm_ops = { SET_RUNTIME_PM_OPS(gic_runtime_suspend, gic_runtime_resume, NULL) |
960164f71 irqchip/gic-pm: F... |
127 128 |
SET_LATE_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume) |
9c8edddfc irqchip/gic: Add ... |
129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 |
}; static const char * const gic400_clocks[] = { "clk", }; static const struct gic_clk_data gic400_data = { .num_clocks = ARRAY_SIZE(gic400_clocks), .clocks = gic400_clocks, }; static const struct of_device_id gic_match[] = { { .compatible = "nvidia,tegra210-agic", .data = &gic400_data }, {}, }; MODULE_DEVICE_TABLE(of, gic_match); static struct platform_driver gic_driver = { .probe = gic_probe, .driver = { .name = "gic", .of_match_table = gic_match, .pm = &gic_pm_ops, } }; builtin_platform_driver(gic_driver); |