blob: c8e2dd3209ae67ba5f241bc686469578710a3f1b [file] [log] [blame]
Anji Jonnala5063e042013-03-09 09:49:11 +05301/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002 *
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
14#include <linux/module.h>
15#include <linux/kernel.h>
16#include <linux/delay.h>
17#include <linux/init.h>
18#include <linux/io.h>
19#include <linux/slab.h>
Praveen Chidambaramaa9d52b2012-04-02 11:09:47 -060020#include <linux/of.h>
21#include <linux/of_address.h>
22#include <linux/platform_device.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070023#include <mach/msm_iomap.h>
Praveen Chidambaram76679d42011-12-16 14:19:02 -070024#include <mach/socinfo.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070025#include "spm.h"
26#include "spm_driver.h"
27
28struct msm_spm_power_modes {
29 uint32_t mode;
30 bool notify_rpm;
31 uint32_t start_addr;
32
33};
34
35struct msm_spm_device {
36 struct msm_spm_driver_data reg_data;
37 struct msm_spm_power_modes *modes;
38 uint32_t num_modes;
Anji Jonnala5063e042013-03-09 09:49:11 +053039 uint32_t cpu_vdd;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070040};
41
Praveen Chidambarambcd483b2012-09-16 14:54:35 -060042struct msm_spm_vdd_info {
43 uint32_t cpu;
44 uint32_t vlevel;
45 int err;
46};
47
Praveen Chidambaramaa9d52b2012-04-02 11:09:47 -060048static struct msm_spm_device msm_spm_l2_device;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070049static DEFINE_PER_CPU_SHARED_ALIGNED(struct msm_spm_device, msm_cpu_spm_device);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070050
Praveen Chidambarambcd483b2012-09-16 14:54:35 -060051
Praveen Chidambarambcd483b2012-09-16 14:54:35 -060052static void msm_spm_smp_set_vdd(void *data)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070053{
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070054 struct msm_spm_device *dev;
Praveen Chidambarambcd483b2012-09-16 14:54:35 -060055 struct msm_spm_vdd_info *info = (struct msm_spm_vdd_info *)data;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070056
Praveen Chidambarambcd483b2012-09-16 14:54:35 -060057 dev = &per_cpu(msm_cpu_spm_device, info->cpu);
Anji Jonnala5063e042013-03-09 09:49:11 +053058 dev->cpu_vdd = info->vlevel;
Praveen Chidambarambcd483b2012-09-16 14:54:35 -060059 info->err = msm_spm_drv_set_vdd(&dev->reg_data, info->vlevel);
60}
61
Praveen Chidambaram7347bfe2012-11-01 15:21:10 -060062/**
63 * msm_spm_set_vdd(): Set core voltage
64 * @cpu: core id
65 * @vlevel: Encoded PMIC data.
66 */
Praveen Chidambarambcd483b2012-09-16 14:54:35 -060067int msm_spm_set_vdd(unsigned int cpu, unsigned int vlevel)
68{
69 struct msm_spm_vdd_info info;
70 int ret;
71
72 info.cpu = cpu;
73 info.vlevel = vlevel;
74
Praveen Chidambaram8624ce72012-10-05 17:11:33 -060075 if (cpu_online(cpu)) {
76 /**
77 * We do not want to set the voltage of another core from
78 * this core, as its possible that we may race the vdd change
79 * with the SPM state machine of that core, which could also
80 * be changing the voltage of that core during power collapse.
81 * Hence, set the function to be executed on that core and block
82 * until the vdd change is complete.
83 */
84 ret = smp_call_function_single(cpu, msm_spm_smp_set_vdd,
85 &info, true);
86 if (!ret)
87 ret = info.err;
88 } else {
89 /**
90 * Since the core is not online, it is safe to set the vdd
91 * directly.
92 */
93 msm_spm_smp_set_vdd(&info);
Praveen Chidambarambcd483b2012-09-16 14:54:35 -060094 ret = info.err;
Praveen Chidambaram8624ce72012-10-05 17:11:33 -060095 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070096
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070097 return ret;
98}
Praveen Chidambaramaa9d52b2012-04-02 11:09:47 -060099EXPORT_SYMBOL(msm_spm_set_vdd);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700100
Praveen Chidambaram7347bfe2012-11-01 15:21:10 -0600101/**
102 * msm_spm_get_vdd(): Get core voltage
103 * @cpu: core id
104 * @return: Returns encoded PMIC data.
105 */
Praveen Chidambaram4133ba12012-09-29 22:27:03 -0600106unsigned int msm_spm_get_vdd(unsigned int cpu)
107{
108 struct msm_spm_device *dev;
109
110 dev = &per_cpu(msm_cpu_spm_device, cpu);
Anji Jonnala5063e042013-03-09 09:49:11 +0530111 return dev->cpu_vdd;
Praveen Chidambaram4133ba12012-09-29 22:27:03 -0600112}
113EXPORT_SYMBOL(msm_spm_get_vdd);
114
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700115static int msm_spm_dev_set_low_power_mode(struct msm_spm_device *dev,
116 unsigned int mode, bool notify_rpm)
117{
118 uint32_t i;
119 uint32_t start_addr = 0;
120 int ret = -EINVAL;
121
122 if (mode == MSM_SPM_MODE_DISABLED) {
123 ret = msm_spm_drv_set_spm_enable(&dev->reg_data, false);
124 } else if (!msm_spm_drv_set_spm_enable(&dev->reg_data, true)) {
125 for (i = 0; i < dev->num_modes; i++) {
126 if ((dev->modes[i].mode == mode) &&
127 (dev->modes[i].notify_rpm == notify_rpm)) {
128 start_addr = dev->modes[i].start_addr;
129 break;
130 }
131 }
132 ret = msm_spm_drv_set_low_power_mode(&dev->reg_data,
133 start_addr);
134 }
135 return ret;
136}
137
Stephen Boyddb354112012-05-09 14:24:58 -0700138static int __devinit msm_spm_dev_init(struct msm_spm_device *dev,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700139 struct msm_spm_platform_data *data)
140{
141 int i, ret = -ENOMEM;
142 uint32_t offset = 0;
143
144 dev->num_modes = data->num_modes;
145 dev->modes = kmalloc(
146 sizeof(struct msm_spm_power_modes) * dev->num_modes,
147 GFP_KERNEL);
148
149 if (!dev->modes)
150 goto spm_failed_malloc;
151
Praveen Chidambaramaa9d52b2012-04-02 11:09:47 -0600152 dev->reg_data.ver_reg = data->ver_reg;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700153 ret = msm_spm_drv_init(&dev->reg_data, data);
154
155 if (ret)
156 goto spm_failed_init;
157
158 for (i = 0; i < dev->num_modes; i++) {
159
Praveen Chidambaramaa9d52b2012-04-02 11:09:47 -0600160 /* Default offset is 0 and gets updated as we write more
161 * sequences into SPM
162 */
163 dev->modes[i].start_addr = offset;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700164 ret = msm_spm_drv_write_seq_data(&dev->reg_data,
Praveen Chidambaramaa9d52b2012-04-02 11:09:47 -0600165 data->modes[i].cmd, &offset);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700166 if (ret < 0)
167 goto spm_failed_init;
168
169 dev->modes[i].mode = data->modes[i].mode;
170 dev->modes[i].notify_rpm = data->modes[i].notify_rpm;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700171 }
172 msm_spm_drv_flush_seq_entry(&dev->reg_data);
173 return 0;
174
175spm_failed_init:
176 kfree(dev->modes);
177spm_failed_malloc:
178 return ret;
179}
180
Praveen Chidambaram7347bfe2012-11-01 15:21:10 -0600181/**
182 * msm_spm_turn_on_cpu_rail(): Power on cpu rail before turning on core
183 * @cpu: core id
184 */
Praveen Chidambaramc0750ca2012-01-08 10:03:28 -0700185int msm_spm_turn_on_cpu_rail(unsigned int cpu)
186{
187 uint32_t val = 0;
188 uint32_t timeout = 0;
189 void *reg = NULL;
Stepan Moskovchenko2b0b06e2012-02-03 15:03:52 -0800190 void *saw_bases[] = {
191 0,
192 MSM_SAW1_BASE,
193 MSM_SAW2_BASE,
194 MSM_SAW3_BASE
195 };
Praveen Chidambaramc0750ca2012-01-08 10:03:28 -0700196
Stepan Moskovchenko2b0b06e2012-02-03 15:03:52 -0800197 if (cpu == 0 || cpu >= num_possible_cpus())
Praveen Chidambaramc0750ca2012-01-08 10:03:28 -0700198 return -EINVAL;
199
Stepan Moskovchenko2b0b06e2012-02-03 15:03:52 -0800200 reg = saw_bases[cpu];
Praveen Chidambaramc0750ca2012-01-08 10:03:28 -0700201
Stepan Moskovchenko5b9e7762012-09-21 20:32:17 -0700202 if (soc_class_is_msm8960() || soc_class_is_msm8930() ||
203 soc_class_is_apq8064()) {
Stepan Moskovchenko2b0b06e2012-02-03 15:03:52 -0800204 val = 0xA4;
205 reg += 0x14;
206 timeout = 512;
Praveen Chidambaramc0750ca2012-01-08 10:03:28 -0700207 } else {
208 return -ENOSYS;
209 }
210
211 writel_relaxed(val, reg);
212 mb();
213 udelay(timeout);
214
215 return 0;
216}
217EXPORT_SYMBOL(msm_spm_turn_on_cpu_rail);
218
Praveen Chidambaramaa9d52b2012-04-02 11:09:47 -0600219void msm_spm_reinit(void)
220{
221 unsigned int cpu;
222 for_each_possible_cpu(cpu)
223 msm_spm_drv_reinit(&per_cpu(msm_cpu_spm_device.reg_data, cpu));
224}
225EXPORT_SYMBOL(msm_spm_reinit);
226
Praveen Chidambaram7347bfe2012-11-01 15:21:10 -0600227/**
228 * msm_spm_set_low_power_mode() - Configure SPM start address for low power mode
229 * @mode: SPM LPM mode to enter
230 * @notify_rpm: Notify RPM in this mode
231 */
Praveen Chidambaramaa9d52b2012-04-02 11:09:47 -0600232int msm_spm_set_low_power_mode(unsigned int mode, bool notify_rpm)
233{
234 struct msm_spm_device *dev = &__get_cpu_var(msm_cpu_spm_device);
235 return msm_spm_dev_set_low_power_mode(dev, mode, notify_rpm);
236}
237EXPORT_SYMBOL(msm_spm_set_low_power_mode);
238
Praveen Chidambaram7347bfe2012-11-01 15:21:10 -0600239/**
240 * msm_spm_init(): Board initalization function
241 * @data: platform specific SPM register configuration data
242 * @nr_devs: Number of SPM devices being initialized
243 */
Praveen Chidambaramaa9d52b2012-04-02 11:09:47 -0600244int __init msm_spm_init(struct msm_spm_platform_data *data, int nr_devs)
245{
246 unsigned int cpu;
247 int ret = 0;
248
249 BUG_ON((nr_devs < num_possible_cpus()) || !data);
250
251 for_each_possible_cpu(cpu) {
252 struct msm_spm_device *dev = &per_cpu(msm_cpu_spm_device, cpu);
253 ret = msm_spm_dev_init(dev, &data[cpu]);
254 if (ret < 0) {
255 pr_warn("%s():failed CPU:%u ret:%d\n", __func__,
256 cpu, ret);
257 break;
258 }
259 }
260
261 return ret;
262}
263
264#ifdef CONFIG_MSM_L2_SPM
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700265
Praveen Chidambaram7347bfe2012-11-01 15:21:10 -0600266/**
267 * msm_spm_l2_set_low_power_mode(): Configure L2 SPM start address
268 * for low power mode
269 * @mode: SPM LPM mode to enter
270 * @notify_rpm: Notify RPM in this mode
271 */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700272int msm_spm_l2_set_low_power_mode(unsigned int mode, bool notify_rpm)
273{
274 return msm_spm_dev_set_low_power_mode(
275 &msm_spm_l2_device, mode, notify_rpm);
276}
Praveen Chidambaramaa9d52b2012-04-02 11:09:47 -0600277EXPORT_SYMBOL(msm_spm_l2_set_low_power_mode);
Maheshkumar Sivasubramanian4ac23762011-11-02 10:03:06 -0600278
279void msm_spm_l2_reinit(void)
280{
281 msm_spm_drv_reinit(&msm_spm_l2_device.reg_data);
282}
Praveen Chidambaramaa9d52b2012-04-02 11:09:47 -0600283EXPORT_SYMBOL(msm_spm_l2_reinit);
284
Praveen Chidambaram7347bfe2012-11-01 15:21:10 -0600285/**
286 * msm_spm_apcs_set_vdd(): Set Apps processor core sub-system voltage
287 * @vlevel: Encoded PMIC data.
288 */
Praveen Chidambaramaa9d52b2012-04-02 11:09:47 -0600289int msm_spm_apcs_set_vdd(unsigned int vlevel)
290{
291 return msm_spm_drv_set_vdd(&msm_spm_l2_device.reg_data, vlevel);
292}
293EXPORT_SYMBOL(msm_spm_apcs_set_vdd);
294
Praveen Chidambaram7347bfe2012-11-01 15:21:10 -0600295/**
296 * msm_spm_apcs_set_phase(): Set number of SMPS phases.
297 * phase_cnt: Number of phases to be set active
298 */
Praveen Chidambaramaa9d52b2012-04-02 11:09:47 -0600299int msm_spm_apcs_set_phase(unsigned int phase_cnt)
300{
Praveen Chidambaram1dbe4952012-10-03 17:06:02 -0600301 return msm_spm_drv_set_pmic_data(&msm_spm_l2_device.reg_data,
302 MSM_SPM_PMIC_PHASE_PORT, phase_cnt);
Praveen Chidambaramaa9d52b2012-04-02 11:09:47 -0600303}
304EXPORT_SYMBOL(msm_spm_apcs_set_phase);
305
Praveen Chidambaram7347bfe2012-11-01 15:21:10 -0600306/** msm_spm_enable_fts_lpm() : Enable FTS to switch to low power
307 * when the cores are in low power modes
308 * @mode: The mode configuration for FTS
309 */
Praveen Chidambaram1dbe4952012-10-03 17:06:02 -0600310int msm_spm_enable_fts_lpm(uint32_t mode)
311{
312 return msm_spm_drv_set_pmic_data(&msm_spm_l2_device.reg_data,
313 MSM_SPM_PMIC_PFM_PORT, mode);
314}
315EXPORT_SYMBOL(msm_spm_enable_fts_lpm);
316
Praveen Chidambaram7347bfe2012-11-01 15:21:10 -0600317/**
318 * msm_spm_l2_init(): Board initialization function
319 * @data: SPM target specific register configuration
320 */
Praveen Chidambaramaa9d52b2012-04-02 11:09:47 -0600321int __init msm_spm_l2_init(struct msm_spm_platform_data *data)
322{
323 return msm_spm_dev_init(&msm_spm_l2_device, data);
324}
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700325#endif
Praveen Chidambaramaa9d52b2012-04-02 11:09:47 -0600326
Sathish Ambley86487e52012-06-11 13:46:11 -0700327static int __devinit msm_spm_dev_probe(struct platform_device *pdev)
Praveen Chidambaramaa9d52b2012-04-02 11:09:47 -0600328{
329 int ret = 0;
330 int cpu = 0;
331 int i = 0;
332 struct device_node *node = pdev->dev.of_node;
333 struct msm_spm_platform_data spm_data;
334 char *key = NULL;
335 uint32_t val = 0;
336 struct msm_spm_seq_entry modes[MSM_SPM_MODE_NR];
337 size_t len = 0;
338 struct msm_spm_device *dev = NULL;
339 struct resource *res = NULL;
340 uint32_t mode_count = 0;
341
342 struct spm_of {
343 char *key;
344 uint32_t id;
345 };
346
347 struct spm_of spm_of_data[] = {
348 {"qcom,saw2-cfg", MSM_SPM_REG_SAW2_CFG},
349 {"qcom,saw2-avs-ctl", MSM_SPM_REG_SAW2_AVS_CTL},
350 {"qcom,saw2-avs-hysteresis", MSM_SPM_REG_SAW2_AVS_HYSTERESIS},
Praveen Chidambaramaa9d52b2012-04-02 11:09:47 -0600351 {"qcom,saw2-avs-limit", MSM_SPM_REG_SAW2_AVS_LIMIT},
Praveen Chidambaram2772d832012-08-22 11:50:34 -0600352 {"qcom,saw2-avs-dly", MSM_SPM_REG_SAW2_AVS_DLY},
Praveen Chidambaramaa9d52b2012-04-02 11:09:47 -0600353 {"qcom,saw2-spm-dly", MSM_SPM_REG_SAW2_SPM_DLY},
Praveen Chidambaram2772d832012-08-22 11:50:34 -0600354 {"qcom,saw2-spm-ctl", MSM_SPM_REG_SAW2_SPM_CTL},
Praveen Chidambaramaa9d52b2012-04-02 11:09:47 -0600355 {"qcom,saw2-pmic-data0", MSM_SPM_REG_SAW2_PMIC_DATA_0},
356 {"qcom,saw2-pmic-data1", MSM_SPM_REG_SAW2_PMIC_DATA_1},
357 {"qcom,saw2-pmic-data2", MSM_SPM_REG_SAW2_PMIC_DATA_2},
358 {"qcom,saw2-pmic-data3", MSM_SPM_REG_SAW2_PMIC_DATA_3},
359 {"qcom,saw2-pmic-data4", MSM_SPM_REG_SAW2_PMIC_DATA_4},
360 {"qcom,saw2-pmic-data5", MSM_SPM_REG_SAW2_PMIC_DATA_5},
361 {"qcom,saw2-pmic-data6", MSM_SPM_REG_SAW2_PMIC_DATA_6},
362 {"qcom,saw2-pmic-data7", MSM_SPM_REG_SAW2_PMIC_DATA_7},
363 };
364
365 struct mode_of {
366 char *key;
367 uint32_t id;
368 uint32_t notify_rpm;
369 };
370
Mahesh Sivasubramanian11373322012-06-14 11:17:20 -0600371 struct mode_of of_cpu_modes[] = {
372 {"qcom,saw2-spm-cmd-wfi", MSM_SPM_MODE_CLOCK_GATING, 0},
373 {"qcom,saw2-spm-cmd-ret", MSM_SPM_MODE_POWER_RETENTION, 0},
374 {"qcom,saw2-spm-cmd-spc", MSM_SPM_MODE_POWER_COLLAPSE, 0},
375 {"qcom,saw2-spm-cmd-pc", MSM_SPM_MODE_POWER_COLLAPSE, 1},
Praveen Chidambaramaa9d52b2012-04-02 11:09:47 -0600376 };
377
Mahesh Sivasubramanian11373322012-06-14 11:17:20 -0600378 struct mode_of of_l2_modes[] = {
Mahesh Sivasubramanian1826ae42012-11-07 14:37:13 -0700379 {"qcom,saw2-spm-cmd-ret", MSM_SPM_L2_MODE_RETENTION, 0},
Mahesh Sivasubramanian11373322012-06-14 11:17:20 -0600380 {"qcom,saw2-spm-cmd-gdhs", MSM_SPM_L2_MODE_GDHS, 1},
381 {"qcom,saw2-spm-cmd-pc", MSM_SPM_L2_MODE_POWER_COLLAPSE, 1},
382 };
383
384 struct mode_of *mode_of_data;
385 int num_modes;
386
Praveen Chidambaramaa9d52b2012-04-02 11:09:47 -0600387 memset(&spm_data, 0, sizeof(struct msm_spm_platform_data));
388 memset(&modes, 0,
389 (MSM_SPM_MODE_NR - 2) * sizeof(struct msm_spm_seq_entry));
390
391 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
392 if (!res)
393 goto fail;
394
395 spm_data.reg_base_addr = devm_ioremap(&pdev->dev, res->start,
396 resource_size(res));
397 if (!spm_data.reg_base_addr)
398 return -ENOMEM;
399
400 key = "qcom,core-id";
401 ret = of_property_read_u32(node, key, &val);
402 if (ret)
403 goto fail;
404 cpu = val;
405
406 key = "qcom,saw2-ver-reg";
407 ret = of_property_read_u32(node, key, &val);
408 if (ret)
409 goto fail;
410 spm_data.ver_reg = val;
411
412 key = "qcom,vctl-timeout-us";
413 ret = of_property_read_u32(node, key, &val);
414 if (!ret)
415 spm_data.vctl_timeout_us = val;
416
Mahesh Sivasubramanian11373322012-06-14 11:17:20 -0600417 /*
418 * Device with id 0..NR_CPUS are SPM for apps cores
419 * Device with id 0xFFFF is for L2 SPM.
420 */
421 if (cpu >= 0 && cpu < num_possible_cpus()) {
422 mode_of_data = of_cpu_modes;
423 num_modes = ARRAY_SIZE(of_cpu_modes);
424 dev = &per_cpu(msm_cpu_spm_device, cpu);
425
426 } else {
427 mode_of_data = of_l2_modes;
428 num_modes = ARRAY_SIZE(of_l2_modes);
429 dev = &msm_spm_l2_device;
430 }
431
Praveen Chidambaram1dbe4952012-10-03 17:06:02 -0600432 spm_data.vctl_port = -1;
433 spm_data.phase_port = -1;
434 spm_data.pfm_port = -1;
435
436 /* optional */
437 if (dev == &msm_spm_l2_device) {
438 key = "qcom,vctl-port";
439 ret = of_property_read_u32(node, key, &val);
440 if (!ret)
441 spm_data.vctl_port = val;
442
443 key = "qcom,phase-port";
444 ret = of_property_read_u32(node, key, &val);
445 if (!ret)
446 spm_data.phase_port = val;
447
448 key = "qcom,pfm-port";
449 ret = of_property_read_u32(node, key, &val);
450 if (!ret)
451 spm_data.pfm_port = val;
452 }
453
454 for (i = 0; i < ARRAY_SIZE(spm_of_data); i++) {
455 ret = of_property_read_u32(node, spm_of_data[i].key, &val);
456 if (ret)
457 continue;
458 spm_data.reg_init_values[spm_of_data[i].id] = val;
459 }
460
Mahesh Sivasubramanian11373322012-06-14 11:17:20 -0600461 for (i = 0; i < num_modes; i++) {
Praveen Chidambaramaa9d52b2012-04-02 11:09:47 -0600462 key = mode_of_data[i].key;
463 modes[mode_count].cmd =
464 (uint8_t *)of_get_property(node, key, &len);
465 if (!modes[mode_count].cmd)
466 continue;
467 modes[mode_count].mode = mode_of_data[i].id;
468 modes[mode_count].notify_rpm = mode_of_data[i].notify_rpm;
469 mode_count++;
470 }
471
472 spm_data.modes = modes;
473 spm_data.num_modes = mode_count;
474
Praveen Chidambaramaa9d52b2012-04-02 11:09:47 -0600475 ret = msm_spm_dev_init(dev, &spm_data);
Mahesh Sivasubramanian11373322012-06-14 11:17:20 -0600476
Praveen Chidambaramaa9d52b2012-04-02 11:09:47 -0600477 if (ret < 0)
478 pr_warn("%s():failed core-id:%u ret:%d\n", __func__, cpu, ret);
479
480 return ret;
481
482fail:
483 pr_err("%s: Failed reading node=%s, key=%s\n",
484 __func__, node->full_name, key);
485 return -EFAULT;
486}
487
Sathish Ambley86487e52012-06-11 13:46:11 -0700488static struct of_device_id msm_spm_match_table[] = {
Praveen Chidambaramaa9d52b2012-04-02 11:09:47 -0600489 {.compatible = "qcom,spm-v2"},
490 {},
491};
492
Sathish Ambley86487e52012-06-11 13:46:11 -0700493static struct platform_driver msm_spm_device_driver = {
Praveen Chidambaramaa9d52b2012-04-02 11:09:47 -0600494 .probe = msm_spm_dev_probe,
495 .driver = {
496 .name = "spm-v2",
497 .owner = THIS_MODULE,
498 .of_match_table = msm_spm_match_table,
499 },
500};
501
Praveen Chidambaram7347bfe2012-11-01 15:21:10 -0600502/**
503 * msm_spm_device_init(): Device tree initialization function
504 */
Praveen Chidambaramaa9d52b2012-04-02 11:09:47 -0600505int __init msm_spm_device_init(void)
506{
507 return platform_driver_register(&msm_spm_device_driver);
508}