1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (C) 2016 NVIDIA CORPORATION, All Rights Reserved.
5 #include <linux/module.h>
8 #include <linux/of_irq.h>
9 #include <linux/irqchip/arm-gic.h>
10 #include <linux/platform_device.h>
11 #include <linux/pm_runtime.h>
12 #include <linux/slab.h>
15 unsigned int num_clocks
;
16 const char *const *clocks
;
20 struct gic_chip_data
*chip_data
;
21 const struct gic_clk_data
*clk_data
;
22 struct clk_bulk_data
*clks
;
25 static int gic_runtime_resume(struct device
*dev
)
27 struct gic_chip_pm
*chip_pm
= dev_get_drvdata(dev
);
28 struct gic_chip_data
*gic
= chip_pm
->chip_data
;
29 const struct gic_clk_data
*data
= chip_pm
->clk_data
;
32 ret
= clk_bulk_prepare_enable(data
->num_clocks
, chip_pm
->clks
);
37 * On the very first resume, the pointer to chip_pm->chip_data
38 * will be NULL and this is intentional, because we do not
39 * want to restore the GIC on the very first resume. So if
40 * the pointer is not valid just return.
45 gic_dist_restore(gic
);
51 static int gic_runtime_suspend(struct device
*dev
)
53 struct gic_chip_pm
*chip_pm
= dev_get_drvdata(dev
);
54 struct gic_chip_data
*gic
= chip_pm
->chip_data
;
55 const struct gic_clk_data
*data
= chip_pm
->clk_data
;
60 clk_bulk_disable_unprepare(data
->num_clocks
, chip_pm
->clks
);
65 static int gic_probe(struct platform_device
*pdev
)
67 struct device
*dev
= &pdev
->dev
;
68 const struct gic_clk_data
*data
;
69 struct gic_chip_pm
*chip_pm
;
72 data
= of_device_get_match_data(&pdev
->dev
);
74 dev_err(&pdev
->dev
, "no device match found\n");
78 chip_pm
= devm_kzalloc(dev
, sizeof(*chip_pm
), GFP_KERNEL
);
82 irq
= irq_of_parse_and_map(dev
->of_node
, 0);
84 dev_err(dev
, "no parent interrupt found!\n");
88 chip_pm
->clks
= devm_kcalloc(dev
, data
->num_clocks
,
89 sizeof(*chip_pm
->clks
), GFP_KERNEL
);
93 for (i
= 0; i
< data
->num_clocks
; i
++)
94 chip_pm
->clks
[i
].id
= data
->clocks
[i
];
96 ret
= devm_clk_bulk_get(dev
, data
->num_clocks
, chip_pm
->clks
);
100 chip_pm
->clk_data
= data
;
101 dev_set_drvdata(dev
, chip_pm
);
103 pm_runtime_enable(dev
);
105 ret
= pm_runtime_resume_and_get(dev
);
109 ret
= gic_of_init_child(dev
, &chip_pm
->chip_data
, irq
);
115 dev_info(dev
, "GIC IRQ controller registered\n");
120 pm_runtime_put_sync(dev
);
122 pm_runtime_disable(dev
);
124 irq_dispose_mapping(irq
);
129 static const struct dev_pm_ops gic_pm_ops
= {
130 SET_RUNTIME_PM_OPS(gic_runtime_suspend
,
131 gic_runtime_resume
, NULL
)
132 SET_LATE_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend
,
133 pm_runtime_force_resume
)
136 static const char * const gic400_clocks
[] = {
140 static const struct gic_clk_data gic400_data
= {
141 .num_clocks
= ARRAY_SIZE(gic400_clocks
),
142 .clocks
= gic400_clocks
,
145 static const struct of_device_id gic_match
[] = {
146 { .compatible
= "nvidia,tegra210-agic", .data
= &gic400_data
},
149 MODULE_DEVICE_TABLE(of
, gic_match
);
151 static struct platform_driver gic_driver
= {
155 .of_match_table
= gic_match
,
160 builtin_platform_driver(gic_driver
);