@@ -50,10 +50,8 @@ static int cros_ec_sensorhub_register(struct device *dev,
50
50
struct cros_ec_sensorhub * sensorhub )
51
51
{
52
52
int sensor_type [MOTIONSENSE_TYPE_MAX ] = { 0 };
53
+ struct cros_ec_command * msg = sensorhub -> msg ;
53
54
struct cros_ec_dev * ec = sensorhub -> ec ;
54
- struct ec_params_motion_sense * params ;
55
- struct ec_response_motion_sense * resp ;
56
- struct cros_ec_command * msg ;
57
55
int ret , i , sensor_num ;
58
56
char * name ;
59
57
@@ -71,22 +69,13 @@ static int cros_ec_sensorhub_register(struct device *dev,
71
69
return - EINVAL ;
72
70
}
73
71
74
- /* Prepare a message to send INFO command to each sensor. */
75
- msg = kzalloc (sizeof (* msg ) + max (sizeof (* params ), sizeof (* resp )),
76
- GFP_KERNEL );
77
- if (!msg )
78
- return - ENOMEM ;
79
-
80
72
msg -> version = 1 ;
81
- msg -> command = EC_CMD_MOTION_SENSE_CMD + ec -> cmd_offset ;
82
- msg -> outsize = sizeof (* params );
83
- msg -> insize = sizeof (* resp );
84
- params = (struct ec_params_motion_sense * )msg -> data ;
85
- resp = (struct ec_response_motion_sense * )msg -> data ;
73
+ msg -> insize = sizeof (struct ec_response_motion_sense );
74
+ msg -> outsize = sizeof (struct ec_params_motion_sense );
86
75
87
76
for (i = 0 ; i < sensor_num ; i ++ ) {
88
- params -> cmd = MOTIONSENSE_CMD_INFO ;
89
- params -> info .sensor_num = i ;
77
+ sensorhub -> params -> cmd = MOTIONSENSE_CMD_INFO ;
78
+ sensorhub -> params -> info .sensor_num = i ;
90
79
91
80
ret = cros_ec_cmd_xfer_status (ec -> ec_dev , msg );
92
81
if (ret < 0 ) {
@@ -95,7 +84,7 @@ static int cros_ec_sensorhub_register(struct device *dev,
95
84
continue ;
96
85
}
97
86
98
- switch (resp -> info .type ) {
87
+ switch (sensorhub -> resp -> info .type ) {
99
88
case MOTIONSENSE_TYPE_ACCEL :
100
89
name = "cros-ec-accel" ;
101
90
break ;
@@ -118,15 +107,16 @@ static int cros_ec_sensorhub_register(struct device *dev,
118
107
name = "cros-ec-activity" ;
119
108
break ;
120
109
default :
121
- dev_warn (dev , "unknown type %d\n" , resp -> info .type );
110
+ dev_warn (dev , "unknown type %d\n" ,
111
+ sensorhub -> resp -> info .type );
122
112
continue ;
123
113
}
124
114
125
115
ret = cros_ec_sensorhub_allocate_sensor (dev , name , i );
126
116
if (ret )
127
- goto error ;
117
+ return ret ;
128
118
129
- sensor_type [resp -> info .type ]++ ;
119
+ sensor_type [sensorhub -> resp -> info .type ]++ ;
130
120
}
131
121
132
122
if (sensor_type [MOTIONSENSE_TYPE_ACCEL ] >= 2 )
@@ -138,29 +128,41 @@ static int cros_ec_sensorhub_register(struct device *dev,
138
128
"cros-ec-lid-angle" ,
139
129
0 );
140
130
if (ret )
141
- goto error ;
131
+ return ret ;
142
132
}
143
133
144
- kfree (msg );
145
134
return 0 ;
146
-
147
- error :
148
- kfree (msg );
149
- return ret ;
150
135
}
151
136
152
137
static int cros_ec_sensorhub_probe (struct platform_device * pdev )
153
138
{
154
139
struct device * dev = & pdev -> dev ;
140
+ struct cros_ec_dev * ec = dev_get_drvdata (dev -> parent );
155
141
struct cros_ec_sensorhub * data ;
142
+ struct cros_ec_command * msg ;
156
143
int ret ;
157
144
int i ;
158
145
146
+ msg = devm_kzalloc (dev , sizeof (struct cros_ec_command ) +
147
+ max ((u16 )sizeof (struct ec_params_motion_sense ),
148
+ ec -> ec_dev -> max_response ), GFP_KERNEL );
149
+ if (!msg )
150
+ return - ENOMEM ;
151
+
152
+ msg -> command = EC_CMD_MOTION_SENSE_CMD + ec -> cmd_offset ;
153
+
159
154
data = devm_kzalloc (dev , sizeof (struct cros_ec_sensorhub ), GFP_KERNEL );
160
155
if (!data )
161
156
return - ENOMEM ;
162
157
163
- data -> ec = dev_get_drvdata (dev -> parent );
158
+ mutex_init (& data -> cmd_lock );
159
+
160
+ data -> dev = dev ;
161
+ data -> ec = ec ;
162
+ data -> msg = msg ;
163
+ data -> params = (struct ec_params_motion_sense * )msg -> data ;
164
+ data -> resp = (struct ec_response_motion_sense * )msg -> data ;
165
+
164
166
dev_set_drvdata (dev , data );
165
167
166
168
/* Check whether this EC is a sensor hub. */
@@ -182,12 +184,63 @@ static int cros_ec_sensorhub_probe(struct platform_device *pdev)
182
184
}
183
185
}
184
186
187
+ /*
188
+ * If the EC does not have a FIFO, the sensors will query their data
189
+ * themselves via sysfs or a software trigger.
190
+ */
191
+ if (cros_ec_check_features (ec , EC_FEATURE_MOTION_SENSE_FIFO )) {
192
+ ret = cros_ec_sensorhub_ring_add (data );
193
+ if (ret )
194
+ return ret ;
195
+ /*
196
+ * The msg and its data is not under the control of the ring
197
+ * handler.
198
+ */
199
+ return devm_add_action_or_reset (dev ,
200
+ cros_ec_sensorhub_ring_remove ,
201
+ data );
202
+ }
203
+
204
+ return 0 ;
205
+ }
206
+
207
+ #ifdef CONFIG_PM_SLEEP
208
+ /*
209
+ * When the EC is suspending, we must stop sending interrupt,
210
+ * we may use the same interrupt line for waking up the device.
211
+ * Tell the EC to stop sending non-interrupt event on the iio ring.
212
+ */
213
+ static int cros_ec_sensorhub_suspend (struct device * dev )
214
+ {
215
+ struct platform_device * pdev = to_platform_device (dev );
216
+ struct cros_ec_sensorhub * sensorhub = platform_get_drvdata (pdev );
217
+ struct cros_ec_dev * ec = sensorhub -> ec ;
218
+
219
+ if (cros_ec_check_features (ec , EC_FEATURE_MOTION_SENSE_FIFO ))
220
+ return cros_ec_sensorhub_ring_fifo_enable (sensorhub , false);
185
221
return 0 ;
186
222
}
187
223
224
+ static int cros_ec_sensorhub_resume (struct device * dev )
225
+ {
226
+ struct platform_device * pdev = to_platform_device (dev );
227
+ struct cros_ec_sensorhub * sensorhub = platform_get_drvdata (pdev );
228
+ struct cros_ec_dev * ec = sensorhub -> ec ;
229
+
230
+ if (cros_ec_check_features (ec , EC_FEATURE_MOTION_SENSE_FIFO ))
231
+ return cros_ec_sensorhub_ring_fifo_enable (sensorhub , true);
232
+ return 0 ;
233
+ }
234
+ #endif
235
+
236
+ static SIMPLE_DEV_PM_OPS (cros_ec_sensorhub_pm_ops ,
237
+ cros_ec_sensorhub_suspend ,
238
+ cros_ec_sensorhub_resume ) ;
239
+
188
240
static struct platform_driver cros_ec_sensorhub_driver = {
189
241
.driver = {
190
242
.name = DRV_NAME ,
243
+ .pm = & cros_ec_sensorhub_pm_ops ,
191
244
},
192
245
.probe = cros_ec_sensorhub_probe ,
193
246
};
0 commit comments