blob: e74fdf98f5ce1b5c53139990b653d3c117880b91 [file] [log] [blame]
Joonwoo Park4a14a552012-08-02 11:03:21 -07001/*
Bharath Ramachandramurthy15c509c2013-03-22 16:31:08 -07002 * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
Joonwoo Park4a14a552012-08-02 11:03:21 -07003 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 and
6 * only version 2 as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 */
13
14#include <linux/init.h>
15#include <linux/kernel.h>
16#include <linux/module.h>
17#include <linux/err.h>
18#include <linux/delay.h>
19#include <linux/platform_device.h>
Stephen Boyd77db8bb2012-06-27 15:15:16 -070020#include <mach/subsystem_restart.h>
Joonwoo Park4a14a552012-08-02 11:03:21 -070021#include <mach/qdsp6v2/apr.h>
Venkat Sudhir480db8a2012-11-09 15:31:50 -080022#include <linux/of_device.h>
Joonwoo Park4a14a552012-08-02 11:03:21 -070023
24#define Q6_PIL_GET_DELAY_MS 100
25
26struct adsp_loader_private {
27 void *pil_h;
28};
29
30static int adsp_loader_probe(struct platform_device *pdev)
31{
32 struct adsp_loader_private *priv;
33 int rc = 0;
Venkat Sudhir480db8a2012-11-09 15:31:50 -080034 const char *adsp_dt = "qcom,adsp-state";
35 u32 adsp_state;
Joonwoo Park4a14a552012-08-02 11:03:21 -070036
Venkat Sudhir480db8a2012-11-09 15:31:50 -080037 rc = of_property_read_u32(pdev->dev.of_node, adsp_dt, &adsp_state);
38 if (rc) {
39 dev_err(&pdev->dev,
40 "%s: ADSP state = %x\n", __func__, adsp_state);
41 return rc;
Joonwoo Park4a14a552012-08-02 11:03:21 -070042 }
43
Venkat Sudhir480db8a2012-11-09 15:31:50 -080044 if (adsp_state == APR_SUBSYS_DOWN) {
45 priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
46 if (!priv)
47 return -ENOMEM;
Joonwoo Park4a14a552012-08-02 11:03:21 -070048
Venkat Sudhir480db8a2012-11-09 15:31:50 -080049 platform_set_drvdata(pdev, priv);
50
51 priv->pil_h = subsystem_get("adsp");
52 if (IS_ERR(priv->pil_h)) {
53 pr_err("%s: pil get adsp failed, error:%d\n",
54 __func__, rc);
55 devm_kfree(&pdev->dev, priv);
56 goto fail;
57 }
58
Venkat Sudhir480db8a2012-11-09 15:31:50 -080059 /* Set the state of the ADSP in APR driver */
60 apr_set_q6_state(APR_SUBSYS_LOADED);
61 } else if (adsp_state == APR_SUBSYS_LOADED) {
62 dev_dbg(&pdev->dev,
63 "%s:MDM9x25 ADSP state = %x\n", __func__, adsp_state);
64 apr_set_q6_state(APR_SUBSYS_LOADED);
65 }
Joonwoo Park4a14a552012-08-02 11:03:21 -070066
67 /* Query for MMPM API */
68
69 pr_info("%s: Q6/ADSP image is loaded\n", __func__);
70fail:
71 return rc;
72}
73
74static int adsp_loader_remove(struct platform_device *pdev)
75{
76 struct adsp_loader_private *priv;
77
78 priv = platform_get_drvdata(pdev);
Venkat Sudhir480db8a2012-11-09 15:31:50 -080079 if (priv != NULL)
80 subsystem_put(priv->pil_h);
Joonwoo Park4a14a552012-08-02 11:03:21 -070081 pr_info("%s: Q6/ADSP image is unloaded\n", __func__);
82
83 return 0;
84}
85
86static const struct of_device_id adsp_loader_dt_match[] = {
87 { .compatible = "qcom,adsp-loader" },
88 { }
89};
90MODULE_DEVICE_TABLE(of, adsp_loader_dt_match);
91
92static struct platform_driver adsp_loader_driver = {
93 .driver = {
94 .name = "adsp-loader",
95 .owner = THIS_MODULE,
96 .of_match_table = adsp_loader_dt_match,
97 },
98 .probe = adsp_loader_probe,
99 .remove = __devexit_p(adsp_loader_remove),
100};
101
102static int __init adsp_loader_init(void)
103{
104 return platform_driver_register(&adsp_loader_driver);
105}
106module_init(adsp_loader_init);
107
108static void __exit adsp_loader_exit(void)
109{
110 platform_driver_unregister(&adsp_loader_driver);
111}
112module_exit(adsp_loader_exit);
113
114MODULE_DESCRIPTION("ADSP Loader module");
115MODULE_LICENSE("GPL v2");