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