6
6
* SAW power controller driver
7
7
*/
8
8
9
- #include <linux/kernel.h>
9
+ #include <linux/bitfield.h>
10
+ #include <linux/err.h>
10
11
#include <linux/init.h>
11
12
#include <linux/io.h>
13
+ #include <linux/iopoll.h>
14
+ #include <linux/kernel.h>
15
+ #include <linux/linear_range.h>
12
16
#include <linux/module.h>
13
- #include <linux/slab.h>
14
17
#include <linux/of.h>
15
- #include <linux/err.h>
16
18
#include <linux/platform_device.h>
19
+ #include <linux/slab.h>
20
+ #include <linux/smp.h>
21
+
22
+ #include <linux/regulator/driver.h>
23
+
17
24
#include <soc/qcom/spm.h>
18
25
26
+ #define FIELD_SET (current , mask , val ) \
27
+ (((current) & ~(mask)) | FIELD_PREP((mask), (val)))
28
+
19
29
#define SPM_CTL_INDEX 0x7f
20
30
#define SPM_CTL_INDEX_SHIFT 4
21
31
#define SPM_CTL_EN BIT(0)
22
32
33
+ /* These registers might be specific to SPM 1.1 */
34
+ #define SPM_VCTL_VLVL GENMASK(7, 0)
35
+ #define SPM_PMIC_DATA_0_VLVL GENMASK(7, 0)
36
+ #define SPM_PMIC_DATA_1_MIN_VSEL GENMASK(5, 0)
37
+ #define SPM_PMIC_DATA_1_MAX_VSEL GENMASK(21, 16)
38
+
39
+ #define SPM_1_1_AVS_CTL_AVS_ENABLED BIT(27)
40
+ #define SPM_AVS_CTL_MAX_VLVL GENMASK(22, 17)
41
+ #define SPM_AVS_CTL_MIN_VLVL GENMASK(15, 10)
42
+
23
43
enum spm_reg {
24
44
SPM_REG_CFG ,
25
45
SPM_REG_SPM_CTL ,
@@ -29,10 +49,12 @@ enum spm_reg {
29
49
SPM_REG_PMIC_DATA_1 ,
30
50
SPM_REG_VCTL ,
31
51
SPM_REG_SEQ_ENTRY ,
32
- SPM_REG_SPM_STS ,
52
+ SPM_REG_STS0 ,
53
+ SPM_REG_STS1 ,
33
54
SPM_REG_PMIC_STS ,
34
55
SPM_REG_AVS_CTL ,
35
56
SPM_REG_AVS_LIMIT ,
57
+ SPM_REG_RST ,
36
58
SPM_REG_NR ,
37
59
};
38
60
@@ -49,11 +71,20 @@ struct spm_reg_data {
49
71
u32 avs_limit ;
50
72
u8 seq [MAX_SEQ_DATA ];
51
73
u8 start_index [PM_SLEEP_MODE_NR ];
74
+
75
+ smp_call_func_t set_vdd ;
76
+ /* for now we support only a single range */
77
+ struct linear_range * range ;
78
+ unsigned int ramp_delay ;
79
+ unsigned int init_uV ;
52
80
};
53
81
54
82
struct spm_driver_data {
55
83
void __iomem * reg_base ;
56
84
const struct spm_reg_data * reg_data ;
85
+ struct device * dev ;
86
+ unsigned int volt_sel ;
87
+ int reg_cpu ;
57
88
};
58
89
59
90
static const u16 spm_reg_offset_v4_1 [SPM_REG_NR ] = {
@@ -189,14 +220,23 @@ static const struct spm_reg_data spm_reg_8226_cpu = {
189
220
190
221
static const u16 spm_reg_offset_v1_1 [SPM_REG_NR ] = {
191
222
[SPM_REG_CFG ] = 0x08 ,
223
+ [SPM_REG_STS0 ] = 0x0c ,
224
+ [SPM_REG_STS1 ] = 0x10 ,
225
+ [SPM_REG_VCTL ] = 0x14 ,
226
+ [SPM_REG_AVS_CTL ] = 0x18 ,
192
227
[SPM_REG_SPM_CTL ] = 0x20 ,
193
228
[SPM_REG_PMIC_DLY ] = 0x24 ,
194
229
[SPM_REG_PMIC_DATA_0 ] = 0x28 ,
195
230
[SPM_REG_PMIC_DATA_1 ] = 0x2C ,
196
231
[SPM_REG_SEQ_ENTRY ] = 0x80 ,
197
232
};
198
233
234
+ static void smp_set_vdd_v1_1 (void * data );
235
+
199
236
/* SPM register data for 8064 */
237
+ static struct linear_range spm_v1_1_regulator_range =
238
+ REGULATOR_LINEAR_RANGE (700000 , 0 , 56 , 12500 );
239
+
200
240
static const struct spm_reg_data spm_reg_8064_cpu = {
201
241
.reg_offset = spm_reg_offset_v1_1 ,
202
242
.spm_cfg = 0x1F ,
@@ -207,6 +247,10 @@ static const struct spm_reg_data spm_reg_8064_cpu = {
207
247
0x10 , 0x54 , 0x30 , 0x0C , 0x24 , 0x30 , 0x0F },
208
248
.start_index [PM_SLEEP_MODE_STBY ] = 0 ,
209
249
.start_index [PM_SLEEP_MODE_SPC ] = 2 ,
250
+ .set_vdd = smp_set_vdd_v1_1 ,
251
+ .range = & spm_v1_1_regulator_range ,
252
+ .init_uV = 1300000 ,
253
+ .ramp_delay = 1250 ,
210
254
};
211
255
212
256
static inline void spm_register_write (struct spm_driver_data * drv ,
@@ -258,6 +302,185 @@ void spm_set_low_power_mode(struct spm_driver_data *drv,
258
302
spm_register_write_sync (drv , SPM_REG_SPM_CTL , ctl_val );
259
303
}
260
304
305
+ static int spm_set_voltage_sel (struct regulator_dev * rdev , unsigned int selector )
306
+ {
307
+ struct spm_driver_data * drv = rdev_get_drvdata (rdev );
308
+
309
+ drv -> volt_sel = selector ;
310
+
311
+ /* Always do the SAW register writes on the corresponding CPU */
312
+ return smp_call_function_single (drv -> reg_cpu , drv -> reg_data -> set_vdd , drv , true);
313
+ }
314
+
315
+ static int spm_get_voltage_sel (struct regulator_dev * rdev )
316
+ {
317
+ struct spm_driver_data * drv = rdev_get_drvdata (rdev );
318
+
319
+ return drv -> volt_sel ;
320
+ }
321
+
322
+ static const struct regulator_ops spm_reg_ops = {
323
+ .set_voltage_sel = spm_set_voltage_sel ,
324
+ .get_voltage_sel = spm_get_voltage_sel ,
325
+ .list_voltage = regulator_list_voltage_linear_range ,
326
+ .set_voltage_time_sel = regulator_set_voltage_time_sel ,
327
+ };
328
+
329
+ static void smp_set_vdd_v1_1 (void * data )
330
+ {
331
+ struct spm_driver_data * drv = data ;
332
+ unsigned int vctl , data0 , data1 , avs_ctl , sts ;
333
+ unsigned int vlevel , volt_sel ;
334
+ bool avs_enabled ;
335
+
336
+ volt_sel = drv -> volt_sel ;
337
+ vlevel = volt_sel | 0x80 ; /* band */
338
+
339
+ avs_ctl = spm_register_read (drv , SPM_REG_AVS_CTL );
340
+ vctl = spm_register_read (drv , SPM_REG_VCTL );
341
+ data0 = spm_register_read (drv , SPM_REG_PMIC_DATA_0 );
342
+ data1 = spm_register_read (drv , SPM_REG_PMIC_DATA_1 );
343
+
344
+ avs_enabled = avs_ctl & SPM_1_1_AVS_CTL_AVS_ENABLED ;
345
+
346
+ /* If AVS is enabled, switch it off during the voltage change */
347
+ if (avs_enabled ) {
348
+ avs_ctl &= ~SPM_1_1_AVS_CTL_AVS_ENABLED ;
349
+ spm_register_write (drv , SPM_REG_AVS_CTL , avs_ctl );
350
+ }
351
+
352
+ /* Kick the state machine back to idle */
353
+ spm_register_write (drv , SPM_REG_RST , 1 );
354
+
355
+ vctl = FIELD_SET (vctl , SPM_VCTL_VLVL , vlevel );
356
+ data0 = FIELD_SET (data0 , SPM_PMIC_DATA_0_VLVL , vlevel );
357
+ data1 = FIELD_SET (data1 , SPM_PMIC_DATA_1_MIN_VSEL , volt_sel );
358
+ data1 = FIELD_SET (data1 , SPM_PMIC_DATA_1_MAX_VSEL , volt_sel );
359
+
360
+ spm_register_write (drv , SPM_REG_VCTL , vctl );
361
+ spm_register_write (drv , SPM_REG_PMIC_DATA_0 , data0 );
362
+ spm_register_write (drv , SPM_REG_PMIC_DATA_1 , data1 );
363
+
364
+ if (read_poll_timeout_atomic (spm_register_read ,
365
+ sts , sts == vlevel ,
366
+ 1 , 200 , false,
367
+ drv , SPM_REG_STS1 )) {
368
+ dev_err_ratelimited (drv -> dev , "timeout setting the voltage (%x %x)!\n" , sts , vlevel );
369
+ goto enable_avs ;
370
+ }
371
+
372
+ if (avs_enabled ) {
373
+ unsigned int max_avs = volt_sel ;
374
+ unsigned int min_avs = max (max_avs , 4U ) - 4 ;
375
+
376
+ avs_ctl = FIELD_SET (avs_ctl , SPM_AVS_CTL_MIN_VLVL , min_avs );
377
+ avs_ctl = FIELD_SET (avs_ctl , SPM_AVS_CTL_MAX_VLVL , max_avs );
378
+ spm_register_write (drv , SPM_REG_AVS_CTL , avs_ctl );
379
+ }
380
+
381
+ enable_avs :
382
+ if (avs_enabled ) {
383
+ avs_ctl |= SPM_1_1_AVS_CTL_AVS_ENABLED ;
384
+ spm_register_write (drv , SPM_REG_AVS_CTL , avs_ctl );
385
+ }
386
+ }
387
+
388
+ static int spm_get_cpu (struct device * dev )
389
+ {
390
+ int cpu ;
391
+ bool found ;
392
+
393
+ for_each_possible_cpu (cpu ) {
394
+ struct device_node * cpu_node , * saw_node ;
395
+
396
+ cpu_node = of_cpu_device_node_get (cpu );
397
+ if (!cpu_node )
398
+ continue ;
399
+
400
+ saw_node = of_parse_phandle (cpu_node , "qcom,saw" , 0 );
401
+ found = (saw_node == dev -> of_node );
402
+ of_node_put (saw_node );
403
+ of_node_put (cpu_node );
404
+
405
+ if (found )
406
+ return cpu ;
407
+ }
408
+
409
+ /* L2 SPM is not bound to any CPU, voltage setting is not supported */
410
+
411
+ return - EOPNOTSUPP ;
412
+ }
413
+
414
+ #ifdef CONFIG_REGULATOR
415
+ static int spm_register_regulator (struct device * dev , struct spm_driver_data * drv )
416
+ {
417
+ struct regulator_config config = {
418
+ .dev = dev ,
419
+ .driver_data = drv ,
420
+ };
421
+ struct regulator_desc * rdesc ;
422
+ struct regulator_dev * rdev ;
423
+ int ret ;
424
+ bool found ;
425
+
426
+ if (!drv -> reg_data -> set_vdd )
427
+ return 0 ;
428
+
429
+ rdesc = devm_kzalloc (dev , sizeof (* rdesc ), GFP_KERNEL );
430
+ if (!rdesc )
431
+ return - ENOMEM ;
432
+
433
+ rdesc -> name = "spm" ;
434
+ rdesc -> of_match = of_match_ptr ("regulator" );
435
+ rdesc -> type = REGULATOR_VOLTAGE ;
436
+ rdesc -> owner = THIS_MODULE ;
437
+ rdesc -> ops = & spm_reg_ops ;
438
+
439
+ rdesc -> linear_ranges = drv -> reg_data -> range ;
440
+ rdesc -> n_linear_ranges = 1 ;
441
+ rdesc -> n_voltages = rdesc -> linear_ranges [rdesc -> n_linear_ranges - 1 ].max_sel + 1 ;
442
+ rdesc -> ramp_delay = drv -> reg_data -> ramp_delay ;
443
+
444
+ ret = spm_get_cpu (dev );
445
+ if (ret < 0 )
446
+ return ret ;
447
+
448
+ drv -> reg_cpu = ret ;
449
+ dev_dbg (dev , "SAW2 bound to CPU %d\n" , drv -> reg_cpu );
450
+
451
+ /*
452
+ * Program initial voltage, otherwise registration will also try
453
+ * setting the voltage, which might result in undervolting the CPU.
454
+ */
455
+ drv -> volt_sel = DIV_ROUND_UP (drv -> reg_data -> init_uV - rdesc -> min_uV ,
456
+ rdesc -> uV_step );
457
+ ret = linear_range_get_selector_high (drv -> reg_data -> range ,
458
+ drv -> reg_data -> init_uV ,
459
+ & drv -> volt_sel ,
460
+ & found );
461
+ if (ret ) {
462
+ dev_err (dev , "Initial uV value out of bounds\n" );
463
+ return ret ;
464
+ }
465
+
466
+ /* Always do the SAW register writes on the corresponding CPU */
467
+ smp_call_function_single (drv -> reg_cpu , drv -> reg_data -> set_vdd , drv , true);
468
+
469
+ rdev = devm_regulator_register (dev , rdesc , & config );
470
+ if (IS_ERR (rdev )) {
471
+ dev_err (dev , "failed to register regulator\n" );
472
+ return PTR_ERR (rdev );
473
+ }
474
+
475
+ return 0 ;
476
+ }
477
+ #else
478
+ static int spm_register_regulator (struct device * dev , struct spm_driver_data * drv )
479
+ {
480
+ return 0 ;
481
+ }
482
+ #endif
483
+
261
484
static const struct of_device_id spm_match_table [] = {
262
485
{ .compatible = "qcom,sdm660-gold-saw2-v4.1-l2" ,
263
486
.data = & spm_reg_660_gold_l2 },
@@ -308,6 +531,7 @@ static int spm_dev_probe(struct platform_device *pdev)
308
531
return - ENODEV ;
309
532
310
533
drv -> reg_data = match_id -> data ;
534
+ drv -> dev = & pdev -> dev ;
311
535
platform_set_drvdata (pdev , drv );
312
536
313
537
/* Write the SPM sequences first.. */
@@ -335,7 +559,7 @@ static int spm_dev_probe(struct platform_device *pdev)
335
559
if (drv -> reg_data -> reg_offset [SPM_REG_SPM_CTL ])
336
560
spm_set_low_power_mode (drv , PM_SLEEP_MODE_STBY );
337
561
338
- return 0 ;
562
+ return spm_register_regulator ( & pdev -> dev , drv ) ;
339
563
}
340
564
341
565
static struct platform_driver spm_driver = {
0 commit comments