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