blob: 0683bc54acbc1aa8723e86fd463d44b8920ed321 [file] [log] [blame]
Naveen Ramaraj88f23632012-10-10 12:23:29 -07001/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 */
12
13#include <linux/workqueue.h>
14#include <linux/types.h>
15#include <linux/delay.h>
16#include <linux/bitops.h>
17#include <linux/wait.h>
18#include <linux/sched.h>
19#include <linux/notifier.h>
20#include <linux/slab.h>
21#include <linux/module.h>
22#include <linux/init.h>
23#include <linux/cdev.h>
24#include <linux/fs.h>
25#include <linux/platform_device.h>
26#include <linux/err.h>
27#include <linux/io.h>
28#include <linux/ctype.h>
29#include <linux/of_device.h>
Naveen Ramaraj93060a42012-11-15 23:23:55 -080030#include <linux/msm_dsps.h>
31#include <linux/uaccess.h>
Naveen Ramaraj88f23632012-10-10 12:23:29 -070032#include <asm/mach-types.h>
Naveen Ramaraj93060a42012-11-15 23:23:55 -080033#include <asm/arch_timer.h>
Naveen Ramaraj88f23632012-10-10 12:23:29 -070034#include <mach/subsystem_restart.h>
35#include <mach/ocmem.h>
36#include <mach/msm_smd.h>
37#include <mach/sensors_adsp.h>
38#include <mach/msm_bus.h>
39#include <mach/msm_bus_board.h>
40
Naveen Ramaraj93060a42012-11-15 23:23:55 -080041#define DRV_NAME "sensors"
Naveen Ramaraj88f23632012-10-10 12:23:29 -070042#define DRV_VERSION "1.00"
43
44#define SNS_OCMEM_SMD_CHANNEL "SENSOR"
45#define SNS_OCMEM_CLIENT_ID OCMEM_SENSORS
46#define SNS_OCMEM_SIZE SZ_256K
47#define SMD_BUF_SIZE 2048
48#define SNS_TIMEOUT_MS 1000
49
50#define SNS_OCMEM_ALLOC_GROW 0x00000001
51#define SNS_OCMEM_ALLOC_SHRINK 0x00000002
52#define SNS_OCMEM_MAP_DONE 0x00000004
53#define SNS_OCMEM_MAP_FAIL 0x00000008
54#define SNS_OCMEM_UNMAP_DONE 0x00000010
55#define SNS_OCMEM_UNMAP_FAIL 0x00000020
56
57#define DSPS_HAS_CLIENT 0x00000100
58#define DSPS_HAS_NO_CLIENT 0x00000200
59#define DSPS_BW_VOTE_ON 0x00000400
60#define DSPS_BW_VOTE_OFF 0x00000800
61#define DSPS_PHYS_ADDR_SET 0x00001000
62
63/**
64 * Structure contains all state used by the sensors driver
65 */
66struct sns_adsp_control_s {
67 wait_queue_head_t sns_wait;
68 spinlock_t sns_lock;
69 struct workqueue_struct *sns_workqueue;
70 struct work_struct sns_work;
71 smd_channel_t *smd_ch;
72 uint32_t sns_ocmem_status;
73 uint32_t mem_segments_size;
74 struct sns_mem_segment_s_v01 mem_segments[SNS_OCMEM_MAX_NUM_SEG_V01];
75 struct ocmem_buf *buf;
76 struct ocmem_map_list map_list;
77 struct ocmem_notifier *ocmem_handle;
78 bool ocmem_enabled;
79 struct notifier_block ocmem_nb;
80 uint32_t sns_ocmem_bus_client;
81 struct platform_device *pdev;
82 void *pil;
Naveen Ramaraj93060a42012-11-15 23:23:55 -080083 struct class *dev_class;
84 dev_t dev_num;
85 struct device *dev;
86 struct cdev *cdev;
Naveen Ramaraj88f23632012-10-10 12:23:29 -070087};
88
89static struct sns_adsp_control_s sns_ctl;
90
91/* All asynchronous responses from the OCMEM driver are received
92by this function */
93int sns_ocmem_drv_cb(struct notifier_block *self,
94 unsigned long action,
95 void *dev)
96{
97 unsigned long flags;
98 pr_debug("%s\n", __func__);
99
100 spin_lock_irqsave(&sns_ctl.sns_lock, flags);
101
102 pr_debug("%s: Received OCMEM callback: action=%li\n",
103 __func__, action);
104
105 switch (action) {
106 case OCMEM_MAP_DONE:
107 sns_ctl.sns_ocmem_status |= SNS_OCMEM_MAP_DONE;
108 sns_ctl.sns_ocmem_status &= (~OCMEM_MAP_FAIL &
109 ~SNS_OCMEM_UNMAP_DONE &
110 ~SNS_OCMEM_UNMAP_FAIL);
111 break;
112 case OCMEM_MAP_FAIL:
113 sns_ctl.sns_ocmem_status |= SNS_OCMEM_MAP_FAIL;
114 sns_ctl.sns_ocmem_status &= (~OCMEM_MAP_DONE &
115 ~SNS_OCMEM_UNMAP_DONE &
116 ~SNS_OCMEM_UNMAP_FAIL);
117 break;
118 case OCMEM_UNMAP_DONE:
119 sns_ctl.sns_ocmem_status |= SNS_OCMEM_UNMAP_DONE;
120 sns_ctl.sns_ocmem_status &= (~SNS_OCMEM_UNMAP_FAIL &
121 ~SNS_OCMEM_MAP_DONE &
122 ~OCMEM_MAP_FAIL);
123 break;
124 case OCMEM_UNMAP_FAIL:
125 sns_ctl.sns_ocmem_status |= SNS_OCMEM_UNMAP_FAIL;
126 sns_ctl.sns_ocmem_status &= (~SNS_OCMEM_UNMAP_DONE &
127 ~SNS_OCMEM_MAP_DONE &
128 ~OCMEM_MAP_FAIL);
129 break;
130 case OCMEM_ALLOC_GROW:
131 sns_ctl.sns_ocmem_status |= SNS_OCMEM_ALLOC_GROW;
132 sns_ctl.sns_ocmem_status &= ~SNS_OCMEM_ALLOC_SHRINK;
133 break;
134 case OCMEM_ALLOC_SHRINK:
135 sns_ctl.sns_ocmem_status |= SNS_OCMEM_ALLOC_SHRINK;
136 sns_ctl.sns_ocmem_status &= ~SNS_OCMEM_ALLOC_GROW;
137 break;
138 default:
139 pr_err("%s: Unknown action received in OCMEM callback %lu\n",
140 __func__, action);
141 break;
142 }
143
144 pr_debug("%s: sns_ocmem_status: 0x%x\n", __func__,
145 sns_ctl.sns_ocmem_status);
146 spin_unlock_irqrestore(&sns_ctl.sns_lock, flags);
147
148 wake_up(&sns_ctl.sns_wait);
149
150 return 0;
151}
152
153/**
154 * Processes messages received through SMD from the ADSP
155 *
156 * @param hdr The message header
157 * @param msg Message pointer
158 *
159 * */
160void sns_ocmem_smd_process(struct sns_ocmem_hdr_s *hdr, void *msg)
161{
162 unsigned long flags;
163 pr_debug("%s\n", __func__);
164
165 spin_lock_irqsave(&sns_ctl.sns_lock, flags);
166
167 pr_debug("%s: Received message from ADSP; id: %i type: %i (%08x)\n",
168 __func__, hdr->msg_id, hdr->msg_type,
169 sns_ctl.sns_ocmem_status);
170
171 if (hdr->msg_id == SNS_OCMEM_PHYS_ADDR_RESP_V01 &&
172 hdr->msg_type == SNS_OCMEM_MSG_TYPE_RESP) {
173 struct sns_ocmem_phys_addr_resp_msg_v01 *msg_ptr =
174 (struct sns_ocmem_phys_addr_resp_msg_v01 *)msg;
175 pr_debug("%s: Received SNS_OCMEM_PHYS_ADDR_RESP_V01\n",
176 __func__);
177 pr_debug("%s: segments_valid=%d, segments_len=%d\n", __func__,
178 msg_ptr->segments_valid, msg_ptr->segments_len);
179
180 if (msg_ptr->segments_valid) {
181 sns_ctl.mem_segments_size = msg_ptr->segments_len;
182 memcpy(sns_ctl.mem_segments, msg_ptr->segments,
183 sizeof(struct sns_mem_segment_s_v01) *
184 msg_ptr->segments_len);
185
186 sns_ctl.sns_ocmem_status |= DSPS_PHYS_ADDR_SET;
187 } else {
188 pr_err("%s: Received invalid segment list\n", __func__);
189 }
190 } else if (hdr->msg_id == SNS_OCMEM_HAS_CLIENT_IND_V01 &&
191 hdr->msg_type == SNS_OCMEM_MSG_TYPE_IND) {
192 struct sns_ocmem_has_client_ind_msg_v01 *msg_ptr =
193 (struct sns_ocmem_has_client_ind_msg_v01 *)msg;
194
195 pr_debug("%s: Received SNS_OCMEM_HAS_CLIENT_IND_V01\n",
196 __func__);
197 pr_debug("%s: ADSP has %i client(s)\n", __func__,
198 msg_ptr->num_clients);
199 if (msg_ptr->num_clients > 0) {
200 sns_ctl.sns_ocmem_status |= DSPS_HAS_CLIENT;
201 sns_ctl.sns_ocmem_status &= ~DSPS_HAS_NO_CLIENT;
202 } else {
203 sns_ctl.sns_ocmem_status |= DSPS_HAS_NO_CLIENT;
204 sns_ctl.sns_ocmem_status &= ~DSPS_HAS_CLIENT;
205 }
206 } else if (hdr->msg_id == SNS_OCMEM_BW_VOTE_RESP_V01 &&
207 hdr->msg_type == SNS_OCMEM_MSG_TYPE_RESP) {
208 /* no need to handle this response msg, just return */
209 pr_debug("%s: Received SNS_OCMEM_BW_VOTE_RESP_V01\n", __func__);
210 spin_unlock_irqrestore(&sns_ctl.sns_lock, flags);
211 return;
212 } else if (hdr->msg_id == SNS_OCMEM_BW_VOTE_IND_V01 &&
213 hdr->msg_type == SNS_OCMEM_MSG_TYPE_IND) {
214 struct sns_ocmem_bw_vote_ind_msg_v01 *msg_ptr =
215 (struct sns_ocmem_bw_vote_ind_msg_v01 *)msg;
216 pr_debug("%s: Received BW_VOTE_IND_V01, is_vote_on=%d\n",
217 __func__, msg_ptr->is_vote_on);
218
219 if (msg_ptr->is_vote_on) {
220 sns_ctl.sns_ocmem_status |= DSPS_BW_VOTE_ON;
221 sns_ctl.sns_ocmem_status &= ~DSPS_BW_VOTE_OFF;
222 } else {
223 sns_ctl.sns_ocmem_status |= DSPS_BW_VOTE_OFF;
224 sns_ctl.sns_ocmem_status &= ~DSPS_BW_VOTE_ON;
225 }
226 } else {
227 pr_err("%s: Unknown message type received. id: %i; type: %i\n",
228 __func__, hdr->msg_id, hdr->msg_type);
229 }
230
231 pr_debug("%s: sns_ocmem_status: 0x%x\n",
232 __func__, sns_ctl.sns_ocmem_status);
233
234 spin_unlock_irqrestore(&sns_ctl.sns_lock, flags);
235
236 wake_up(&sns_ctl.sns_wait);
237}
238
239/**
240 * All SMD notifications and messages from Sensors on ADSP are
241 * received by this function
242 *
243 * */
244
245void sns_ocmem_smd_notify_data(void *data, unsigned int event)
246{
247 pr_debug("%s:\n", __func__);
248
249 if (event == SMD_EVENT_DATA) {
250 int len;
251 pr_debug("%s: Received SMD event Data\n", __func__);
252 len = smd_read_avail(sns_ctl.smd_ch);
253 pr_debug("%s: len=%d\n", __func__, len);
254 if (len > 0) {
255 data = kzalloc(SMD_BUF_SIZE, GFP_ATOMIC);
256 if (data == NULL) {
257 pr_err("%s: malloc failed", __func__);
258 return;
259 }
260
261 len = smd_read_from_cb(sns_ctl.smd_ch,
262 data, SMD_BUF_SIZE);
263 if (len > 0) {
264 sns_ocmem_smd_process(
265 (struct sns_ocmem_hdr_s *) data,
266 (void *)((char *)data +
267 sizeof(struct sns_ocmem_hdr_s)));
268 } else {
269 pr_err("Failed to read event from smd %i", len);
270 }
271 kfree(data);
272 } else if (len < 0) {
273 pr_err("Failed to read event from smd %i", len);
274 }
275 } else if (event == SMD_EVENT_OPEN) {
276 pr_debug("%s: Received SMD event Open\n", __func__);
277 } else if (event == SMD_EVENT_CLOSE) {
278 pr_debug("%s: Received SMD event Close\n", __func__);
279 }
280}
281
282static bool sns_ocmem_is_status_set(uint32_t sns_ocmem_status)
283{
284 unsigned long flags;
285 bool is_set;
286 pr_debug("%s: status=0x%x\n", __func__, sns_ocmem_status);
287
288 spin_lock_irqsave(&sns_ctl.sns_lock, flags);
289 is_set = sns_ctl.sns_ocmem_status & sns_ocmem_status;
290 spin_unlock_irqrestore(&sns_ctl.sns_lock, flags);
291 pr_debug("%s: is_set=%d\n", __func__, is_set);
292 return is_set;
293}
294
295/**
296 * Wait for a response from ADSP or OCMEM Driver, timeout if necessary
297 *
298 * @param sns_ocmem_status Status flags to wait for.
299 * @param timeout_sec Seconds to wait before timeout
300 * @param timeout_nsec Nanoseconds to wait. Total timeout = nsec + sec
301 *
302 * @return 0 If any status flag is set at any time prior to a timeout.
303 * 0 if success or timedout ; <0 for failures
304 *
305 */
306static int sns_ocmem_wait(uint32_t sns_ocmem_status,
307 uint32_t timeout_ms)
308{
309 int err;
310 pr_debug("%s: status=0x%x, timeout_ms=%d\n", __func__,
311 sns_ocmem_status, timeout_ms);
312 if (timeout_ms) {
313 err = wait_event_interruptible_timeout(sns_ctl.sns_wait,
314 sns_ocmem_is_status_set(sns_ocmem_status),
315 msecs_to_jiffies(timeout_ms));
316
317 if (err == 0)
318 pr_err("%s: interruptible_timeout timeout err=%i\n",
319 __func__, err);
320 else if (err < 0)
321 pr_err("%s: interruptible_timeout failed err=%i\n",
322 __func__, err);
323 } else { /* no timeout */
324 err = wait_event_interruptible(sns_ctl.sns_wait,
325 sns_ocmem_is_status_set(sns_ocmem_status));
326 if (err < 0)
327 pr_err("%s: wait_event_interruptible failed err=%i\n",
328 __func__, err);
329 }
330
331 return err;
332}
333
334/**
335 * Sends a message to the ADSP via SMD.
336 *
337 * @param hdr Specifies message type and other meta data
338 * @param msg_ptr Pointer to the message contents.
339 * Must be freed within this function if no error is returned.
340 *
341 * @return 0 upon success; < 0 upon error
342 */
343static int
344sns_ocmem_send_msg(struct sns_ocmem_hdr_s *hdr, void const *msg_ptr)
345{
346 int rv = 0;
347 int err = 0;
348 void *temp = NULL;
349 int size = sizeof(struct sns_ocmem_hdr_s) + hdr->msg_size;
350
351 temp = kzalloc(sizeof(struct sns_ocmem_hdr_s) + hdr->msg_size,
352 GFP_KERNEL);
353 pr_debug("%s size=%d\n", __func__, size);
354
355 if (temp == NULL) {
356 pr_err("%s: allocation failure\n", __func__);
357 rv = -ENOMEM;
358 }
359
360 hdr->dst_module = SNS_OCMEM_MODULE_ADSP;
361 hdr->src_module = SNS_OCMEM_MODULE_KERNEL;
362
363 memcpy(temp, hdr, sizeof(struct sns_ocmem_hdr_s));
364 memcpy((char *)temp + sizeof(struct sns_ocmem_hdr_s),
365 msg_ptr, hdr->msg_size);
366 pr_debug("%s: send msg type: %i size: %i id: %i dst: %i src: %i\n",
367 __func__, hdr->msg_type, hdr->msg_size,
368 hdr->msg_id, hdr->dst_module, hdr->src_module);
369
370 if (hdr == NULL) {
371 pr_err("%s: NULL message header\n", __func__);
372 rv = -EINVAL;
373 } else {
374 if (sns_ctl.smd_ch == NULL) {
375 pr_err("%s: null smd_ch\n", __func__);
376 rv = -EINVAL;
377 }
378 err = smd_write(sns_ctl.smd_ch, temp, size);
379 if (err < 0) {
380 pr_err("%s: smd_write failed %i\n", __func__, err);
381 rv = -ECOMM;
382 } else {
383 pr_debug("%s smd_write successful ret=%d\n",
384 __func__, err);
385 }
386 }
387
388 kfree(temp);
389
390 return rv;
391}
392
393/**
394 * Load ADSP Firmware.
395 */
396
397static int sns_load_adsp(void)
398{
399 pr_debug("%s.\n", __func__);
400
401 sns_ctl.pil = subsystem_get("adsp");
402 if (IS_ERR(sns_ctl.pil)) {
403 pr_err("%s: fail to load ADSP firmware\n", __func__);
404 return -ENODEV;
405 }
406
407 pr_debug("%s: Q6/ADSP image is loaded\n", __func__);
408
409 return 0;
410}
411
412static int sns_ocmem_platform_data_populate(struct platform_device *pdev)
413{
414 int ret;
415 struct msm_bus_scale_pdata *sns_ocmem_bus_scale_pdata = NULL;
416 struct msm_bus_vectors *sns_ocmem_bus_vectors = NULL;
417 struct msm_bus_paths *ocmem_sns_bus_paths = NULL;
418 u32 val;
419
420 if (!pdev->dev.of_node) {
421 pr_err("%s: device tree information missing\n", __func__);
422 return -ENODEV;
423 }
424
425 sns_ocmem_bus_vectors = kzalloc(sizeof(struct msm_bus_vectors),
426 GFP_KERNEL);
427 if (!sns_ocmem_bus_vectors) {
428 dev_err(&pdev->dev, "Failed to allocate memory for platform data\n");
429 return -ENOMEM;
430 }
431
432 ret = of_property_read_u32(pdev->dev.of_node,
433 "qcom,src-id", &val);
434 if (ret) {
435 dev_err(&pdev->dev, "%s: qcom,src-id missing in DT node\n",
436 __func__);
437 goto fail1;
438 }
439 sns_ocmem_bus_vectors->src = val;
440 ret = of_property_read_u32(pdev->dev.of_node,
441 "qcom,dst-id", &val);
442 if (ret) {
443 dev_err(&pdev->dev, "%s: qcom,dst-id missing in DT node\n",
444 __func__);
445 goto fail1;
446 }
447 sns_ocmem_bus_vectors->dst = val;
448 ret = of_property_read_u32(pdev->dev.of_node,
449 "qcom,ab", &val);
450 if (ret) {
451 dev_err(&pdev->dev, "%s: qcom,ab missing in DT node\n",
452 __func__);
453 goto fail1;
454 }
455 sns_ocmem_bus_vectors->ab = val;
456 ret = of_property_read_u32(pdev->dev.of_node,
457 "qcom,ib", &val);
458 if (ret) {
459 dev_err(&pdev->dev, "%s: qcom,ib missing in DT node\n",
460 __func__);
461 goto fail1;
462 }
463 sns_ocmem_bus_vectors->ib = val;
464 ocmem_sns_bus_paths = kzalloc(sizeof(struct msm_bus_paths),
465 GFP_KERNEL);
466
467 if (!ocmem_sns_bus_paths) {
468 dev_err(&pdev->dev, "Failed to allocate memory for platform data\n");
469 goto fail1;
470 }
471 ocmem_sns_bus_paths->num_paths = 1;
472 ocmem_sns_bus_paths->vectors = sns_ocmem_bus_vectors;
473
474 sns_ocmem_bus_scale_pdata =
475 kzalloc(sizeof(struct msm_bus_scale_pdata), GFP_KERNEL);
476 if (!sns_ocmem_bus_scale_pdata) {
477 dev_err(&pdev->dev, "Failed to allocate memory for platform data\n");
478 goto fail2;
479 }
480
481 sns_ocmem_bus_scale_pdata->usecase = ocmem_sns_bus_paths;
482 sns_ocmem_bus_scale_pdata->num_usecases = 1;
483 sns_ocmem_bus_scale_pdata->name = "sensors-ocmem";
484
485 dev_set_drvdata(&pdev->dev, sns_ocmem_bus_scale_pdata);
486 return ret;
487
488fail2:
489 kfree(ocmem_sns_bus_paths);
490fail1:
491 kfree(sns_ocmem_bus_vectors);
492 return ret;
493}
494
495
496/**
497 * Initialize all sensors ocmem driver data fields and register with the
498 * ocmem driver.
499 *
500 * @return 0 upon success; < 0 upon error
501 */
502static int sns_ocmem_init(void)
503{
504 int i, err, ret;
505 struct sns_ocmem_hdr_s addr_req_hdr;
506 struct msm_bus_scale_pdata *sns_ocmem_bus_scale_pdata = NULL;
507
508 pr_debug("%s\n", __func__);
509
510 /* register from OCMEM callack */
511 sns_ctl.ocmem_handle =
512 ocmem_notifier_register(SNS_OCMEM_CLIENT_ID,
513 &sns_ctl.ocmem_nb);
514 if (sns_ctl.ocmem_handle == NULL) {
515 pr_err("OCMEM notifier registration failed\n");
516 return -EFAULT;
517 }
518
519 /* populate platform data */
520 ret = sns_ocmem_platform_data_populate(sns_ctl.pdev);
521 if (ret) {
522 dev_err(&sns_ctl.pdev->dev,
523 "%s: failed to populate platform data, rc = %d\n",
524 __func__, ret);
525 return -ENODEV;
526 }
527 sns_ocmem_bus_scale_pdata = dev_get_drvdata(&sns_ctl.pdev->dev);
528
529 sns_ctl.sns_ocmem_bus_client =
530 msm_bus_scale_register_client(sns_ocmem_bus_scale_pdata);
531
532 if (!sns_ctl.sns_ocmem_bus_client) {
533 pr_err("%s: msm_bus_scale_register_client() failed\n",
534 __func__);
535 return -EFAULT;
536 }
537
538 /* load ADSP first */
539 if (sns_load_adsp() != 0) {
540 pr_err("%s: sns_load_adsp failed\n", __func__);
541 return -EFAULT;
542 }
543
544 /* wait before open SMD channel from kernel to ensure
545 channel has been openned already from ADSP side */
546 pr_debug("%s: sleep for 1000 ms\n", __func__);
547 msleep(1000);
548
549 err = smd_named_open_on_edge(SNS_OCMEM_SMD_CHANNEL,
550 SMD_APPS_QDSP,
551 &sns_ctl.smd_ch,
552 NULL,
553 sns_ocmem_smd_notify_data);
554 if (err != 0) {
555 pr_err("%s: smd_named_open_on_edge failed %i\n", __func__, err);
556 return -EFAULT;
557 }
558
559 pr_debug("%s: SMD channel openned successfuly!\n", __func__);
560 /* wait for the channel ready before writing data */
561 pr_debug("%s: sleep for 1000 ms\n", __func__);
562 msleep(1000);
563 pr_debug("%s sending PHYS_ADDR_REQ\n", __func__);
564 addr_req_hdr.msg_id = SNS_OCMEM_PHYS_ADDR_REQ_V01;
565 addr_req_hdr.msg_type = SNS_OCMEM_MSG_TYPE_REQ;
566 addr_req_hdr.msg_size = 0;
567
568 err = sns_ocmem_send_msg(&addr_req_hdr, NULL);
569 if (err != 0) {
570 pr_err("%s: sns_ocmem_send_msg failed %i\n", __func__, err);
571 return -ECOMM;
572 }
573
574 err = sns_ocmem_wait(DSPS_PHYS_ADDR_SET, 0);
575 if (err != 0) {
576 pr_err("%s: sns_ocmem_wait failed %i\n", __func__, err);
577 return -EFAULT;
578 }
579
580 sns_ctl.map_list.num_chunks = sns_ctl.mem_segments_size;
581 for (i = 0; i < sns_ctl.mem_segments_size; i++) {
582 sns_ctl.map_list.chunks[i].ro =
583 sns_ctl.mem_segments[i].type == 1 ? true : false;
584 sns_ctl.map_list.chunks[i].ddr_paddr =
585 sns_ctl.mem_segments[i].start_address;
586 sns_ctl.map_list.chunks[i].size =
587 sns_ctl.mem_segments[i].size;
588
589 pr_debug("%s: chunks[%d]: ro=%d, ddr_paddr=0x%lx, size=%li",
590 __func__, i,
591 sns_ctl.map_list.chunks[i].ro,
592 sns_ctl.map_list.chunks[i].ddr_paddr,
593 sns_ctl.map_list.chunks[i].size);
594 }
595
596 return 0;
597}
598
599/**
600 * Unmaps memory in ocmem back to DDR, indicates to the ADSP its completion,
601 * and waits for it to finish removing its bandwidth vote.
602 *
603 */
604static void sns_ocmem_unmap(void)
605{
606 unsigned long flags;
607 int err = 0;
608 pr_debug("%s\n", __func__);
609
610 ocmem_set_power_state(SNS_OCMEM_CLIENT_ID,
611 sns_ctl.buf, OCMEM_ON);
612
613 spin_lock_irqsave(&sns_ctl.sns_lock, flags);
614 sns_ctl.sns_ocmem_status &= (~SNS_OCMEM_UNMAP_FAIL &
615 ~SNS_OCMEM_UNMAP_DONE);
616 spin_unlock_irqrestore(&sns_ctl.sns_lock, flags);
617
618 err = ocmem_unmap(SNS_OCMEM_CLIENT_ID,
619 sns_ctl.buf,
620 &sns_ctl.map_list);
621
622 if (err != 0) {
623 pr_err("ocmem_unmap failed %i\n", err);
624 } else {
625 err = sns_ocmem_wait(SNS_OCMEM_UNMAP_DONE |
626 SNS_OCMEM_UNMAP_FAIL, 0);
627
628 if (err == 0) {
629 if (sns_ocmem_is_status_set(SNS_OCMEM_UNMAP_DONE))
630 pr_debug("%s: OCMEM_UNMAP_DONE\n", __func__);
631 else if (sns_ocmem_is_status_set(
632 SNS_OCMEM_UNMAP_FAIL)) {
633 pr_err("%s: OCMEM_UNMAP_FAIL\n", __func__);
634 BUG_ON(true);
635 } else
636 pr_err("%s: status flag not set\n", __func__);
637 } else {
638 pr_err("%s: sns_ocmem_wait failed %i\n",
639 __func__, err);
640 }
641 }
642
643 ocmem_set_power_state(SNS_OCMEM_CLIENT_ID,
644 sns_ctl.buf, OCMEM_OFF);
645}
646
647/**
648 * Waits for allocation to succeed. This may take considerable time if the device
649 * is presently in a high-power use case.
650 *
651 * @return 0 on success; < 0 upon error
652 */
653static int sns_ocmem_wait_for_alloc(void)
654{
655 int err = 0;
656 pr_debug("%s\n", __func__);
657
658 err = sns_ocmem_wait(SNS_OCMEM_ALLOC_GROW |
659 DSPS_HAS_NO_CLIENT, 0);
660
661 if (err == 0) {
662 if (sns_ocmem_is_status_set(DSPS_HAS_NO_CLIENT)) {
663 pr_debug("%s: Lost client while waiting for GROW\n",
664 __func__);
665 ocmem_free(SNS_OCMEM_CLIENT_ID, sns_ctl.buf);
666 sns_ctl.buf = NULL;
667 return -EPIPE;
668 }
669 } else {
670 pr_err("sns_ocmem_wait failed %i\n", err);
671 return -EFAULT;
672 }
673
674 return 0;
675}
676
677/**
678 * Kicks-off the mapping of memory from DDR to ocmem. Waits for the process
679 * to complete, then indicates so to the ADSP.
680 *
681 * @return 0: Success; < 0: Other error
682 */
683static int sns_ocmem_map(void)
684{
685 int err = 0;
686 unsigned long flags;
687 pr_debug("%s\n", __func__);
688
689 spin_lock_irqsave(&sns_ctl.sns_lock, flags);
690 sns_ctl.sns_ocmem_status &=
691 (~SNS_OCMEM_MAP_FAIL & ~SNS_OCMEM_MAP_DONE);
692 spin_unlock_irqrestore(&sns_ctl.sns_lock, flags);
693
694 /* vote for ocmem bus bandwidth */
695 err = msm_bus_scale_client_update_request(
696 sns_ctl.sns_ocmem_bus_client,
697 0);
698 if (err)
699 pr_err("%s: failed to vote for bus bandwidth\n", __func__);
700
701 err = ocmem_map(SNS_OCMEM_CLIENT_ID,
702 sns_ctl.buf,
703 &sns_ctl.map_list);
704
705 if (err != 0) {
706 pr_debug("ocmem_map failed %i\n", err);
707 ocmem_set_power_state(SNS_OCMEM_CLIENT_ID,
708 sns_ctl.buf, OCMEM_OFF);
709 ocmem_free(SNS_OCMEM_CLIENT_ID, sns_ctl.buf);
710 sns_ctl.buf = NULL;
711 } else {
712 err = sns_ocmem_wait(SNS_OCMEM_ALLOC_SHRINK |
713 DSPS_HAS_NO_CLIENT |
714 SNS_OCMEM_MAP_DONE |
715 SNS_OCMEM_MAP_FAIL, 0);
716
717 if (err == 0) {
718 if (sns_ocmem_is_status_set(SNS_OCMEM_MAP_DONE))
719 pr_debug("%s: OCMEM mapping DONE\n", __func__);
720 else if (sns_ocmem_is_status_set(DSPS_HAS_NO_CLIENT)) {
721 pr_debug("%s: Lost client while waiting for MAP\n",
722 __func__);
723 sns_ocmem_unmap();
724 ocmem_free(SNS_OCMEM_CLIENT_ID,
725 sns_ctl.buf);
726 sns_ctl.buf = NULL;
727 err = -EPIPE;
728 } else if (sns_ocmem_is_status_set(
729 SNS_OCMEM_ALLOC_SHRINK)) {
730 pr_debug("%s: SHRINK while wait for MAP\n",
731 __func__);
732 sns_ocmem_unmap();
733 err = ocmem_shrink(SNS_OCMEM_CLIENT_ID,
734 sns_ctl.buf, 0);
735 BUG_ON(err != 0);
736 err = -EFAULT;
737 } else if (sns_ocmem_is_status_set(
738 SNS_OCMEM_MAP_FAIL)) {
739 pr_err("%s: OCMEM mapping fails\n", __func__);
740 ocmem_set_power_state(SNS_OCMEM_CLIENT_ID,
741 sns_ctl.buf,
742 OCMEM_OFF);
743 ocmem_free(SNS_OCMEM_CLIENT_ID,
744 sns_ctl.buf);
745 sns_ctl.buf = NULL;
746 } else
747 pr_err("%s: status flag not set\n", __func__);
748 } else {
749 pr_err("sns_ocmem_wait failed %i\n", err);
750 }
751 }
752
753 return err;
754}
755
756/**
757 * Allocates memory in ocmem and maps to it from DDR.
758 *
759 * @return 0 upon success; <0 upon failure;
760 */
761static int sns_ocmem_alloc(void)
762{
763 int err = 0;
764 unsigned long flags;
765 pr_debug("%s\n", __func__);
766
767 if (sns_ctl.buf == NULL) {
768 spin_lock_irqsave(&sns_ctl.sns_lock, flags);
769 sns_ctl.sns_ocmem_status &= ~SNS_OCMEM_ALLOC_GROW &
770 ~SNS_OCMEM_ALLOC_SHRINK;
771 spin_unlock_irqrestore(&sns_ctl.sns_lock, flags);
772 sns_ctl.buf = ocmem_allocate_nb(SNS_OCMEM_CLIENT_ID,
773 SNS_OCMEM_SIZE);
774
775 if (sns_ctl.buf == NULL) {
776 pr_err("ocmem_allocate_nb returned NULL\n");
777 sns_ctl.ocmem_enabled = false;
778 err = -EFAULT;
779 } else if (sns_ctl.buf->len != 0 &&
780 SNS_OCMEM_SIZE > sns_ctl.buf->len) {
781 pr_err("ocmem_allocate_nb: invalid len %li, Req: %i)\n",
782 sns_ctl.buf->len, SNS_OCMEM_SIZE);
783 sns_ctl.ocmem_enabled = false;
784 err = -EFAULT;
785 }
786 }
787
788 pr_debug("%s OCMEM buf=%lx, buffer len=%li\n", __func__,
789 sns_ctl.buf->addr, sns_ctl.buf->len);
790
791 while (sns_ctl.ocmem_enabled) {
792 if (sns_ctl.buf->len == 0) {
793 pr_debug("%s: Waiting for memory allocation\n",
794 __func__);
795 err = sns_ocmem_wait_for_alloc();
796 if (err == -EPIPE) {
797 pr_debug("%s:Lost client while wait for alloc\n",
798 __func__);
799 break;
800 } else if (err != 0) {
801 pr_err("sns_ocmem_wait_for_alloc failed %i\n",
802 err);
803 break;
804 }
805 }
806
807 ocmem_set_power_state(SNS_OCMEM_CLIENT_ID,
808 sns_ctl.buf,
809 OCMEM_ON);
810
811 err = sns_ocmem_map();
812
813 if (err == -EPIPE) {
814 pr_debug("%s: Lost client while waiting for mapping\n",
815 __func__);
816 break;
817 } else if (err < 0) {
818 pr_debug("%s: Mapping failed, will try again\n",
819 __func__);
820 break;
821 } else if (err == 0) {
822 pr_debug("%s: Mapping finished\n", __func__);
823 break;
824 }
825 }
826
827 return err;
828}
829
830/**
831 * Indicate to the ADSP that unmapping has completed, and wait for the response
832 * that its bandwidth vote has been removed.
833 *
834 * @return 0 Upon success; < 0 upon error
835 */
836static int sns_ocmem_unmap_send(void)
837{
838 int err;
839 struct sns_ocmem_hdr_s msg_hdr;
840 struct sns_ocmem_bw_vote_req_msg_v01 msg;
841 pr_debug("%s\n", __func__);
842
843 memset(&msg, 0, sizeof(struct sns_ocmem_bw_vote_req_msg_v01));
844
845 msg_hdr.msg_id = SNS_OCMEM_BW_VOTE_REQ_V01;
846 msg_hdr.msg_type = SNS_OCMEM_MSG_TYPE_REQ;
847 msg_hdr.msg_size = sizeof(struct sns_ocmem_bw_vote_req_msg_v01);
848 msg.is_map = 0;
849 msg.vectors_valid = 0;
850 msg.vectors_len = 0;
851
852 pr_debug("%s: send bw_vote OFF\n", __func__);
853 err = sns_ocmem_send_msg(&msg_hdr, &msg);
854 if (err != 0) {
855 pr_err("%s: sns_ocmem_send_msg failed %i\n",
856 __func__, err);
857 } else {
858 err = sns_ocmem_wait(DSPS_BW_VOTE_OFF, 0);
859 if (err != 0)
860 pr_err("%s: sns_ocmem_wait failed %i\n", __func__, err);
861 }
862
863 return err;
864}
865
866/**
867 * Indicate to the ADSP that mapping has completed, and wait for the response
868 * that its bandwidth vote has been made.
869 *
870 * @return 0 Upon success; < 0 upon error
871 */
872static int sns_ocmem_map_send(void)
873{
874 int err;
875 struct sns_ocmem_hdr_s msg_hdr;
876 struct sns_ocmem_bw_vote_req_msg_v01 msg;
877 struct ocmem_vectors *vectors;
878 pr_debug("%s\n", __func__);
879
880 memset(&msg, 0, sizeof(struct sns_ocmem_bw_vote_req_msg_v01));
881
882 msg_hdr.msg_id = SNS_OCMEM_BW_VOTE_REQ_V01;
883 msg_hdr.msg_type = SNS_OCMEM_MSG_TYPE_REQ;
884 msg_hdr.msg_size = sizeof(struct sns_ocmem_bw_vote_req_msg_v01);
885 msg.is_map = 1;
886
887 vectors = ocmem_get_vectors(SNS_OCMEM_CLIENT_ID, sns_ctl.buf);
888 if ((vectors != NULL)) {
889 memcpy(&msg.vectors, vectors, sizeof(vectors));
890 /* TODO: set vectors_len */
891 msg.vectors_valid = true;
892 msg.vectors_len = 0;
893 }
894
895 pr_debug("%s: send bw_vote ON\n", __func__);
896 err = sns_ocmem_send_msg(&msg_hdr, &msg);
897 if (err != 0) {
898 pr_err("%s: sns_ocmem_send_msg failed %i\n", __func__, err);
899 } else {
900 err = sns_ocmem_wait(DSPS_BW_VOTE_ON |
901 SNS_OCMEM_ALLOC_SHRINK, 0);
902 if (err != 0)
903 pr_err("%s: sns_ocmem_wait failed %i\n", __func__, err);
904 }
905
906 return err;
907}
908
909/**
910 * Perform the encessary operations to clean-up OCMEM after being notified that
911 * there is no longer a client; if sensors was evicted; or if some error
912 * has occurred.
913 *
914 * @param[i] do_free Whether the memory should be freed (true) or if shrink
915 * should be called instead (false).
916 */
917static void sns_ocmem_evicted(bool do_free)
918{
919 int err = 0;
920 pr_debug("%s\n", __func__);
921
922 sns_ocmem_unmap();
923 if (do_free) {
924 ocmem_free(SNS_OCMEM_CLIENT_ID, sns_ctl.buf);
925 sns_ctl.buf = NULL;
926 } else {
927 err = ocmem_shrink(SNS_OCMEM_CLIENT_ID, sns_ctl.buf, 0);
928 BUG_ON(err != 0);
929 }
930
931 err = sns_ocmem_unmap_send();
932 if (err != 0)
933 pr_err("sns_ocmem_unmap_send failed %i\n", err);
934}
935
936/**
937 * After mapping has completed and the ADSP has reacted appropriately, wait
938 * for a shrink command or word from the ADSP that it no longer has a client.
939 *
940 * @return 0 If no clients; < 0 upon error;
941 */
942static int sns_ocmem_map_done(void)
943{
944 int err = 0;
945 unsigned long flags;
946
947 pr_debug("%s\n", __func__);
948
949 err = sns_ocmem_map_send();
950 if (err != 0) {
951 pr_err("sns_ocmem_map_send failed %i\n", err);
952 sns_ocmem_evicted(true);
953 } else {
954 ocmem_set_power_state(SNS_OCMEM_CLIENT_ID,
955 sns_ctl.buf, OCMEM_OFF);
956
957 pr_debug("%s: Waiting for shrink or 'no client' updates\n",
958 __func__);
959 err = sns_ocmem_wait(DSPS_HAS_NO_CLIENT |
960 SNS_OCMEM_ALLOC_SHRINK, 0);
961 if (err == 0) {
962 if (sns_ocmem_is_status_set(DSPS_HAS_NO_CLIENT)) {
963 pr_debug("%s: No longer have a client\n",
964 __func__);
965 sns_ocmem_evicted(true);
966 } else if (sns_ocmem_is_status_set(
967 SNS_OCMEM_ALLOC_SHRINK)) {
968 pr_debug("%s: Received SHRINK\n", __func__);
969 sns_ocmem_evicted(false);
970
971 spin_lock_irqsave(&sns_ctl.sns_lock, flags);
972 sns_ctl.sns_ocmem_status &=
973 ~SNS_OCMEM_ALLOC_SHRINK;
974 spin_unlock_irqrestore(&sns_ctl.sns_lock,
975 flags);
976 err = -EFAULT;
977 }
978 } else {
979 pr_err("sns_ocmem_wait failed %i\n", err);
980 }
981 }
982
983 return err;
984}
985
986/**
987 * Main function.
988 * Initializes sensors ocmem feature, and waits for an ADSP client.
989 *
990 */
991static void sns_ocmem_main(struct work_struct *work)
992{
993 int err = 0;
994 pr_debug("%s\n", __func__);
995
996 err = sns_ocmem_init();
997 if (err != 0) {
998 pr_err("%s: sns_ocmem_init failed %i\n", __func__, err);
999 return;
1000 }
1001
1002 while (true) {
1003 pr_debug("%s: Waiting for sensor client\n", __func__);
1004 if (sns_ocmem_is_status_set(DSPS_HAS_CLIENT) ||
1005 !sns_ocmem_wait(DSPS_HAS_CLIENT, 0)) {
1006 pr_debug("%s: DSPS_HAS_CLIENT\n", __func__);
1007
1008 err = sns_ocmem_alloc();
1009 if (err != 0) {
1010 pr_err("sns_ocmem_alloc failed %i\n", err);
1011 return;
1012 } else {
1013 err = sns_ocmem_map_done();
1014 if (err != 0) {
1015 pr_err("sns_ocmem_map_done failed %i",
1016 err);
1017 return;
1018 }
1019 }
1020 }
1021 }
1022
1023 ocmem_notifier_unregister(sns_ctl.ocmem_handle,
1024 &sns_ctl.ocmem_nb);
1025}
1026
Naveen Ramaraj93060a42012-11-15 23:23:55 -08001027static int sensors_adsp_open(struct inode *ip, struct file *fp)
1028{
1029 int ret = 0;
1030 pr_debug("%s\n", __func__);
1031 return ret;
1032}
1033
1034static int sensors_adsp_release(struct inode *inode, struct file *file)
1035{
1036 pr_debug("%s\n", __func__);
1037 return 0;
1038}
1039
1040/**
1041 * Read QTimer clock ticks and scale down to 32KHz clock as used
1042 * in DSPS
1043 */
1044static u32 sns_read_qtimer(void)
1045{
1046 u64 val;
1047 val = arch_counter_get_cntpct();
1048 /*
1049 * To convert ticks from 19.2 Mhz clock to 32768 Hz clock:
1050 * x = (value * 32768) / 19200000
1051 * This is same as first left shift the value by 4 bits, i.e. mutiply
1052 * by 16, and then divide by 9375. The latter is preferable since
1053 * QTimer tick (value) is 56-bit, so (value * 32768) could overflow,
1054 * while (value * 16) will never do
1055 */
1056 val <<= 4;
1057 do_div(val, 9375);
1058
1059 pr_debug("%s.count=%llu\n", __func__, val);
1060 return (u32)val;
1061}
1062
1063/**
1064 * IO Control - handle commands from client.
1065 *
1066 */
1067static long sensors_adsp_ioctl(struct file *file,
1068 unsigned int cmd, unsigned long arg)
1069{
1070 int ret = 0;
1071 u32 val = 0;
1072 pr_debug("%s\n", __func__);
1073
1074 switch (cmd) {
1075 case DSPS_IOCTL_READ_SLOW_TIMER:
1076 val = sns_read_qtimer();
1077 ret = put_user(val, (u32 __user *) arg);
1078 break;
1079
1080 default:
1081 ret = -EINVAL;
1082 break;
1083 }
1084
1085 return ret;
1086}
1087
1088/**
1089 * platform driver
1090 *
1091 */
1092const struct file_operations sensors_adsp_fops = {
1093 .owner = THIS_MODULE,
1094 .open = sensors_adsp_open,
1095 .release = sensors_adsp_release,
1096 .unlocked_ioctl = sensors_adsp_ioctl,
1097};
1098
Naveen Ramaraj88f23632012-10-10 12:23:29 -07001099static int sensors_adsp_probe(struct platform_device *pdev)
1100{
Naveen Ramaraj93060a42012-11-15 23:23:55 -08001101 int ret = 0;
Naveen Ramaraj88f23632012-10-10 12:23:29 -07001102 pr_debug("%s.\n", __func__);
Naveen Ramaraj93060a42012-11-15 23:23:55 -08001103 sns_ctl.dev_class = class_create(THIS_MODULE, DRV_NAME);
1104 if (sns_ctl.dev_class == NULL) {
1105 pr_err("%s: class_create fail.\n", __func__);
1106 goto res_err;
1107 }
1108
1109 ret = alloc_chrdev_region(&sns_ctl.dev_num, 0, 1, DRV_NAME);
1110 if (ret) {
1111 pr_err("%s: alloc_chrdev_region fail.\n", __func__);
1112 goto alloc_chrdev_region_err;
1113 }
1114
1115 sns_ctl.dev = device_create(sns_ctl.dev_class, NULL,
1116 sns_ctl.dev_num,
1117 &sns_ctl, DRV_NAME);
1118 if (IS_ERR(sns_ctl.dev)) {
1119 pr_err("%s: device_create fail.\n", __func__);
1120 goto device_create_err;
1121 }
1122
1123 sns_ctl.cdev = cdev_alloc();
1124 if (sns_ctl.cdev == NULL) {
1125 pr_err("%s: cdev_alloc fail.\n", __func__);
1126 goto cdev_alloc_err;
1127 }
1128 cdev_init(sns_ctl.cdev, &sensors_adsp_fops);
1129 sns_ctl.cdev->owner = THIS_MODULE;
1130
1131 ret = cdev_add(sns_ctl.cdev, sns_ctl.dev_num, 1);
1132 if (ret) {
1133 pr_err("%s: cdev_add fail.\n", __func__);
1134 goto cdev_add_err;
1135 }
Naveen Ramaraj88f23632012-10-10 12:23:29 -07001136
1137 sns_ctl.sns_workqueue =
1138 alloc_workqueue("sns_ocmem", WQ_NON_REENTRANT, 0);
1139 if (!sns_ctl.sns_workqueue) {
Naveen Ramaraj93060a42012-11-15 23:23:55 -08001140 pr_err("%s: Failed to create work queue\n",
Naveen Ramaraj88f23632012-10-10 12:23:29 -07001141 __func__);
Naveen Ramaraj93060a42012-11-15 23:23:55 -08001142 goto cdev_add_err;
Naveen Ramaraj88f23632012-10-10 12:23:29 -07001143 }
1144
1145 init_waitqueue_head(&sns_ctl.sns_wait);
1146 spin_lock_init(&sns_ctl.sns_lock);
1147
1148 sns_ctl.ocmem_handle = NULL;
1149 sns_ctl.buf = NULL;
1150 sns_ctl.sns_ocmem_status = 0;
1151 sns_ctl.ocmem_enabled = true;
1152 sns_ctl.ocmem_nb.notifier_call = sns_ocmem_drv_cb;
1153 sns_ctl.smd_ch = NULL;
1154 sns_ctl.pdev = pdev;
1155
1156 INIT_WORK(&sns_ctl.sns_work, sns_ocmem_main);
1157 queue_work(sns_ctl.sns_workqueue, &sns_ctl.sns_work);
1158
1159 return 0;
Naveen Ramaraj93060a42012-11-15 23:23:55 -08001160
1161cdev_add_err:
1162 kfree(sns_ctl.cdev);
1163cdev_alloc_err:
1164 device_destroy(sns_ctl.dev_class, sns_ctl.dev_num);
1165device_create_err:
1166 unregister_chrdev_region(sns_ctl.dev_num, 1);
1167alloc_chrdev_region_err:
1168 class_destroy(sns_ctl.dev_class);
1169res_err:
1170 return -ENODEV;
Naveen Ramaraj88f23632012-10-10 12:23:29 -07001171}
1172
1173static int sensors_adsp_remove(struct platform_device *pdev)
1174{
1175 struct msm_bus_scale_pdata *sns_ocmem_bus_scale_pdata = NULL;
1176 pr_debug("%s.\n", __func__);
1177
1178 sns_ocmem_bus_scale_pdata = (struct msm_bus_scale_pdata *)
1179 dev_get_drvdata(&pdev->dev);
1180
1181 kfree(sns_ocmem_bus_scale_pdata->usecase->vectors);
1182 kfree(sns_ocmem_bus_scale_pdata->usecase);
1183 kfree(sns_ocmem_bus_scale_pdata);
1184
1185 ocmem_notifier_unregister(sns_ctl.ocmem_handle,
1186 &sns_ctl.ocmem_nb);
1187 destroy_workqueue(sns_ctl.sns_workqueue);
Naveen Ramaraj93060a42012-11-15 23:23:55 -08001188
1189 cdev_del(sns_ctl.cdev);
1190 kfree(sns_ctl.cdev);
1191 sns_ctl.cdev = NULL;
1192 device_destroy(sns_ctl.dev_class, sns_ctl.dev_num);
1193 unregister_chrdev_region(sns_ctl.dev_num, 1);
1194 class_destroy(sns_ctl.dev_class);
1195
Naveen Ramaraj88f23632012-10-10 12:23:29 -07001196 return 0;
1197}
1198
1199static const struct of_device_id msm_adsp_sensors_dt_match[] = {
1200 {.compatible = "qcom,msm-adsp-sensors"},
1201 {}
1202};
1203MODULE_DEVICE_TABLE(of, msm_adsp_sensors_dt_match);
1204
1205
1206static struct platform_driver sensors_adsp_driver = {
1207 .driver = {
1208 .name = "sensors-adsp",
1209 .owner = THIS_MODULE,
1210 .of_match_table = msm_adsp_sensors_dt_match,
1211 },
1212 .probe = sensors_adsp_probe,
1213 .remove = sensors_adsp_remove,
1214};
1215
1216/**
1217 * Module Init.
1218 */
1219static int sensors_adsp_init(void)
1220{
1221 int rc;
1222 pr_debug("%s.\n", __func__);
1223 pr_debug("%s driver version %s.\n", DRV_NAME, DRV_VERSION);
1224
1225 rc = platform_driver_register(&sensors_adsp_driver);
1226
1227 if (rc) {
1228 pr_err("%s: Failed to register sensors adsp driver\n",
1229 __func__);
1230 return rc;
1231 }
1232
1233 return 0;
1234}
1235
1236/**
1237 * Module Exit.
1238 */
1239static void sensors_adsp_exit(void)
1240{
1241 pr_debug("%s.\n", __func__);
1242 platform_driver_unregister(&sensors_adsp_driver);
1243}
1244
1245module_init(sensors_adsp_init);
1246module_exit(sensors_adsp_exit);
1247
1248MODULE_LICENSE("GPL v2");
1249MODULE_DESCRIPTION("Sensors ADSP driver");