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