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)  * omap_device implementation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  * Copyright (C) 2009-2010 Nokia Corporation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  * Paul Walmsley, Kevin Hilman
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8)  * Developed in collaboration with (alphabetical order): Benoit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9)  * Cousson, Thara Gopinath, Tony Lindgren, Rajendra Nayak, Vikram
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10)  * Pandita, Sakari Poussa, Anand Sawant, Santosh Shilimkar, Richard
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11)  * Woodruff
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13)  * This code provides a consistent interface for OMAP device drivers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14)  * to control power management and interconnect properties of their
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15)  * devices.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17)  * In the medium- to long-term, this code should be implemented as a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18)  * proper omap_bus/omap_device in Linux, no more platform_data func
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19)  * pointers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) #undef DEBUG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) #include <linux/err.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) #include <linux/clk.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) #include <linux/clkdev.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) #include <linux/pm_domain.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) #include <linux/pm_runtime.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) #include <linux/of.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) #include <linux/of_address.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) #include <linux/of_irq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) #include <linux/notifier.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) #include "common.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) #include "soc.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) #include "omap_device.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) #include "omap_hwmod.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) /* Private functions */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) static void _add_clkdev(struct omap_device *od, const char *clk_alias,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) 		       const char *clk_name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) 	struct clk *r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) 	int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) 	if (!clk_alias || !clk_name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 	dev_dbg(&od->pdev->dev, "Creating %s -> %s\n", clk_alias, clk_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) 	r = clk_get_sys(dev_name(&od->pdev->dev), clk_alias);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) 	if (!IS_ERR(r)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 		dev_dbg(&od->pdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 			 "alias %s already exists\n", clk_alias);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) 		clk_put(r);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) 	r = clk_get_sys(NULL, clk_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 	if (IS_ERR(r)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 		struct of_phandle_args clkspec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 		clkspec.np = of_find_node_by_name(NULL, clk_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) 		r = of_clk_get_from_provider(&clkspec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 		rc = clk_register_clkdev(r, clk_alias,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 					 dev_name(&od->pdev->dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) 		rc = clk_add_alias(clk_alias, dev_name(&od->pdev->dev),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 				   clk_name, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 	if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 		if (rc == -ENODEV || rc == -ENOMEM)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 			dev_err(&od->pdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 				"clkdev_alloc for %s failed\n", clk_alias);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 			dev_err(&od->pdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 				"clk_get for %s failed\n", clk_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) }
^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)  * _add_hwmod_clocks_clkdev - Add clkdev entry for hwmod optional clocks
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91)  * and main clock
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92)  * @od: struct omap_device *od
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93)  * @oh: struct omap_hwmod *oh
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95)  * For the main clock and every optional clock present per hwmod per
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96)  * omap_device, this function adds an entry in the clkdev table of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97)  * form <dev-id=dev_name, con-id=role> if it does not exist already.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99)  * The function is called from inside omap_device_build_ss(), after
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)  * omap_device_register.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)  * This allows drivers to get a pointer to its optional clocks based on its role
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103)  * by calling clk_get(<dev*>, <role>).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)  * In the case of the main clock, a "fck" alias is used.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)  * No return value.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) static void _add_hwmod_clocks_clkdev(struct omap_device *od,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 				     struct omap_hwmod *oh)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 	_add_clkdev(od, "fck", oh->main_clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 	for (i = 0; i < oh->opt_clks_cnt; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 		_add_clkdev(od, oh->opt_clks[i].role, oh->opt_clks[i].clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)  * omap_device_build_from_dt - build an omap_device with multiple hwmods
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)  * @pdev: The platform device to update.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)  * Function for building an omap_device already registered from device-tree
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126)  * Returns 0 or PTR_ERR() on error.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) static int omap_device_build_from_dt(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 	struct omap_hwmod **hwmods;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 	struct omap_device *od;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 	struct omap_hwmod *oh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 	struct device_node *node = pdev->dev.of_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 	struct resource res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 	const char *oh_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 	int oh_cnt, i, ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 	bool device_active = false, skip_pm_domain = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 	oh_cnt = of_property_count_strings(node, "ti,hwmods");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 	if (oh_cnt <= 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 		dev_dbg(&pdev->dev, "No 'hwmods' to build omap_device\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 		return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 	/* SDMA still needs special handling for omap_device_build() */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 	ret = of_property_read_string_index(node, "ti,hwmods", 0, &oh_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 	if (!ret && (!strncmp("dma_system", oh_name, 10) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 		     !strncmp("dma", oh_name, 3)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 		skip_pm_domain = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 	/* Use ti-sysc driver instead of omap_device? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 	if (!skip_pm_domain &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 	    !omap_hwmod_parse_module_range(NULL, node, &res))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 		return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 	hwmods = kcalloc(oh_cnt, sizeof(struct omap_hwmod *), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 	if (!hwmods) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 		ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 		goto odbfd_exit;
^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) 	for (i = 0; i < oh_cnt; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 		of_property_read_string_index(node, "ti,hwmods", i, &oh_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 		oh = omap_hwmod_lookup(oh_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 		if (!oh) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 			dev_err(&pdev->dev, "Cannot lookup hwmod '%s'\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 				oh_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 			ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 			goto odbfd_exit1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 		hwmods[i] = oh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 		if (oh->flags & HWMOD_INIT_NO_IDLE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 			device_active = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 	od = omap_device_alloc(pdev, hwmods, oh_cnt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 	if (IS_ERR(od)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 		dev_err(&pdev->dev, "Cannot allocate omap_device for :%s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 			oh_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 		ret = PTR_ERR(od);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 		goto odbfd_exit1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) 	/* Fix up missing resource names */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 	for (i = 0; i < pdev->num_resources; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) 		struct resource *r = &pdev->resource[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 		if (r->name == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 			r->name = dev_name(&pdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 	if (!skip_pm_domain) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 		dev_pm_domain_set(&pdev->dev, &omap_device_pm_domain);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 		if (device_active) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 			omap_device_enable(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) 			pm_runtime_set_active(&pdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) odbfd_exit1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) 	kfree(hwmods);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) odbfd_exit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) 	/* if data/we are at fault.. load up a fail handler */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) 		dev_pm_domain_set(&pdev->dev, &omap_device_fail_pm_domain);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) static int _omap_device_notifier_call(struct notifier_block *nb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) 				      unsigned long event, void *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) 	struct platform_device *pdev = to_platform_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) 	struct omap_device *od;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) 	int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) 	switch (event) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) 	case BUS_NOTIFY_REMOVED_DEVICE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) 		if (pdev->archdata.od)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) 			omap_device_delete(pdev->archdata.od);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) 	case BUS_NOTIFY_UNBOUND_DRIVER:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) 		od = to_omap_device(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) 		if (od && (od->_state == OMAP_DEVICE_STATE_ENABLED)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) 			dev_info(dev, "enabled after unload, idling\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) 			err = omap_device_idle(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) 			if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) 				dev_err(dev, "failed to idle\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) 	case BUS_NOTIFY_BIND_DRIVER:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) 		od = to_omap_device(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) 		if (od) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) 			od->_driver_status = BUS_NOTIFY_BIND_DRIVER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) 			if (od->_state == OMAP_DEVICE_STATE_ENABLED &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) 			    pm_runtime_status_suspended(dev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) 				pm_runtime_set_active(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) 	case BUS_NOTIFY_ADD_DEVICE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) 		if (pdev->dev.of_node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) 			omap_device_build_from_dt(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) 		omap_auxdata_legacy_init(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) 		fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) 		od = to_omap_device(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) 		if (od)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) 			od->_driver_status = event;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) 	return NOTIFY_DONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256)  * _omap_device_enable_hwmods - call omap_hwmod_enable() on all hwmods
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257)  * @od: struct omap_device *od
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259)  * Enable all underlying hwmods.  Returns 0.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) static int _omap_device_enable_hwmods(struct omap_device *od)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) 	int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) 	for (i = 0; i < od->hwmods_cnt; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) 		ret |= omap_hwmod_enable(od->hwmods[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273)  * _omap_device_idle_hwmods - call omap_hwmod_idle() on all hwmods
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274)  * @od: struct omap_device *od
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276)  * Idle all underlying hwmods.  Returns 0.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) static int _omap_device_idle_hwmods(struct omap_device *od)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) 	int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) 	for (i = 0; i < od->hwmods_cnt; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) 		ret |= omap_hwmod_idle(od->hwmods[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) /* Public functions for use by core code */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292)  * omap_device_get_context_loss_count - get lost context count
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293)  * @pdev: The platform device to update.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295)  * Using the primary hwmod, query the context loss count for this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296)  * device.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298)  * Callers should consider context for this device lost any time this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299)  * function returns a value different than the value the caller got
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300)  * the last time it called this function.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302)  * If any hwmods exist for the omap_device associated with @pdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303)  * return the context loss counter for that hwmod, otherwise return
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304)  * zero.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) int omap_device_get_context_loss_count(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) 	struct omap_device *od;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) 	u32 ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) 	od = to_omap_device(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) 	if (od->hwmods_cnt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) 		ret = omap_hwmod_get_context_loss_count(od->hwmods[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320)  * omap_device_alloc - allocate an omap_device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321)  * @pdev: platform_device that will be included in this omap_device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322)  * @ohs: ptr to the omap_hwmod for this omap_device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323)  * @oh_cnt: the size of the ohs list
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325)  * Convenience function for allocating an omap_device structure and filling
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326)  * hwmods, and resources.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328)  * Returns an struct omap_device pointer or ERR_PTR() on error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) struct omap_device *omap_device_alloc(struct platform_device *pdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) 					struct omap_hwmod **ohs, int oh_cnt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) 	int ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) 	struct omap_device *od;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) 	struct omap_hwmod **hwmods;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) 	od = kzalloc(sizeof(struct omap_device), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) 	if (!od) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) 		ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) 		goto oda_exit1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) 	od->hwmods_cnt = oh_cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) 	hwmods = kmemdup(ohs, sizeof(struct omap_hwmod *) * oh_cnt, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) 	if (!hwmods)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) 		goto oda_exit2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) 	od->hwmods = hwmods;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) 	od->pdev = pdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) 	pdev->archdata.od = od;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) 	for (i = 0; i < oh_cnt; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) 		hwmods[i]->od = od;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) 		_add_hwmod_clocks_clkdev(od, hwmods[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) 	return od;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) oda_exit2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) 	kfree(od);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) oda_exit1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) 	dev_err(&pdev->dev, "omap_device: build failed (%d)\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) 	return ERR_PTR(ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) void omap_device_delete(struct omap_device *od)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) 	if (!od)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) 	od->pdev->archdata.od = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) 	kfree(od->hwmods);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) 	kfree(od);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) #ifdef CONFIG_PM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) static int _od_runtime_suspend(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) 	struct platform_device *pdev = to_platform_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) 	ret = pm_generic_runtime_suspend(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) 	return omap_device_idle(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) static int _od_runtime_resume(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) 	struct platform_device *pdev = to_platform_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) 	ret = omap_device_enable(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) 	if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) 		dev_err(dev, "use pm_runtime_put_sync_suspend() in driver?\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) 	return pm_generic_runtime_resume(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) static int _od_fail_runtime_suspend(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) 	dev_warn(dev, "%s: FIXME: missing hwmod/omap_dev info\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) 	return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) static int _od_fail_runtime_resume(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) 	dev_warn(dev, "%s: FIXME: missing hwmod/omap_dev info\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) 	return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) #ifdef CONFIG_SUSPEND
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) static int _od_suspend_noirq(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) 	struct platform_device *pdev = to_platform_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) 	struct omap_device *od = to_omap_device(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) 	/* Don't attempt late suspend on a driver that is not bound */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) 	if (od->_driver_status != BUS_NOTIFY_BOUND_DRIVER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) 	ret = pm_generic_suspend_noirq(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) 	if (!ret && !pm_runtime_status_suspended(dev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) 		if (pm_generic_runtime_suspend(dev) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) 			omap_device_idle(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) 			od->flags |= OMAP_DEVICE_SUSPENDED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) static int _od_resume_noirq(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) 	struct platform_device *pdev = to_platform_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) 	struct omap_device *od = to_omap_device(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) 	if (od->flags & OMAP_DEVICE_SUSPENDED) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) 		od->flags &= ~OMAP_DEVICE_SUSPENDED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) 		omap_device_enable(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) 		pm_generic_runtime_resume(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) 	return pm_generic_resume_noirq(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) #define _od_suspend_noirq NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) #define _od_resume_noirq NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) struct dev_pm_domain omap_device_fail_pm_domain = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) 	.ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) 		SET_RUNTIME_PM_OPS(_od_fail_runtime_suspend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) 				   _od_fail_runtime_resume, NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) struct dev_pm_domain omap_device_pm_domain = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) 	.ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) 		SET_RUNTIME_PM_OPS(_od_runtime_suspend, _od_runtime_resume,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) 				   NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) 		USE_PLATFORM_PM_SLEEP_OPS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) 		SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(_od_suspend_noirq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) 					      _od_resume_noirq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478)  * omap_device_register - register an omap_device with one omap_hwmod
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479)  * @pdev: the platform device (omap_device) to register.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481)  * Register the omap_device structure.  This currently just calls
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482)  * platform_device_register() on the underlying platform_device.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483)  * Returns the return value of platform_device_register().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) int omap_device_register(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) 	pr_debug("omap_device: %s: registering\n", pdev->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) 	dev_pm_domain_set(&pdev->dev, &omap_device_pm_domain);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) 	return platform_device_add(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) /* Public functions for use by device drivers through struct platform_data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497)  * omap_device_enable - fully activate an omap_device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498)  * @pdev: the platform device to activate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500)  * Do whatever is necessary for the hwmods underlying omap_device @od
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501)  * to be accessible and ready to operate.  This generally involves
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502)  * enabling clocks, setting SYSCONFIG registers; and in the future may
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503)  * involve remuxing pins.  Device drivers should call this function
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504)  * indirectly via pm_runtime_get*().  Returns -EINVAL if called when
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505)  * the omap_device is already enabled, or passes along the return
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506)  * value of _omap_device_enable_hwmods().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) int omap_device_enable(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) 	struct omap_device *od;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) 	od = to_omap_device(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) 	if (od->_state == OMAP_DEVICE_STATE_ENABLED) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) 		dev_warn(&pdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) 			 "omap_device: %s() called from invalid state %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) 			 __func__, od->_state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) 	ret = _omap_device_enable_hwmods(od);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) 	if (ret == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) 		od->_state = OMAP_DEVICE_STATE_ENABLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531)  * omap_device_idle - idle an omap_device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532)  * @pdev: The platform_device (omap_device) to idle
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534)  * Idle omap_device @od.  Device drivers call this function indirectly
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535)  * via pm_runtime_put*().  Returns -EINVAL if the omap_device is not
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536)  * currently enabled, or passes along the return value of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537)  * _omap_device_idle_hwmods().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) int omap_device_idle(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) 	struct omap_device *od;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) 	od = to_omap_device(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) 	if (od->_state != OMAP_DEVICE_STATE_ENABLED) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) 		dev_warn(&pdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) 			 "omap_device: %s() called from invalid state %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) 			 __func__, od->_state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) 	ret = _omap_device_idle_hwmods(od);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) 	if (ret == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) 		od->_state = OMAP_DEVICE_STATE_IDLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562)  * omap_device_assert_hardreset - set a device's hardreset line
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563)  * @pdev: struct platform_device * to reset
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564)  * @name: const char * name of the reset line
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566)  * Set the hardreset line identified by @name on the IP blocks
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567)  * associated with the hwmods backing the platform_device @pdev.  All
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568)  * of the hwmods associated with @pdev must have the same hardreset
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569)  * line linked to them for this to work.  Passes along the return value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570)  * of omap_hwmod_assert_hardreset() in the event of any failure, or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571)  * returns 0 upon success.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) int omap_device_assert_hardreset(struct platform_device *pdev, const char *name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) 	struct omap_device *od = to_omap_device(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) 	int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) 	for (i = 0; i < od->hwmods_cnt; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) 		ret = omap_hwmod_assert_hardreset(od->hwmods[i], name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) 		if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589)  * omap_device_deassert_hardreset - release a device's hardreset line
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590)  * @pdev: struct platform_device * to reset
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591)  * @name: const char * name of the reset line
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593)  * Release the hardreset line identified by @name on the IP blocks
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594)  * associated with the hwmods backing the platform_device @pdev.  All
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595)  * of the hwmods associated with @pdev must have the same hardreset
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596)  * line linked to them for this to work.  Passes along the return
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597)  * value of omap_hwmod_deassert_hardreset() in the event of any
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598)  * failure, or returns 0 upon success.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) int omap_device_deassert_hardreset(struct platform_device *pdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) 				   const char *name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) 	struct omap_device *od = to_omap_device(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) 	int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) 	for (i = 0; i < od->hwmods_cnt; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) 		ret = omap_hwmod_deassert_hardreset(od->hwmods[i], name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) 		if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617)  * omap_device_get_by_hwmod_name() - convert a hwmod name to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618)  * device pointer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619)  * @oh_name: name of the hwmod device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621)  * Returns back a struct device * pointer associated with a hwmod
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622)  * device represented by a hwmod_name
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) struct device *omap_device_get_by_hwmod_name(const char *oh_name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) 	struct omap_hwmod *oh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) 	if (!oh_name) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) 		WARN(1, "%s: no hwmod name!\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) 		return ERR_PTR(-EINVAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) 	oh = omap_hwmod_lookup(oh_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) 	if (!oh) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) 		WARN(1, "%s: no hwmod for %s\n", __func__,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) 			oh_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) 		return ERR_PTR(-ENODEV);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) 	if (!oh->od) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) 		WARN(1, "%s: no omap_device for %s\n", __func__,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) 			oh_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) 		return ERR_PTR(-ENODEV);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) 	return &oh->od->pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) static struct notifier_block platform_nb = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) 	.notifier_call = _omap_device_notifier_call,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) static int __init omap_device_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) 	bus_register_notifier(&platform_bus_type, &platform_nb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) omap_postcore_initcall(omap_device_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660)  * omap_device_late_idle - idle devices without drivers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661)  * @dev: struct device * associated with omap_device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662)  * @data: unused
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664)  * Check the driver bound status of this device, and idle it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665)  * if there is no driver attached.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) static int __init omap_device_late_idle(struct device *dev, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) 	struct platform_device *pdev = to_platform_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) 	struct omap_device *od = to_omap_device(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) 	if (!od)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) 	 * If omap_device state is enabled, but has no driver bound,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) 	 * idle it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) 	 * Some devices (like memory controllers) are always kept
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) 	 * enabled, and should not be idled even with no drivers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) 	for (i = 0; i < od->hwmods_cnt; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) 		if (od->hwmods[i]->flags & HWMOD_INIT_NO_IDLE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) 			return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) 	if (od->_driver_status != BUS_NOTIFY_BOUND_DRIVER &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) 	    od->_driver_status != BUS_NOTIFY_BIND_DRIVER) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) 		if (od->_state == OMAP_DEVICE_STATE_ENABLED) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) 			dev_warn(dev, "%s: enabled but no driver.  Idling\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) 				 __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) 			omap_device_idle(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) static int __init omap_device_late_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) 	bus_for_each_dev(&platform_bus_type, NULL, NULL, omap_device_late_idle);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) omap_late_initcall_sync(omap_device_late_init);