Skip to content

Commit 70f752e

Browse files
committed
soc/tegra: pmc: Add PMC contextual functions
Add implementations that take as argument a struct tegra_pmc * for most public APIs, as well as a function to obtain the PMC for any given device. This will allow transitioning away users from relying on a global variable storing the PMC context. Signed-off-by: Thierry Reding <treding@nvidia.com>
1 parent e1fd5ad commit 70f752e

2 files changed

Lines changed: 219 additions & 15 deletions

File tree

drivers/soc/tegra/pmc.c

Lines changed: 160 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -957,30 +957,122 @@ static int tegra_genpd_power_off(struct generic_pm_domain *domain)
957957
return err;
958958
}
959959

960+
static void tegra_pmc_put_device(void *data)
961+
{
962+
struct tegra_pmc *pmc = data;
963+
964+
put_device(pmc->dev);
965+
}
966+
967+
static const struct of_device_id tegra_pmc_match[];
968+
969+
static struct tegra_pmc *tegra_pmc_get(struct device *dev)
970+
{
971+
struct platform_device *pdev;
972+
struct device_node *np;
973+
struct tegra_pmc *pmc;
974+
975+
np = of_parse_phandle(dev->of_node, "nvidia,pmc", 0);
976+
if (!np) {
977+
struct device_node *parent = of_node_get(dev->of_node);
978+
979+
while ((parent = of_get_next_parent(parent)) != NULL) {
980+
np = of_find_matching_node(parent, tegra_pmc_match);
981+
if (np)
982+
break;
983+
}
984+
985+
of_node_put(parent);
986+
987+
if (!np)
988+
return ERR_PTR(-ENODEV);
989+
}
990+
991+
pdev = of_find_device_by_node(np);
992+
of_node_put(np);
993+
994+
if (!pdev)
995+
return ERR_PTR(-ENODEV);
996+
997+
pmc = platform_get_drvdata(pdev);
998+
if (!pmc) {
999+
put_device(&pdev->dev);
1000+
return ERR_PTR(-EPROBE_DEFER);
1001+
}
1002+
1003+
return pmc;
1004+
}
1005+
9601006
/**
961-
* tegra_powergate_power_on() - power on partition
1007+
* tegra_pmc_get() - find the PMC for a given device
1008+
* @dev: device for which to find the PMC
1009+
*
1010+
* Returns a pointer to the PMC on success or an ERR_PTR()-encoded error code
1011+
* otherwise.
1012+
*/
1013+
struct tegra_pmc *devm_tegra_pmc_get(struct device *dev)
1014+
{
1015+
struct tegra_pmc *pmc;
1016+
int err;
1017+
1018+
pmc = tegra_pmc_get(dev);
1019+
if (IS_ERR(pmc))
1020+
return pmc;
1021+
1022+
err = devm_add_action_or_reset(dev, tegra_pmc_put_device, pmc);
1023+
if (err < 0)
1024+
return ERR_PTR(err);
1025+
1026+
return pmc;
1027+
}
1028+
EXPORT_SYMBOL(devm_tegra_pmc_get);
1029+
1030+
/**
1031+
* tegra_pmc_powergate_power_on() - power on partition
1032+
* @pmc: power management controller
9621033
* @id: partition ID
9631034
*/
964-
int tegra_powergate_power_on(unsigned int id)
1035+
int tegra_pmc_powergate_power_on(struct tegra_pmc *pmc, unsigned int id)
9651036
{
9661037
if (!tegra_powergate_is_available(pmc, id))
9671038
return -EINVAL;
9681039

9691040
return tegra_powergate_set(pmc, id, true);
9701041
}
1042+
EXPORT_SYMBOL(tegra_pmc_powergate_power_on);
1043+
1044+
/**
1045+
* tegra_powergate_power_on() - power on partition
1046+
* @id: partition ID
1047+
*/
1048+
int tegra_powergate_power_on(unsigned int id)
1049+
{
1050+
return tegra_pmc_powergate_power_on(pmc, id);
1051+
}
9711052
EXPORT_SYMBOL(tegra_powergate_power_on);
9721053

9731054
/**
974-
* tegra_powergate_power_off() - power off partition
1055+
* tegra_pmc_powergate_power_off() - power off partition
1056+
* @pmc: power management controller
9751057
* @id: partition ID
9761058
*/
977-
int tegra_powergate_power_off(unsigned int id)
1059+
int tegra_pmc_powergate_power_off(struct tegra_pmc *pmc, unsigned int id)
9781060
{
9791061
if (!tegra_powergate_is_available(pmc, id))
9801062
return -EINVAL;
9811063

9821064
return tegra_powergate_set(pmc, id, false);
9831065
}
1066+
EXPORT_SYMBOL(tegra_pmc_powergate_power_off);
1067+
1068+
/**
1069+
* tegra_powergate_power_off() - power off partition
1070+
* @id: partition ID
1071+
*/
1072+
int tegra_powergate_power_off(unsigned int id)
1073+
{
1074+
return tegra_pmc_powergate_power_off(pmc, id);
1075+
}
9841076
EXPORT_SYMBOL(tegra_powergate_power_off);
9851077

9861078
/**
@@ -997,28 +1089,41 @@ static int tegra_powergate_is_powered(struct tegra_pmc *pmc, unsigned int id)
9971089
}
9981090

9991091
/**
1000-
* tegra_powergate_remove_clamping() - remove power clamps for partition
1092+
* tegra_pmc_powergate_remove_clamping() - remove power clamps for partition
1093+
* @pmc: power management controller
10011094
* @id: partition ID
10021095
*/
1003-
int tegra_powergate_remove_clamping(unsigned int id)
1096+
int tegra_pmc_powergate_remove_clamping(struct tegra_pmc *pmc, unsigned int id)
10041097
{
10051098
if (!tegra_powergate_is_available(pmc, id))
10061099
return -EINVAL;
10071100

10081101
return __tegra_powergate_remove_clamping(pmc, id);
10091102
}
1103+
EXPORT_SYMBOL(tegra_pmc_powergate_remove_clamping);
1104+
1105+
/**
1106+
* tegra_powergate_remove_clamping() - remove power clamps for partition
1107+
* @id: partition ID
1108+
*/
1109+
int tegra_powergate_remove_clamping(unsigned int id)
1110+
{
1111+
return tegra_pmc_powergate_remove_clamping(pmc, id);
1112+
}
10101113
EXPORT_SYMBOL(tegra_powergate_remove_clamping);
10111114

10121115
/**
1013-
* tegra_powergate_sequence_power_up() - power up partition
1116+
* tegra_pmc_powergate_sequence_power_up() - power up partition
1117+
* @pmc: power management controller
10141118
* @id: partition ID
10151119
* @clk: clock for partition
10161120
* @rst: reset for partition
10171121
*
10181122
* Must be called with clk disabled, and returns with clk enabled.
10191123
*/
1020-
int tegra_powergate_sequence_power_up(unsigned int id, struct clk *clk,
1021-
struct reset_control *rst)
1124+
int tegra_pmc_powergate_sequence_power_up(struct tegra_pmc *pmc,
1125+
unsigned int id, struct clk *clk,
1126+
struct reset_control *rst)
10221127
{
10231128
struct tegra_powergate *pg;
10241129
int err;
@@ -1052,6 +1157,21 @@ int tegra_powergate_sequence_power_up(unsigned int id, struct clk *clk,
10521157

10531158
return err;
10541159
}
1160+
EXPORT_SYMBOL(tegra_pmc_powergate_sequence_power_up);
1161+
1162+
/**
1163+
* tegra_powergate_sequence_power_up() - power up partition
1164+
* @id: partition ID
1165+
* @clk: clock for partition
1166+
* @rst: reset for partition
1167+
*
1168+
* Must be called with clk disabled, and returns with clk enabled.
1169+
*/
1170+
int tegra_powergate_sequence_power_up(unsigned int id, struct clk *clk,
1171+
struct reset_control *rst)
1172+
{
1173+
return tegra_pmc_powergate_sequence_power_up(pmc, id, clk, rst);
1174+
}
10551175
EXPORT_SYMBOL(tegra_powergate_sequence_power_up);
10561176

10571177
/**
@@ -1627,11 +1747,12 @@ static void tegra_io_pad_unprepare(struct tegra_pmc *pmc)
16271747

16281748
/**
16291749
* tegra_io_pad_power_enable() - enable power to I/O pad
1750+
* @pmc: power management controller
16301751
* @id: Tegra I/O pad ID for which to enable power
16311752
*
16321753
* Returns: 0 on success or a negative error code on failure.
16331754
*/
1634-
int tegra_io_pad_power_enable(enum tegra_io_pad id)
1755+
int tegra_pmc_io_pad_power_enable(struct tegra_pmc *pmc, enum tegra_io_pad id)
16351756
{
16361757
const struct tegra_io_pad_soc *pad;
16371758
unsigned long request, status;
@@ -1666,15 +1787,28 @@ int tegra_io_pad_power_enable(enum tegra_io_pad id)
16661787
mutex_unlock(&pmc->powergates_lock);
16671788
return err;
16681789
}
1790+
EXPORT_SYMBOL(tegra_pmc_io_pad_power_enable);
1791+
1792+
/**
1793+
* tegra_io_pad_power_enable() - enable power to I/O pad
1794+
* @id: Tegra I/O pad ID for which to enable power
1795+
*
1796+
* Returns: 0 on success or a negative error code on failure.
1797+
*/
1798+
int tegra_io_pad_power_enable(enum tegra_io_pad id)
1799+
{
1800+
return tegra_pmc_io_pad_power_enable(pmc, id);
1801+
}
16691802
EXPORT_SYMBOL(tegra_io_pad_power_enable);
16701803

16711804
/**
1672-
* tegra_io_pad_power_disable() - disable power to I/O pad
1805+
* tegra_pmc_io_pad_power_disable() - disable power to I/O pad
1806+
* @pmc: power management controller
16731807
* @id: Tegra I/O pad ID for which to disable power
16741808
*
16751809
* Returns: 0 on success or a negative error code on failure.
16761810
*/
1677-
int tegra_io_pad_power_disable(enum tegra_io_pad id)
1811+
int tegra_pmc_io_pad_power_disable(struct tegra_pmc *pmc, enum tegra_io_pad id)
16781812
{
16791813
const struct tegra_io_pad_soc *pad;
16801814
unsigned long request, status;
@@ -1709,6 +1843,18 @@ int tegra_io_pad_power_disable(enum tegra_io_pad id)
17091843
mutex_unlock(&pmc->powergates_lock);
17101844
return err;
17111845
}
1846+
EXPORT_SYMBOL(tegra_pmc_io_pad_power_disable);
1847+
1848+
/**
1849+
* tegra_io_pad_power_disable() - disable power to I/O pad
1850+
* @id: Tegra I/O pad ID for which to disable power
1851+
*
1852+
* Returns: 0 on success or a negative error code on failure.
1853+
*/
1854+
int tegra_io_pad_power_disable(enum tegra_io_pad id)
1855+
{
1856+
return tegra_pmc_io_pad_power_disable(pmc, id);
1857+
}
17121858
EXPORT_SYMBOL(tegra_io_pad_power_disable);
17131859

17141860
static int tegra_io_pad_is_powered(struct tegra_pmc *pmc, enum tegra_io_pad id)
@@ -2184,9 +2330,9 @@ static int tegra_io_pad_pinconf_set(struct pinctrl_dev *pctl_dev,
21842330
switch (param) {
21852331
case PIN_CONFIG_MODE_LOW_POWER:
21862332
if (arg)
2187-
err = tegra_io_pad_power_disable(pad->id);
2333+
err = tegra_pmc_io_pad_power_disable(pmc, pad->id);
21882334
else
2189-
err = tegra_io_pad_power_enable(pad->id);
2335+
err = tegra_pmc_io_pad_power_enable(pmc, pad->id);
21902336
if (err)
21912337
return err;
21922338
break;

include/soc/tegra/pmc.h

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
struct clk;
1818
struct reset_control;
19+
struct tegra_pmc;
1920

2021
bool tegra_pmc_cpu_is_powered(unsigned int cpuid);
2122
int tegra_pmc_cpu_power_on(unsigned int cpuid);
@@ -149,11 +150,24 @@ enum tegra_io_pad {
149150
};
150151

151152
#ifdef CONFIG_SOC_TEGRA_PMC
153+
struct tegra_pmc *devm_tegra_pmc_get(struct device *dev);
154+
155+
int tegra_pmc_powergate_power_on(struct tegra_pmc *pmc, unsigned int id);
156+
int tegra_pmc_powergate_power_off(struct tegra_pmc *pmc, unsigned int id);
157+
int tegra_pmc_powergate_remove_clamping(struct tegra_pmc *pmc, unsigned int id);
158+
159+
/* Must be called with clk disabled, and returns with clk enabled */
160+
int tegra_pmc_powergate_sequence_power_up(struct tegra_pmc *pmc,
161+
unsigned int id, struct clk *clk,
162+
struct reset_control *rst);
163+
int tegra_pmc_io_pad_power_enable(struct tegra_pmc *pmc, enum tegra_io_pad id);
164+
int tegra_pmc_io_pad_power_disable(struct tegra_pmc *pmc, enum tegra_io_pad id);
165+
166+
/* legacy */
152167
int tegra_powergate_power_on(unsigned int id);
153168
int tegra_powergate_power_off(unsigned int id);
154169
int tegra_powergate_remove_clamping(unsigned int id);
155170

156-
/* Must be called with clk disabled, and returns with clk enabled */
157171
int tegra_powergate_sequence_power_up(unsigned int id, struct clk *clk,
158172
struct reset_control *rst);
159173

@@ -166,6 +180,50 @@ void tegra_pmc_enter_suspend_mode(enum tegra_suspend_mode mode);
166180
bool tegra_pmc_core_domain_state_synced(void);
167181

168182
#else
183+
static inline struct tegra_pmc *devm_tegra_pmc_get(struct device *dev)
184+
{
185+
return ERR_PTR(-ENOSYS);
186+
}
187+
188+
static inline int
189+
tegra_pmc_powergate_power_on(struct tegra_pmc *pmc, unsigned int id)
190+
{
191+
return -ENOSYS;
192+
}
193+
194+
static inline int
195+
tegra_pmc_powergate_power_off(struct tegra_pmc *pmc, unsigned int id)
196+
{
197+
return -ENOSYS;
198+
}
199+
200+
static inline int
201+
tegra_pmc_powergate_remove_clamping(struct tegra_pmc *pmc, unsigned int id)
202+
{
203+
return -ENOSYS;
204+
}
205+
206+
/* Must be called with clk disabled, and returns with clk enabled */
207+
static inline int
208+
tegra_pmc_powergate_sequence_power_up(struct tegra_pmc *pmc, unsigned int id,
209+
struct clk *clk,
210+
struct reset_control *rst)
211+
{
212+
return -ENOSYS;
213+
}
214+
215+
static inline int
216+
tegra_pmc_io_pad_power_enable(struct tegra_pmc *pmc, enum tegra_io_pad id)
217+
{
218+
return -ENOSYS;
219+
}
220+
221+
static inline int
222+
tegra_pmc_io_pad_power_disable(struct tegra_pmc *pmc, enum tegra_io_pad id)
223+
{
224+
return -ENOSYS;
225+
}
226+
169227
static inline int tegra_powergate_power_on(unsigned int id)
170228
{
171229
return -ENOSYS;

0 commit comments

Comments
 (0)