xref: /linux/drivers/memory/tegra/tegra-emc-common.c (revision 0eaed89c18aeedf0898baf2dbf5ff027c6795152)
1 // SPDX-License-Identifier: GPL-2.0
2 
3 #include <linux/device.h>
4 #include <linux/module.h>
5 #include <linux/mutex.h>
6 #include <linux/pm_opp.h>
7 
8 #include "tegra-emc-common.h"
9 
10 /**
11  * tegra_emc_rate_requests_init() - Initialize EMC rate request tracking
12  * @reqs: struct tegra_emc_rate_requests to initialize.
13  * @dev: EMC device.
14  *
15  * Initializes the rate request tracking state with default state
16  * (no active requests). Must be called before using @reqs with
17  * other functions.
18  */
19 void tegra_emc_rate_requests_init(struct tegra_emc_rate_requests *reqs,
20 				  struct device *dev)
21 {
22 	unsigned int i;
23 
24 	mutex_init(&reqs->rate_lock);
25 	reqs->dev = dev;
26 
27 	for (i = 0; i < TEGRA_EMC_RATE_TYPE_MAX; i++) {
28 		reqs->requested_rate[i].min_rate = 0;
29 		reqs->requested_rate[i].max_rate = ULONG_MAX;
30 	}
31 }
32 EXPORT_SYMBOL_GPL(tegra_emc_rate_requests_init);
33 
34 /* Caller must hold reqs->rate_lock. */
35 static int tegra_emc_request_rate(struct tegra_emc_rate_requests *reqs,
36 				  unsigned long new_min_rate,
37 				  unsigned long new_max_rate,
38 				  enum tegra_emc_rate_request_type type)
39 {
40 	struct tegra_emc_rate_request *req = reqs->requested_rate;
41 	unsigned long min_rate = 0, max_rate = ULONG_MAX;
42 	unsigned int i;
43 	int err;
44 
45 	lockdep_assert_held(&reqs->rate_lock);
46 
47 	/* select minimum and maximum rates among the requested rates */
48 	for (i = 0; i < TEGRA_EMC_RATE_TYPE_MAX; i++, req++) {
49 		if (i == type) {
50 			min_rate = max(new_min_rate, min_rate);
51 			max_rate = min(new_max_rate, max_rate);
52 		} else {
53 			min_rate = max(req->min_rate, min_rate);
54 			max_rate = min(req->max_rate, max_rate);
55 		}
56 	}
57 
58 	if (min_rate > max_rate) {
59 		dev_err_ratelimited(reqs->dev, "%s: type %u: out of range: %lu %lu\n",
60 				    __func__, type, min_rate, max_rate);
61 		return -ERANGE;
62 	}
63 
64 	/*
65 	 * EMC rate-changes should go via OPP API because it manages voltage
66 	 * changes.
67 	 */
68 	err = dev_pm_opp_set_rate(reqs->dev, min_rate);
69 	if (err)
70 		return err;
71 
72 	reqs->requested_rate[type].min_rate = new_min_rate;
73 	reqs->requested_rate[type].max_rate = new_max_rate;
74 
75 	return 0;
76 }
77 
78 /**
79  * tegra_emc_set_min_rate() - Update minimum rate request for a request type
80  * @reqs: rate request tracking state
81  * @rate: new minimum rate in Hz requested by @type
82  * @type: type of request
83  *
84  * Records @rate as the new minimum rate request for @type, recalculates target
85  * rate based on all requests and applies new rate through the OPP API.
86  *
87  * Context: Sleeps. Requests to same @reqs are synchronized via mutex.
88  *
89  * Return:
90  * * %0 - success
91  * * %-ERANGE - request would cause minimum rate request to be higher than
92  *              maximum rate request
93  * * other - setting new rate failed
94  */
95 int tegra_emc_set_min_rate(struct tegra_emc_rate_requests *reqs,
96 			   unsigned long rate,
97 			   enum tegra_emc_rate_request_type type)
98 {
99 	struct tegra_emc_rate_request *req = &reqs->requested_rate[type];
100 	int ret;
101 
102 	mutex_lock(&reqs->rate_lock);
103 	ret = tegra_emc_request_rate(reqs, rate, req->max_rate, type);
104 	mutex_unlock(&reqs->rate_lock);
105 
106 	return ret;
107 }
108 EXPORT_SYMBOL_GPL(tegra_emc_set_min_rate);
109 
110 /**
111  * tegra_emc_set_max_rate() - Update maximum rate request for a request type
112  * @reqs: rate request tracking state
113  * @rate: new maximum rate in Hz requested by @type
114  * @type: type of request
115  *
116  * Records @rate as the new maximum rate request for @type, recalculates target
117  * rate based on all requests and applies new rate through the OPP API.
118  *
119  * Context: Sleeps. Requests to same @reqs are synchronized via mutex.
120  *
121  * Return:
122  * * %0 - success
123  * * %-ERANGE - request would cause minimum rate request to be higher than
124  *              maximum rate request
125  * * other - setting new rate failed
126  */
127 int tegra_emc_set_max_rate(struct tegra_emc_rate_requests *reqs,
128 			   unsigned long rate,
129 			   enum tegra_emc_rate_request_type type)
130 {
131 	struct tegra_emc_rate_request *req = &reqs->requested_rate[type];
132 	int ret;
133 
134 	mutex_lock(&reqs->rate_lock);
135 	ret = tegra_emc_request_rate(reqs, req->min_rate, rate, type);
136 	mutex_unlock(&reqs->rate_lock);
137 
138 	return ret;
139 }
140 EXPORT_SYMBOL_GPL(tegra_emc_set_max_rate);
141 
142 MODULE_DESCRIPTION("NVIDIA Tegra EMC common code");
143 MODULE_LICENSE("GPL");
144