Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^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);