1 /*
2  * pwr.c
3  *
4  * DSP-BIOS Bridge driver support functions for TI OMAP processors.
5  *
6  * PWR API for controlling DSP power states.
7  *
8  * Copyright (C) 2005-2006 Texas Instruments, Inc.
9  *
10  * This package is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License version 2 as
12  * published by the Free Software Foundation.
13  *
14  * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
15  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
16  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
17  */
18 
19 /*  ----------------------------------- Host OS */
20 #include <dspbridge/host_os.h>
21 
22 /*  ----------------------------------- This */
23 #include <dspbridge/pwr.h>
24 
25 /*  ----------------------------------- Resource Manager */
26 #include <dspbridge/devdefs.h>
27 #include <dspbridge/drv.h>
28 
29 /*  ----------------------------------- Platform Manager */
30 #include <dspbridge/dev.h>
31 
32 /*  ----------------------------------- Link Driver */
33 #include <dspbridge/dspioctl.h>
34 
35 /*
36  *  ======== pwr_sleep_dsp ========
37  *    Send command to DSP to enter sleep state.
38  */
pwr_sleep_dsp(const u32 sleep_code,const u32 timeout)39 int pwr_sleep_dsp(const u32 sleep_code, const u32 timeout)
40 {
41 	struct bridge_drv_interface *intf_fxns;
42 	struct bridge_dev_context *dw_context;
43 	int status = -EPERM;
44 	struct dev_object *hdev_obj = NULL;
45 	u32 ioctlcode = 0;
46 	u32 arg = timeout;
47 
48 	for (hdev_obj = (struct dev_object *)drv_get_first_dev_object();
49 	     hdev_obj != NULL;
50 	     hdev_obj =
51 	     (struct dev_object *)drv_get_next_dev_object((u32) hdev_obj)) {
52 		if (dev_get_bridge_context(hdev_obj,
53 						(struct bridge_dev_context **)
54 						   &dw_context)) {
55 			continue;
56 		}
57 		if (dev_get_intf_fxns(hdev_obj,
58 						(struct bridge_drv_interface **)
59 						&intf_fxns)) {
60 			continue;
61 		}
62 		if (sleep_code == PWR_DEEPSLEEP)
63 			ioctlcode = BRDIOCTL_DEEPSLEEP;
64 		else if (sleep_code == PWR_EMERGENCYDEEPSLEEP)
65 			ioctlcode = BRDIOCTL_EMERGENCYSLEEP;
66 		else
67 			status = -EINVAL;
68 
69 		if (status != -EINVAL) {
70 			status = (*intf_fxns->dev_cntrl) (dw_context,
71 							      ioctlcode,
72 							      (void *)&arg);
73 		}
74 	}
75 	return status;
76 }
77 
78 /*
79  *  ======== pwr_wake_dsp ========
80  *    Send command to DSP to wake it from sleep.
81  */
pwr_wake_dsp(const u32 timeout)82 int pwr_wake_dsp(const u32 timeout)
83 {
84 	struct bridge_drv_interface *intf_fxns;
85 	struct bridge_dev_context *dw_context;
86 	int status = -EPERM;
87 	struct dev_object *hdev_obj = NULL;
88 	u32 arg = timeout;
89 
90 	for (hdev_obj = (struct dev_object *)drv_get_first_dev_object();
91 	     hdev_obj != NULL;
92 	     hdev_obj = (struct dev_object *)drv_get_next_dev_object
93 	     ((u32) hdev_obj)) {
94 		if (!(dev_get_bridge_context(hdev_obj,
95 						      (struct bridge_dev_context
96 						       **)&dw_context))) {
97 			if (!(dev_get_intf_fxns(hdev_obj,
98 			      (struct bridge_drv_interface **)&intf_fxns))) {
99 				status =
100 				    (*intf_fxns->dev_cntrl) (dw_context,
101 							BRDIOCTL_WAKEUP,
102 							(void *)&arg);
103 			}
104 		}
105 	}
106 	return status;
107 }
108 
109 /*
110  *  ======== pwr_pm_pre_scale========
111  *    Sends pre-notification message to DSP.
112  */
pwr_pm_pre_scale(u16 voltage_domain,u32 level)113 int pwr_pm_pre_scale(u16 voltage_domain, u32 level)
114 {
115 	struct bridge_drv_interface *intf_fxns;
116 	struct bridge_dev_context *dw_context;
117 	int status = -EPERM;
118 	struct dev_object *hdev_obj = NULL;
119 	u32 arg[2];
120 
121 	arg[0] = voltage_domain;
122 	arg[1] = level;
123 
124 	for (hdev_obj = (struct dev_object *)drv_get_first_dev_object();
125 	     hdev_obj != NULL;
126 	     hdev_obj = (struct dev_object *)drv_get_next_dev_object
127 	     ((u32) hdev_obj)) {
128 		if (!(dev_get_bridge_context(hdev_obj,
129 						      (struct bridge_dev_context
130 						       **)&dw_context))) {
131 			if (!(dev_get_intf_fxns(hdev_obj,
132 			      (struct bridge_drv_interface **)&intf_fxns))) {
133 				status =
134 				    (*intf_fxns->dev_cntrl) (dw_context,
135 						BRDIOCTL_PRESCALE_NOTIFY,
136 						(void *)&arg);
137 			}
138 		}
139 	}
140 	return status;
141 }
142 
143 /*
144  *  ======== pwr_pm_post_scale========
145  *    Sends post-notification message to DSP.
146  */
pwr_pm_post_scale(u16 voltage_domain,u32 level)147 int pwr_pm_post_scale(u16 voltage_domain, u32 level)
148 {
149 	struct bridge_drv_interface *intf_fxns;
150 	struct bridge_dev_context *dw_context;
151 	int status = -EPERM;
152 	struct dev_object *hdev_obj = NULL;
153 	u32 arg[2];
154 
155 	arg[0] = voltage_domain;
156 	arg[1] = level;
157 
158 	for (hdev_obj = (struct dev_object *)drv_get_first_dev_object();
159 	     hdev_obj != NULL;
160 	     hdev_obj = (struct dev_object *)drv_get_next_dev_object
161 	     ((u32) hdev_obj)) {
162 		if (!(dev_get_bridge_context(hdev_obj,
163 						      (struct bridge_dev_context
164 						       **)&dw_context))) {
165 			if (!(dev_get_intf_fxns(hdev_obj,
166 			      (struct bridge_drv_interface **)&intf_fxns))) {
167 				status =
168 				    (*intf_fxns->dev_cntrl) (dw_context,
169 						BRDIOCTL_POSTSCALE_NOTIFY,
170 						(void *)&arg);
171 			}
172 		}
173 	}
174 	return status;
175 
176 }
177