Lines Matching +full:drv +full:- +full:0
1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
27 #include <linux/nvmem-consumer.h>
29 /* Register Offsets for RB-CPR and Bit Definitions */
32 #define REG_RBCPR_VERSION 0
33 #define RBCPR_VER_2 0x02
34 #define FLAGS_IGNORE_1ST_IRQ_STATUS BIT(0)
37 #define REG_RBCPR_GCNT_TARGET(n) (0x60 + 4 * (n))
39 #define RBCPR_GCNT_TARGET_TARGET_SHIFT 0
40 #define RBCPR_GCNT_TARGET_TARGET_MASK GENMASK(11, 0)
42 #define RBCPR_GCNT_TARGET_GCNT_MASK GENMASK(9, 0)
45 #define REG_RBCPR_TIMER_INTERVAL 0x44
46 #define REG_RBIF_TIMER_ADJUST 0x4c
48 #define RBIF_TIMER_ADJ_CONS_UP_MASK GENMASK(3, 0)
49 #define RBIF_TIMER_ADJ_CONS_UP_SHIFT 0
50 #define RBIF_TIMER_ADJ_CONS_DOWN_MASK GENMASK(3, 0)
52 #define RBIF_TIMER_ADJ_CLAMP_INT_MASK GENMASK(7, 0)
56 #define REG_RBIF_LIMIT 0x48
57 #define RBIF_LIMIT_CEILING_MASK GENMASK(5, 0)
60 #define RBIF_LIMIT_FLOOR_MASK GENMASK(5, 0)
63 #define RBIF_LIMIT_FLOOR_DEFAULT 0
65 #define REG_RBIF_SW_VLEVEL 0x94
66 #define RBIF_SW_VLEVEL_DEFAULT 0x20
68 #define REG_RBCPR_STEP_QUOT 0x80
69 #define RBCPR_STEP_QUOT_STEPQUOT_MASK GENMASK(7, 0)
70 #define RBCPR_STEP_QUOT_IDLE_CLK_MASK GENMASK(3, 0)
74 #define REG_RBCPR_CTL 0x90
76 #define RBCPR_CTL_LOOP_EN BIT(0)
81 #define RBCPR_CTL_UP_THRESHOLD_MASK GENMASK(3, 0)
83 #define RBCPR_CTL_DN_THRESHOLD_MASK GENMASK(3, 0)
87 #define REG_RBIF_CONT_ACK_CMD 0x98
88 #define REG_RBIF_CONT_NACK_CMD 0x9c
91 #define REG_RBCPR_RESULT_0 0xa0
97 #define RBCPR_RESULT0_ERROR_MASK GENMASK(11, 0)
99 #define RBCPR_RESULT0_ERROR_STEPS_MASK GENMASK(3, 0)
103 #define REG_RBIF_IRQ_EN(n) (0x100 + 4 * (n))
104 #define REG_RBIF_IRQ_CLEAR 0x110
105 #define REG_RBIF_IRQ_STATUS 0x114
107 #define CPR_INT_DONE BIT(0)
121 #define CPR_FUSE_TARGET_QUOT_BITS_MASK GENMASK(11, 0)
125 #define FUSE_REVISION_UNKNOWN (-1)
252 static bool cpr_is_allowed(struct cpr_drv *drv) in cpr_is_allowed() argument
254 return !drv->loop_disabled; in cpr_is_allowed()
257 static void cpr_write(struct cpr_drv *drv, u32 offset, u32 value) in cpr_write() argument
259 writel_relaxed(value, drv->base + offset); in cpr_write()
262 static u32 cpr_read(struct cpr_drv *drv, u32 offset) in cpr_read() argument
264 return readl_relaxed(drv->base + offset); in cpr_read()
268 cpr_masked_write(struct cpr_drv *drv, u32 offset, u32 mask, u32 value) in cpr_masked_write() argument
272 val = readl_relaxed(drv->base + offset); in cpr_masked_write()
275 writel_relaxed(val, drv->base + offset); in cpr_masked_write()
278 static void cpr_irq_clr(struct cpr_drv *drv) in cpr_irq_clr() argument
280 cpr_write(drv, REG_RBIF_IRQ_CLEAR, CPR_INT_ALL); in cpr_irq_clr()
283 static void cpr_irq_clr_nack(struct cpr_drv *drv) in cpr_irq_clr_nack() argument
285 cpr_irq_clr(drv); in cpr_irq_clr_nack()
286 cpr_write(drv, REG_RBIF_CONT_NACK_CMD, 1); in cpr_irq_clr_nack()
289 static void cpr_irq_clr_ack(struct cpr_drv *drv) in cpr_irq_clr_ack() argument
291 cpr_irq_clr(drv); in cpr_irq_clr_ack()
292 cpr_write(drv, REG_RBIF_CONT_ACK_CMD, 1); in cpr_irq_clr_ack()
295 static void cpr_irq_set(struct cpr_drv *drv, u32 int_bits) in cpr_irq_set() argument
297 cpr_write(drv, REG_RBIF_IRQ_EN(0), int_bits); in cpr_irq_set()
300 static void cpr_ctl_modify(struct cpr_drv *drv, u32 mask, u32 value) in cpr_ctl_modify() argument
302 cpr_masked_write(drv, REG_RBCPR_CTL, mask, value); in cpr_ctl_modify()
305 static void cpr_ctl_enable(struct cpr_drv *drv, struct corner *corner) in cpr_ctl_enable() argument
308 const struct cpr_desc *desc = drv->desc; in cpr_ctl_enable()
311 val = desc->timer_cons_down << RBIF_TIMER_ADJ_CONS_DOWN_SHIFT; in cpr_ctl_enable()
312 val |= desc->timer_cons_up << RBIF_TIMER_ADJ_CONS_UP_SHIFT; in cpr_ctl_enable()
314 cpr_masked_write(drv, REG_RBIF_TIMER_ADJUST, mask, val); in cpr_ctl_enable()
315 cpr_masked_write(drv, REG_RBCPR_CTL, in cpr_ctl_enable()
318 corner->save_ctl); in cpr_ctl_enable()
319 cpr_irq_set(drv, corner->save_irq); in cpr_ctl_enable()
321 if (cpr_is_allowed(drv) && corner->max_uV > corner->min_uV) in cpr_ctl_enable()
324 val = 0; in cpr_ctl_enable()
325 cpr_ctl_modify(drv, RBCPR_CTL_LOOP_EN, val); in cpr_ctl_enable()
328 static void cpr_ctl_disable(struct cpr_drv *drv) in cpr_ctl_disable() argument
330 cpr_irq_set(drv, 0); in cpr_ctl_disable()
331 cpr_ctl_modify(drv, RBCPR_CTL_SW_AUTO_CONT_NACK_DN_EN | in cpr_ctl_disable()
332 RBCPR_CTL_SW_AUTO_CONT_ACK_EN, 0); in cpr_ctl_disable()
333 cpr_masked_write(drv, REG_RBIF_TIMER_ADJUST, in cpr_ctl_disable()
335 RBIF_TIMER_ADJ_CONS_DOWN_MASK, 0); in cpr_ctl_disable()
336 cpr_irq_clr(drv); in cpr_ctl_disable()
337 cpr_write(drv, REG_RBIF_CONT_ACK_CMD, 1); in cpr_ctl_disable()
338 cpr_write(drv, REG_RBIF_CONT_NACK_CMD, 1); in cpr_ctl_disable()
339 cpr_ctl_modify(drv, RBCPR_CTL_LOOP_EN, 0); in cpr_ctl_disable()
342 static bool cpr_ctl_is_enabled(struct cpr_drv *drv) in cpr_ctl_is_enabled() argument
346 reg_val = cpr_read(drv, REG_RBCPR_CTL); in cpr_ctl_is_enabled()
350 static bool cpr_ctl_is_busy(struct cpr_drv *drv) in cpr_ctl_is_busy() argument
354 reg_val = cpr_read(drv, REG_RBCPR_RESULT_0); in cpr_ctl_is_busy()
358 static void cpr_corner_save(struct cpr_drv *drv, struct corner *corner) in cpr_corner_save() argument
360 corner->save_ctl = cpr_read(drv, REG_RBCPR_CTL); in cpr_corner_save()
361 corner->save_irq = cpr_read(drv, REG_RBIF_IRQ_EN(0)); in cpr_corner_save()
364 static void cpr_corner_restore(struct cpr_drv *drv, struct corner *corner) in cpr_corner_restore() argument
367 struct fuse_corner *fuse = corner->fuse_corner; in cpr_corner_restore()
368 const struct cpr_desc *desc = drv->desc; in cpr_corner_restore()
371 ro_sel = fuse->ring_osc_idx; in cpr_corner_restore()
372 gcnt = drv->gcnt; in cpr_corner_restore()
373 gcnt |= fuse->quot - corner->quot_adjust; in cpr_corner_restore()
376 step_quot = desc->idle_clocks << RBCPR_STEP_QUOT_IDLE_CLK_SHIFT; in cpr_corner_restore()
377 step_quot |= fuse->step_quot & RBCPR_STEP_QUOT_STEPQUOT_MASK; in cpr_corner_restore()
378 cpr_write(drv, REG_RBCPR_STEP_QUOT, step_quot); in cpr_corner_restore()
381 for (i = 0; i < CPR_NUM_RING_OSC; i++) in cpr_corner_restore()
382 cpr_write(drv, REG_RBCPR_GCNT_TARGET(i), 0); in cpr_corner_restore()
384 cpr_write(drv, REG_RBCPR_GCNT_TARGET(ro_sel), gcnt); in cpr_corner_restore()
385 ctl = corner->save_ctl; in cpr_corner_restore()
386 cpr_write(drv, REG_RBCPR_CTL, ctl); in cpr_corner_restore()
387 irq = corner->save_irq; in cpr_corner_restore()
388 cpr_irq_set(drv, irq); in cpr_corner_restore()
389 dev_dbg(drv->dev, "gcnt = %#08x, ctl = %#08x, irq = %#08x\n", gcnt, in cpr_corner_restore()
401 regmap_multi_reg_write(tcsr, f->accs, f->num_accs); in cpr_set_acc()
403 for (f -= 1; f >= end; f--) in cpr_set_acc()
404 regmap_multi_reg_write(tcsr, f->accs, f->num_accs); in cpr_set_acc()
408 static int cpr_pre_voltage(struct cpr_drv *drv, in cpr_pre_voltage() argument
412 struct fuse_corner *prev_fuse_corner = drv->corner->fuse_corner; in cpr_pre_voltage()
414 if (drv->tcsr && dir == DOWN) in cpr_pre_voltage()
415 cpr_set_acc(drv->tcsr, prev_fuse_corner, fuse_corner); in cpr_pre_voltage()
417 return 0; in cpr_pre_voltage()
420 static int cpr_post_voltage(struct cpr_drv *drv, in cpr_post_voltage() argument
424 struct fuse_corner *prev_fuse_corner = drv->corner->fuse_corner; in cpr_post_voltage()
426 if (drv->tcsr && dir == UP) in cpr_post_voltage()
427 cpr_set_acc(drv->tcsr, prev_fuse_corner, fuse_corner); in cpr_post_voltage()
429 return 0; in cpr_post_voltage()
432 static int cpr_scale_voltage(struct cpr_drv *drv, struct corner *corner, in cpr_scale_voltage() argument
436 struct fuse_corner *fuse_corner = corner->fuse_corner; in cpr_scale_voltage()
438 ret = cpr_pre_voltage(drv, fuse_corner, dir); in cpr_scale_voltage()
442 ret = regulator_set_voltage(drv->vdd_apc, new_uV, new_uV); in cpr_scale_voltage()
444 dev_err_ratelimited(drv->dev, "failed to set apc voltage %d\n", in cpr_scale_voltage()
449 ret = cpr_post_voltage(drv, fuse_corner, dir); in cpr_scale_voltage()
453 return 0; in cpr_scale_voltage()
456 static unsigned int cpr_get_cur_perf_state(struct cpr_drv *drv) in cpr_get_cur_perf_state() argument
458 return drv->corner ? drv->corner - drv->corners + 1 : 0; in cpr_get_cur_perf_state()
461 static int cpr_scale(struct cpr_drv *drv, enum voltage_change_dir dir) in cpr_scale() argument
466 const struct cpr_desc *desc = drv->desc; in cpr_scale()
469 return 0; in cpr_scale()
471 step_uV = regulator_get_linear_step(drv->vdd_apc); in cpr_scale()
473 return -EINVAL; in cpr_scale()
475 corner = drv->corner; in cpr_scale()
477 val = cpr_read(drv, REG_RBCPR_RESULT_0); in cpr_scale()
481 last_uV = corner->last_uV; in cpr_scale()
484 if (desc->clamp_timer_interval && in cpr_scale()
485 error_steps < desc->up_threshold) { in cpr_scale()
491 error_steps = max(desc->up_threshold, in cpr_scale()
492 desc->vdd_apc_step_up_limit); in cpr_scale()
495 if (last_uV >= corner->max_uV) { in cpr_scale()
496 cpr_irq_clr_nack(drv); in cpr_scale()
502 cpr_ctl_modify(drv, reg_mask, val); in cpr_scale()
505 cpr_irq_set(drv, CPR_INT_DEFAULT & ~CPR_INT_UP); in cpr_scale()
507 return 0; in cpr_scale()
510 if (error_steps > desc->vdd_apc_step_up_limit) in cpr_scale()
511 error_steps = desc->vdd_apc_step_up_limit; in cpr_scale()
515 new_uV = min(new_uV, corner->max_uV); in cpr_scale()
517 dev_dbg(drv->dev, in cpr_scale()
518 "UP: -> new_uV: %d last_uV: %d perf state: %u\n", in cpr_scale()
519 new_uV, last_uV, cpr_get_cur_perf_state(drv)); in cpr_scale()
521 if (desc->clamp_timer_interval && in cpr_scale()
522 error_steps < desc->down_threshold) { in cpr_scale()
528 error_steps = max(desc->down_threshold, in cpr_scale()
529 desc->vdd_apc_step_down_limit); in cpr_scale()
532 if (last_uV <= corner->min_uV) { in cpr_scale()
533 cpr_irq_clr_nack(drv); in cpr_scale()
539 cpr_ctl_modify(drv, reg_mask, val); in cpr_scale()
542 cpr_irq_set(drv, CPR_INT_DEFAULT & ~CPR_INT_DOWN); in cpr_scale()
544 return 0; in cpr_scale()
547 if (error_steps > desc->vdd_apc_step_down_limit) in cpr_scale()
548 error_steps = desc->vdd_apc_step_down_limit; in cpr_scale()
551 new_uV = last_uV - error_steps * step_uV; in cpr_scale()
552 new_uV = max(new_uV, corner->min_uV); in cpr_scale()
554 dev_dbg(drv->dev, in cpr_scale()
555 "DOWN: -> new_uV: %d last_uV: %d perf state: %u\n", in cpr_scale()
556 new_uV, last_uV, cpr_get_cur_perf_state(drv)); in cpr_scale()
559 ret = cpr_scale_voltage(drv, corner, new_uV, dir); in cpr_scale()
561 cpr_irq_clr_nack(drv); in cpr_scale()
564 drv->corner->last_uV = new_uV; in cpr_scale()
569 val = 0; in cpr_scale()
574 val = desc->up_threshold; in cpr_scale()
578 cpr_ctl_modify(drv, reg_mask, val); in cpr_scale()
580 /* Re-enable default interrupts */ in cpr_scale()
581 cpr_irq_set(drv, CPR_INT_DEFAULT); in cpr_scale()
584 cpr_irq_clr_ack(drv); in cpr_scale()
586 return 0; in cpr_scale()
591 struct cpr_drv *drv = dev; in cpr_irq_handler() local
592 const struct cpr_desc *desc = drv->desc; in cpr_irq_handler()
596 mutex_lock(&drv->lock); in cpr_irq_handler()
598 val = cpr_read(drv, REG_RBIF_IRQ_STATUS); in cpr_irq_handler()
599 if (drv->flags & FLAGS_IGNORE_1ST_IRQ_STATUS) in cpr_irq_handler()
600 val = cpr_read(drv, REG_RBIF_IRQ_STATUS); in cpr_irq_handler()
602 dev_dbg(drv->dev, "IRQ_STATUS = %#02x\n", val); in cpr_irq_handler()
604 if (!cpr_ctl_is_enabled(drv)) { in cpr_irq_handler()
605 dev_dbg(drv->dev, "CPR is disabled\n"); in cpr_irq_handler()
607 } else if (cpr_ctl_is_busy(drv) && !desc->clamp_timer_interval) { in cpr_irq_handler()
608 dev_dbg(drv->dev, "CPR measurement is not ready\n"); in cpr_irq_handler()
609 } else if (!cpr_is_allowed(drv)) { in cpr_irq_handler()
610 val = cpr_read(drv, REG_RBCPR_CTL); in cpr_irq_handler()
611 dev_err_ratelimited(drv->dev, in cpr_irq_handler()
621 cpr_scale(drv, UP); in cpr_irq_handler()
623 cpr_scale(drv, DOWN); in cpr_irq_handler()
625 cpr_irq_clr_nack(drv); in cpr_irq_handler()
627 cpr_irq_clr_nack(drv); in cpr_irq_handler()
630 dev_dbg(drv->dev, "IRQ occurred for Mid Flag\n"); in cpr_irq_handler()
632 dev_dbg(drv->dev, in cpr_irq_handler()
637 cpr_corner_save(drv, drv->corner); in cpr_irq_handler()
640 mutex_unlock(&drv->lock); in cpr_irq_handler()
645 static int cpr_enable(struct cpr_drv *drv) in cpr_enable() argument
649 ret = regulator_enable(drv->vdd_apc); in cpr_enable()
653 mutex_lock(&drv->lock); in cpr_enable()
655 if (cpr_is_allowed(drv) && drv->corner) { in cpr_enable()
656 cpr_irq_clr(drv); in cpr_enable()
657 cpr_corner_restore(drv, drv->corner); in cpr_enable()
658 cpr_ctl_enable(drv, drv->corner); in cpr_enable()
661 mutex_unlock(&drv->lock); in cpr_enable()
663 return 0; in cpr_enable()
666 static int cpr_disable(struct cpr_drv *drv) in cpr_disable() argument
668 mutex_lock(&drv->lock); in cpr_disable()
670 if (cpr_is_allowed(drv)) { in cpr_disable()
671 cpr_ctl_disable(drv); in cpr_disable()
672 cpr_irq_clr(drv); in cpr_disable()
675 mutex_unlock(&drv->lock); in cpr_disable()
677 return regulator_disable(drv->vdd_apc); in cpr_disable()
680 static int cpr_config(struct cpr_drv *drv) in cpr_config() argument
685 const struct cpr_desc *desc = drv->desc; in cpr_config()
688 cpr_write(drv, REG_RBIF_IRQ_EN(0), 0); in cpr_config()
689 cpr_write(drv, REG_RBCPR_CTL, 0); in cpr_config()
695 cpr_write(drv, REG_RBIF_LIMIT, val); in cpr_config()
696 cpr_write(drv, REG_RBIF_SW_VLEVEL, RBIF_SW_VLEVEL_DEFAULT); in cpr_config()
702 for (i = 0; i < CPR_NUM_RING_OSC; i++) in cpr_config()
703 cpr_write(drv, REG_RBCPR_GCNT_TARGET(i), 0); in cpr_config()
706 gcnt = (drv->ref_clk_khz * desc->gcnt_us) / 1000; in cpr_config()
709 drv->gcnt = gcnt; in cpr_config()
712 val = (drv->ref_clk_khz * desc->timer_delay_us) / 1000; in cpr_config()
713 cpr_write(drv, REG_RBCPR_TIMER_INTERVAL, val); in cpr_config()
714 dev_dbg(drv->dev, "Timer count: %#0x (for %d us)\n", val, in cpr_config()
715 desc->timer_delay_us); in cpr_config()
718 val = desc->timer_cons_down << RBIF_TIMER_ADJ_CONS_DOWN_SHIFT; in cpr_config()
719 val |= desc->timer_cons_up << RBIF_TIMER_ADJ_CONS_UP_SHIFT; in cpr_config()
720 val |= desc->clamp_timer_interval << RBIF_TIMER_ADJ_CLAMP_INT_SHIFT; in cpr_config()
721 cpr_write(drv, REG_RBIF_TIMER_ADJUST, val); in cpr_config()
724 val = desc->up_threshold << RBCPR_CTL_UP_THRESHOLD_SHIFT; in cpr_config()
725 val |= desc->down_threshold << RBCPR_CTL_DN_THRESHOLD_SHIFT; in cpr_config()
728 cpr_write(drv, REG_RBCPR_CTL, val); in cpr_config()
730 for (i = 0; i < drv->num_corners; i++) { in cpr_config()
731 corner = &drv->corners[i]; in cpr_config()
732 corner->save_ctl = val; in cpr_config()
733 corner->save_irq = CPR_INT_DEFAULT; in cpr_config()
736 cpr_irq_set(drv, CPR_INT_DEFAULT); in cpr_config()
738 val = cpr_read(drv, REG_RBCPR_VERSION); in cpr_config()
740 drv->flags |= FLAGS_IGNORE_1ST_IRQ_STATUS; in cpr_config()
742 return 0; in cpr_config()
748 struct cpr_drv *drv = container_of(domain, struct cpr_drv, pd); in cpr_set_performance_state() local
751 int ret = 0, new_uV; in cpr_set_performance_state()
753 mutex_lock(&drv->lock); in cpr_set_performance_state()
755 dev_dbg(drv->dev, "%s: setting perf state: %u (prev state: %u)\n", in cpr_set_performance_state()
756 __func__, state, cpr_get_cur_perf_state(drv)); in cpr_set_performance_state()
762 corner = drv->corners + state - 1; in cpr_set_performance_state()
763 end = &drv->corners[drv->num_corners - 1]; in cpr_set_performance_state()
764 if (corner > end || corner < drv->corners) { in cpr_set_performance_state()
765 ret = -EINVAL; in cpr_set_performance_state()
770 if (drv->corner > corner) in cpr_set_performance_state()
772 else if (drv->corner < corner) in cpr_set_performance_state()
777 if (cpr_is_allowed(drv)) in cpr_set_performance_state()
778 new_uV = corner->last_uV; in cpr_set_performance_state()
780 new_uV = corner->uV; in cpr_set_performance_state()
782 if (cpr_is_allowed(drv)) in cpr_set_performance_state()
783 cpr_ctl_disable(drv); in cpr_set_performance_state()
785 ret = cpr_scale_voltage(drv, corner, new_uV, dir); in cpr_set_performance_state()
789 if (cpr_is_allowed(drv)) { in cpr_set_performance_state()
790 cpr_irq_clr(drv); in cpr_set_performance_state()
791 if (drv->corner != corner) in cpr_set_performance_state()
792 cpr_corner_restore(drv, corner); in cpr_set_performance_state()
793 cpr_ctl_enable(drv, corner); in cpr_set_performance_state()
796 drv->corner = corner; in cpr_set_performance_state()
799 mutex_unlock(&drv->lock); in cpr_set_performance_state()
811 *data = 0; in cpr_read_efuse()
815 if (PTR_ERR(cell) != -EPROBE_DEFER) in cpr_read_efuse()
827 for (i = 0; i < len; i++) in cpr_read_efuse()
833 return 0; in cpr_read_efuse()
837 cpr_populate_ring_osc_idx(struct cpr_drv *drv) in cpr_populate_ring_osc_idx() argument
839 struct fuse_corner *fuse = drv->fuse_corners; in cpr_populate_ring_osc_idx()
840 struct fuse_corner *end = fuse + drv->desc->num_fuse_corners; in cpr_populate_ring_osc_idx()
841 const struct cpr_fuse *fuses = drv->cpr_fuses; in cpr_populate_ring_osc_idx()
846 ret = cpr_read_efuse(drv->dev, fuses->ring_osc, in cpr_populate_ring_osc_idx()
850 fuse->ring_osc_idx = data; in cpr_populate_ring_osc_idx()
853 return 0; in cpr_populate_ring_osc_idx()
860 struct cpr_drv *drv) in cpr_read_fuse_uV() argument
863 u32 bits = 0; in cpr_read_fuse_uV()
866 ret = cpr_read_efuse(drv->dev, init_v_efuse, &bits); in cpr_read_fuse_uV()
870 steps = bits & ~BIT(desc->cpr_fuses.init_voltage_width - 1); in cpr_read_fuse_uV()
872 if (bits & BIT(desc->cpr_fuses.init_voltage_width - 1)) in cpr_read_fuse_uV()
873 steps = -steps; in cpr_read_fuse_uV()
875 step_size_uV = desc->cpr_fuses.init_voltage_step; in cpr_read_fuse_uV()
877 uV = fdata->ref_uV + steps * step_size_uV; in cpr_read_fuse_uV()
881 static int cpr_fuse_corner_init(struct cpr_drv *drv) in cpr_fuse_corner_init() argument
883 const struct cpr_desc *desc = drv->desc; in cpr_fuse_corner_init()
884 const struct cpr_fuse *fuses = drv->cpr_fuses; in cpr_fuse_corner_init()
885 const struct acc_desc *acc_desc = drv->acc_desc; in cpr_fuse_corner_init()
894 accs = acc_desc->settings; in cpr_fuse_corner_init()
896 step_volt = regulator_get_linear_step(drv->vdd_apc); in cpr_fuse_corner_init()
898 return -EINVAL; in cpr_fuse_corner_init()
901 fuse = drv->fuse_corners; in cpr_fuse_corner_init()
902 end = &fuse[desc->num_fuse_corners - 1]; in cpr_fuse_corner_init()
903 fdata = desc->cpr_fuses.fuse_corner_data; in cpr_fuse_corner_init()
905 for (i = 0; fuse <= end; fuse++, fuses++, i++, fdata++) { in cpr_fuse_corner_init()
911 fdata->min_uV = roundup(fdata->min_uV, step_volt); in cpr_fuse_corner_init()
912 fdata->max_uV = roundup(fdata->max_uV, step_volt); in cpr_fuse_corner_init()
915 uV = cpr_read_fuse_uV(desc, fdata, fuses->init_voltage, in cpr_fuse_corner_init()
916 step_volt, drv); in cpr_fuse_corner_init()
917 if (uV < 0) in cpr_fuse_corner_init()
920 fuse->min_uV = fdata->min_uV; in cpr_fuse_corner_init()
921 fuse->max_uV = fdata->max_uV; in cpr_fuse_corner_init()
922 fuse->uV = clamp(uV, fuse->min_uV, fuse->max_uV); in cpr_fuse_corner_init()
931 end->max_uV = max(end->max_uV, end->uV); in cpr_fuse_corner_init()
935 ret = cpr_read_efuse(drv->dev, fuses->quotient, &fuse->quot); in cpr_fuse_corner_init()
939 fuse->quot *= fdata->quot_scale; in cpr_fuse_corner_init()
940 fuse->quot += fdata->quot_offset; in cpr_fuse_corner_init()
941 fuse->quot += fdata->quot_adjust; in cpr_fuse_corner_init()
942 fuse->step_quot = desc->step_quot[fuse->ring_osc_idx]; in cpr_fuse_corner_init()
945 fuse->accs = accs; in cpr_fuse_corner_init()
946 fuse->num_accs = acc_desc->num_regs_per_fuse; in cpr_fuse_corner_init()
947 accs += acc_desc->num_regs_per_fuse; in cpr_fuse_corner_init()
954 for (fuse = drv->fuse_corners, i = 0; fuse <= end; fuse++, i++) { in cpr_fuse_corner_init()
955 if (fuse->uV > fuse->max_uV) in cpr_fuse_corner_init()
956 fuse->uV = fuse->max_uV; in cpr_fuse_corner_init()
957 else if (fuse->uV < fuse->min_uV) in cpr_fuse_corner_init()
958 fuse->uV = fuse->min_uV; in cpr_fuse_corner_init()
960 ret = regulator_is_supported_voltage(drv->vdd_apc, in cpr_fuse_corner_init()
961 fuse->min_uV, in cpr_fuse_corner_init()
962 fuse->min_uV); in cpr_fuse_corner_init()
964 dev_err(drv->dev, in cpr_fuse_corner_init()
966 fuse->min_uV, i); in cpr_fuse_corner_init()
967 return -EINVAL; in cpr_fuse_corner_init()
970 ret = regulator_is_supported_voltage(drv->vdd_apc, in cpr_fuse_corner_init()
971 fuse->max_uV, in cpr_fuse_corner_init()
972 fuse->max_uV); in cpr_fuse_corner_init()
974 dev_err(drv->dev, in cpr_fuse_corner_init()
976 fuse->max_uV, i); in cpr_fuse_corner_init()
977 return -EINVAL; in cpr_fuse_corner_init()
980 dev_dbg(drv->dev, in cpr_fuse_corner_init()
982 i, fuse->min_uV, fuse->uV, fuse->max_uV, in cpr_fuse_corner_init()
983 fuse->ring_osc_idx, fuse->quot, fuse->step_quot); in cpr_fuse_corner_init()
986 return 0; in cpr_fuse_corner_init()
990 struct cpr_drv *drv, in cpr_calculate_scaling() argument
994 u32 quot_diff = 0; in cpr_calculate_scaling()
1000 fuse = corner->fuse_corner; in cpr_calculate_scaling()
1001 prev_fuse = fuse - 1; in cpr_calculate_scaling()
1004 ret = cpr_read_efuse(drv->dev, quot_offset, "_diff); in cpr_calculate_scaling()
1008 quot_diff *= fdata->quot_offset_scale; in cpr_calculate_scaling()
1009 quot_diff += fdata->quot_offset_adjust; in cpr_calculate_scaling()
1011 quot_diff = fuse->quot - prev_fuse->quot; in cpr_calculate_scaling()
1014 freq_diff = fuse->max_freq - prev_fuse->max_freq; in cpr_calculate_scaling()
1017 return min(scaling, fdata->max_quot_scale); in cpr_calculate_scaling()
1028 fuse = corner->fuse_corner; in cpr_interpolate()
1029 prev_fuse = fuse - 1; in cpr_interpolate()
1031 f_high = fuse->max_freq; in cpr_interpolate()
1032 f_low = prev_fuse->max_freq; in cpr_interpolate()
1033 uV_high = fuse->uV; in cpr_interpolate()
1034 uV_low = prev_fuse->uV; in cpr_interpolate()
1035 f_diff = fuse->max_freq - corner->freq; in cpr_interpolate()
1042 if (f_high <= f_low || uV_high <= uV_low || f_high <= corner->freq) in cpr_interpolate()
1043 return corner->uV; in cpr_interpolate()
1045 temp = f_diff * (uV_high - uV_low); in cpr_interpolate()
1046 temp = div64_ul(temp, f_high - f_low); in cpr_interpolate()
1052 temp_limit = f_diff * fdata->max_volt_scale; in cpr_interpolate()
1055 uV = uV_high - min(temp, temp_limit); in cpr_interpolate()
1062 unsigned int fuse_corner = 0; in cpr_get_fuse_corner()
1065 if (of_property_read_u32(np, "qcom,opp-fuse-level", &fuse_corner)) in cpr_get_fuse_corner()
1066 pr_err("%s: missing 'qcom,opp-fuse-level' property\n", in cpr_get_fuse_corner()
1077 u64 rate = 0; in cpr_get_opp_hz_for_req()
1085 return 0; in cpr_get_opp_hz_for_req()
1094 child_req_np = of_parse_phandle(child_np, "required-opps", 0); in cpr_get_opp_hz_for_req()
1098 of_property_read_u64(child_np, "opp-hz", &rate); in cpr_get_opp_hz_for_req()
1109 static int cpr_corner_init(struct cpr_drv *drv) in cpr_corner_init() argument
1111 const struct cpr_desc *desc = drv->desc; in cpr_corner_init()
1112 const struct cpr_fuse *fuses = drv->cpr_fuses; in cpr_corner_init()
1113 int i, level, scaling = 0; in cpr_corner_init()
1123 int step_volt = regulator_get_linear_step(drv->vdd_apc); in cpr_corner_init()
1127 return -EINVAL; in cpr_corner_init()
1129 corner = drv->corners; in cpr_corner_init()
1130 end = &corner[drv->num_corners - 1]; in cpr_corner_init()
1132 cdata = devm_kcalloc(drv->dev, drv->num_corners, in cpr_corner_init()
1136 return -ENOMEM; in cpr_corner_init()
1142 for (level = 1; level <= drv->num_corners; level++) { in cpr_corner_init()
1143 opp = dev_pm_opp_find_level_exact(&drv->pd.dev, level); in cpr_corner_init()
1145 return -EINVAL; in cpr_corner_init()
1149 return -EINVAL; in cpr_corner_init()
1151 fnum = fc - 1; in cpr_corner_init()
1152 freq = cpr_get_opp_hz_for_req(opp, drv->attached_cpu_dev); in cpr_corner_init()
1155 return -EINVAL; in cpr_corner_init()
1157 cdata[level - 1].fuse_corner = fnum; in cpr_corner_init()
1158 cdata[level - 1].freq = freq; in cpr_corner_init()
1160 fuse = &drv->fuse_corners[fnum]; in cpr_corner_init()
1161 dev_dbg(drv->dev, "freq: %lu level: %u fuse level: %u\n", in cpr_corner_init()
1162 freq, dev_pm_opp_get_level(opp) - 1, fnum); in cpr_corner_init()
1163 if (freq > fuse->max_freq) in cpr_corner_init()
1164 fuse->max_freq = freq; in cpr_corner_init()
1171 * scaling = min(1000 * (QUOT(corner_N) - QUOT(corner_N-1)) in cpr_corner_init()
1172 * / (freq(corner_N) - freq(corner_N-1)), max_factor) in cpr_corner_init()
1175 * QUOT(corner_N-1): quotient read from fuse for fuse corner (N - 1) in cpr_corner_init()
1177 * freq(corner_N-1): max frequency in MHz supported by fuse corner in cpr_corner_init()
1178 * (N - 1) in cpr_corner_init()
1184 * quot_adjust = (freq_max - freq_corner) * scaling / 1000 in cpr_corner_init()
1199 * +--------------- +---------------- in cpr_corner_init()
1200 * 0 1 2 3 4 5 6 0 1 2 3 4 5 6 in cpr_corner_init()
1207 for (apply_scaling = false, i = 0; corner <= end; corner++, i++) { in cpr_corner_init()
1209 fdata = &desc->cpr_fuses.fuse_corner_data[fnum]; in cpr_corner_init()
1211 fuse = &drv->fuse_corners[fnum]; in cpr_corner_init()
1213 prev_fuse = &drv->fuse_corners[fnum - 1]; in cpr_corner_init()
1217 corner->fuse_corner = fuse; in cpr_corner_init()
1218 corner->freq = cdata[i].freq; in cpr_corner_init()
1219 corner->uV = fuse->uV; in cpr_corner_init()
1221 if (prev_fuse && cdata[i - 1].freq == prev_fuse->max_freq) { in cpr_corner_init()
1222 scaling = cpr_calculate_scaling(quot_offset, drv, in cpr_corner_init()
1224 if (scaling < 0) in cpr_corner_init()
1228 } else if (corner->freq == fuse->max_freq) { in cpr_corner_init()
1234 freq_diff = fuse->max_freq - corner->freq; in cpr_corner_init()
1236 corner->quot_adjust = scaling * freq_diff_mhz / 1000; in cpr_corner_init()
1238 corner->uV = cpr_interpolate(corner, step_volt, fdata); in cpr_corner_init()
1241 corner->max_uV = fuse->max_uV; in cpr_corner_init()
1242 corner->min_uV = fuse->min_uV; in cpr_corner_init()
1243 corner->uV = clamp(corner->uV, corner->min_uV, corner->max_uV); in cpr_corner_init()
1244 corner->last_uV = corner->uV; in cpr_corner_init()
1247 if (desc->reduce_to_corner_uV && corner->uV < corner->max_uV) in cpr_corner_init()
1248 corner->max_uV = corner->uV; in cpr_corner_init()
1249 else if (desc->reduce_to_fuse_uV && fuse->uV < corner->max_uV) in cpr_corner_init()
1250 corner->max_uV = max(corner->min_uV, fuse->uV); in cpr_corner_init()
1252 dev_dbg(drv->dev, "corner %d: [%d %d %d] quot %d\n", i, in cpr_corner_init()
1253 corner->min_uV, corner->uV, corner->max_uV, in cpr_corner_init()
1254 fuse->quot - corner->quot_adjust); in cpr_corner_init()
1257 return 0; in cpr_corner_init()
1260 static const struct cpr_fuse *cpr_get_fuses(struct cpr_drv *drv) in cpr_get_fuses() argument
1262 const struct cpr_desc *desc = drv->desc; in cpr_get_fuses()
1266 fuses = devm_kcalloc(drv->dev, desc->num_fuse_corners, in cpr_get_fuses()
1270 return ERR_PTR(-ENOMEM); in cpr_get_fuses()
1272 for (i = 0; i < desc->num_fuse_corners; i++) { in cpr_get_fuses()
1276 fuses[i].ring_osc = devm_kstrdup(drv->dev, tbuf, GFP_KERNEL); in cpr_get_fuses()
1278 return ERR_PTR(-ENOMEM); in cpr_get_fuses()
1281 fuses[i].init_voltage = devm_kstrdup(drv->dev, tbuf, in cpr_get_fuses()
1284 return ERR_PTR(-ENOMEM); in cpr_get_fuses()
1287 fuses[i].quotient = devm_kstrdup(drv->dev, tbuf, GFP_KERNEL); in cpr_get_fuses()
1289 return ERR_PTR(-ENOMEM); in cpr_get_fuses()
1292 fuses[i].quotient_offset = devm_kstrdup(drv->dev, tbuf, in cpr_get_fuses()
1295 return ERR_PTR(-ENOMEM); in cpr_get_fuses()
1301 static void cpr_set_loop_allowed(struct cpr_drv *drv) in cpr_set_loop_allowed() argument
1303 drv->loop_disabled = false; in cpr_set_loop_allowed()
1306 static int cpr_init_parameters(struct cpr_drv *drv) in cpr_init_parameters() argument
1308 const struct cpr_desc *desc = drv->desc; in cpr_init_parameters()
1311 clk = clk_get(drv->dev, "ref"); in cpr_init_parameters()
1315 drv->ref_clk_khz = clk_get_rate(clk) / 1000; in cpr_init_parameters()
1318 if (desc->timer_cons_up > RBIF_TIMER_ADJ_CONS_UP_MASK || in cpr_init_parameters()
1319 desc->timer_cons_down > RBIF_TIMER_ADJ_CONS_DOWN_MASK || in cpr_init_parameters()
1320 desc->up_threshold > RBCPR_CTL_UP_THRESHOLD_MASK || in cpr_init_parameters()
1321 desc->down_threshold > RBCPR_CTL_DN_THRESHOLD_MASK || in cpr_init_parameters()
1322 desc->idle_clocks > RBCPR_STEP_QUOT_IDLE_CLK_MASK || in cpr_init_parameters()
1323 desc->clamp_timer_interval > RBIF_TIMER_ADJ_CLAMP_INT_MASK) in cpr_init_parameters()
1324 return -EINVAL; in cpr_init_parameters()
1326 dev_dbg(drv->dev, "up threshold = %u, down threshold = %u\n", in cpr_init_parameters()
1327 desc->up_threshold, desc->down_threshold); in cpr_init_parameters()
1329 return 0; in cpr_init_parameters()
1332 static int cpr_find_initial_corner(struct cpr_drv *drv) in cpr_find_initial_corner() argument
1337 unsigned int i = 0; in cpr_find_initial_corner()
1339 if (!drv->cpu_clk) { in cpr_find_initial_corner()
1340 dev_err(drv->dev, "cannot get rate from NULL clk\n"); in cpr_find_initial_corner()
1341 return -EINVAL; in cpr_find_initial_corner()
1344 end = &drv->corners[drv->num_corners - 1]; in cpr_find_initial_corner()
1345 rate = clk_get_rate(drv->cpu_clk); in cpr_find_initial_corner()
1358 for (iter = drv->corners; iter <= end; iter++) { in cpr_find_initial_corner()
1359 if (iter->freq > rate) in cpr_find_initial_corner()
1362 if (iter->freq == rate) { in cpr_find_initial_corner()
1363 drv->corner = iter; in cpr_find_initial_corner()
1366 if (iter->freq < rate) in cpr_find_initial_corner()
1367 drv->corner = iter; in cpr_find_initial_corner()
1370 if (!drv->corner) { in cpr_find_initial_corner()
1371 dev_err(drv->dev, "boot up corner not found\n"); in cpr_find_initial_corner()
1372 return -EINVAL; in cpr_find_initial_corner()
1375 dev_dbg(drv->dev, "boot up perf state: %u\n", i); in cpr_find_initial_corner()
1377 return 0; in cpr_find_initial_corner()
1385 .timer_cons_up = 0,
1397 /* fuse corner 0 */
1402 .max_volt_scale = 0,
1403 .max_quot_scale = 0,
1404 .quot_offset = 0,
1406 .quot_adjust = 0,
1408 .quot_offset_adjust = 0,
1417 .quot_offset = 0,
1419 .quot_adjust = -20,
1421 .quot_offset_adjust = 0,
1430 .quot_offset = 0,
1432 .quot_adjust = 0,
1434 .quot_offset_adjust = 0,
1442 { 0xb120, 0x1041040 },
1443 { 0xb124, 0x41 },
1444 { 0xb120, 0x0 },
1445 { 0xb124, 0x0 },
1446 { 0xb120, 0x0 },
1447 { 0xb124, 0x0 },
1450 { 0xb138, 0xff },
1451 { 0xb130, 0x5555 },
1469 struct cpr_drv *drv = container_of(domain, struct cpr_drv, pd); in cpr_power_off() local
1471 return cpr_disable(drv); in cpr_power_off()
1476 struct cpr_drv *drv = container_of(domain, struct cpr_drv, pd); in cpr_power_on() local
1478 return cpr_enable(drv); in cpr_power_on()
1484 struct cpr_drv *drv = container_of(domain, struct cpr_drv, pd); in cpr_pd_attach_dev() local
1485 const struct acc_desc *acc_desc = drv->acc_desc; in cpr_pd_attach_dev()
1486 int ret = 0; in cpr_pd_attach_dev()
1488 mutex_lock(&drv->lock); in cpr_pd_attach_dev()
1490 dev_dbg(drv->dev, "attach callback for: %s\n", dev_name(dev)); in cpr_pd_attach_dev()
1499 if (drv->attached_cpu_dev) in cpr_pd_attach_dev()
1511 drv->cpu_clk = devm_clk_get(dev, NULL); in cpr_pd_attach_dev()
1512 if (IS_ERR(drv->cpu_clk)) { in cpr_pd_attach_dev()
1513 ret = PTR_ERR(drv->cpu_clk); in cpr_pd_attach_dev()
1514 if (ret != -EPROBE_DEFER) in cpr_pd_attach_dev()
1515 dev_err(drv->dev, "could not get cpu clk: %d\n", ret); in cpr_pd_attach_dev()
1518 drv->attached_cpu_dev = dev; in cpr_pd_attach_dev()
1520 dev_dbg(drv->dev, "using cpu clk from: %s\n", in cpr_pd_attach_dev()
1521 dev_name(drv->attached_cpu_dev)); in cpr_pd_attach_dev()
1531 ret = dev_pm_opp_get_opp_count(&drv->pd.dev); in cpr_pd_attach_dev()
1532 if (ret < 0) { in cpr_pd_attach_dev()
1533 dev_err(drv->dev, "could not get OPP count\n"); in cpr_pd_attach_dev()
1536 drv->num_corners = ret; in cpr_pd_attach_dev()
1538 if (drv->num_corners < 2) { in cpr_pd_attach_dev()
1539 dev_err(drv->dev, "need at least 2 OPPs to use CPR\n"); in cpr_pd_attach_dev()
1540 ret = -EINVAL; in cpr_pd_attach_dev()
1544 drv->corners = devm_kcalloc(drv->dev, drv->num_corners, in cpr_pd_attach_dev()
1545 sizeof(*drv->corners), in cpr_pd_attach_dev()
1547 if (!drv->corners) { in cpr_pd_attach_dev()
1548 ret = -ENOMEM; in cpr_pd_attach_dev()
1552 ret = cpr_corner_init(drv); in cpr_pd_attach_dev()
1556 cpr_set_loop_allowed(drv); in cpr_pd_attach_dev()
1558 ret = cpr_init_parameters(drv); in cpr_pd_attach_dev()
1563 ret = cpr_config(drv); in cpr_pd_attach_dev()
1567 ret = cpr_find_initial_corner(drv); in cpr_pd_attach_dev()
1571 if (acc_desc->config) in cpr_pd_attach_dev()
1572 regmap_multi_reg_write(drv->tcsr, acc_desc->config, in cpr_pd_attach_dev()
1573 acc_desc->num_regs_per_fuse); in cpr_pd_attach_dev()
1576 if (acc_desc->enable_mask) in cpr_pd_attach_dev()
1577 regmap_update_bits(drv->tcsr, acc_desc->enable_reg, in cpr_pd_attach_dev()
1578 acc_desc->enable_mask, in cpr_pd_attach_dev()
1579 acc_desc->enable_mask); in cpr_pd_attach_dev()
1581 dev_info(drv->dev, "driver initialized with %u OPPs\n", in cpr_pd_attach_dev()
1582 drv->num_corners); in cpr_pd_attach_dev()
1585 mutex_unlock(&drv->lock); in cpr_pd_attach_dev()
1594 struct cpr_drv *drv = s->private; in cpr_debug_info_show() local
1598 corner = drv->corner; in cpr_debug_info_show()
1599 fuse_corner = corner->fuse_corner; in cpr_debug_info_show()
1602 corner->last_uV); in cpr_debug_info_show()
1604 ro_sel = fuse_corner->ring_osc_idx; in cpr_debug_info_show()
1605 gcnt = cpr_read(drv, REG_RBCPR_GCNT_TARGET(ro_sel)); in cpr_debug_info_show()
1608 ctl = cpr_read(drv, REG_RBCPR_CTL); in cpr_debug_info_show()
1611 irq_status = cpr_read(drv, REG_RBIF_IRQ_STATUS); in cpr_debug_info_show()
1614 reg = cpr_read(drv, REG_RBCPR_RESULT_0); in cpr_debug_info_show()
1617 step_dn = reg & 0x01; in cpr_debug_info_show()
1618 step_up = (reg >> RBCPR_RESULT0_STEP_UP_SHIFT) & 0x01; in cpr_debug_info_show()
1630 error_lt0 = (reg >> RBCPR_RESULT0_ERROR_LT0_SHIFT) & 0x01; in cpr_debug_info_show()
1633 busy = (reg >> RBCPR_RESULT0_BUSY_SHIFT) & 0x01; in cpr_debug_info_show()
1636 return 0; in cpr_debug_info_show()
1640 static void cpr_debugfs_init(struct cpr_drv *drv) in cpr_debugfs_init() argument
1642 drv->debugfs = debugfs_create_dir("qcom_cpr", NULL); in cpr_debugfs_init()
1644 debugfs_create_file("debug_info", 0444, drv->debugfs, in cpr_debugfs_init()
1645 drv, &cpr_debug_info_fops); in cpr_debugfs_init()
1651 struct device *dev = &pdev->dev; in cpr_probe()
1652 struct cpr_drv *drv; in cpr_probe() local
1659 if (!data || !data->cpr_desc || !data->acc_desc) in cpr_probe()
1660 return -EINVAL; in cpr_probe()
1662 drv = devm_kzalloc(dev, sizeof(*drv), GFP_KERNEL); in cpr_probe()
1663 if (!drv) in cpr_probe()
1664 return -ENOMEM; in cpr_probe()
1665 drv->dev = dev; in cpr_probe()
1666 drv->desc = data->cpr_desc; in cpr_probe()
1667 drv->acc_desc = data->acc_desc; in cpr_probe()
1669 drv->fuse_corners = devm_kcalloc(dev, drv->desc->num_fuse_corners, in cpr_probe()
1670 sizeof(*drv->fuse_corners), in cpr_probe()
1672 if (!drv->fuse_corners) in cpr_probe()
1673 return -ENOMEM; in cpr_probe()
1675 np = of_parse_phandle(dev->of_node, "acc-syscon", 0); in cpr_probe()
1677 return -ENODEV; in cpr_probe()
1679 drv->tcsr = syscon_node_to_regmap(np); in cpr_probe()
1681 if (IS_ERR(drv->tcsr)) in cpr_probe()
1682 return PTR_ERR(drv->tcsr); in cpr_probe()
1684 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); in cpr_probe()
1685 drv->base = devm_ioremap_resource(dev, res); in cpr_probe()
1686 if (IS_ERR(drv->base)) in cpr_probe()
1687 return PTR_ERR(drv->base); in cpr_probe()
1689 irq = platform_get_irq(pdev, 0); in cpr_probe()
1690 if (irq < 0) in cpr_probe()
1691 return -EINVAL; in cpr_probe()
1693 drv->vdd_apc = devm_regulator_get(dev, "vdd-apc"); in cpr_probe()
1694 if (IS_ERR(drv->vdd_apc)) in cpr_probe()
1695 return PTR_ERR(drv->vdd_apc); in cpr_probe()
1708 drv->cpr_fuses = cpr_get_fuses(drv); in cpr_probe()
1709 if (IS_ERR(drv->cpr_fuses)) in cpr_probe()
1710 return PTR_ERR(drv->cpr_fuses); in cpr_probe()
1712 ret = cpr_populate_ring_osc_idx(drv); in cpr_probe()
1716 ret = cpr_fuse_corner_init(drv); in cpr_probe()
1720 mutex_init(&drv->lock); in cpr_probe()
1725 "cpr", drv); in cpr_probe()
1729 drv->pd.name = devm_kstrdup_const(dev, dev->of_node->full_name, in cpr_probe()
1731 if (!drv->pd.name) in cpr_probe()
1732 return -EINVAL; in cpr_probe()
1734 drv->pd.power_off = cpr_power_off; in cpr_probe()
1735 drv->pd.power_on = cpr_power_on; in cpr_probe()
1736 drv->pd.set_performance_state = cpr_set_performance_state; in cpr_probe()
1737 drv->pd.opp_to_performance_state = cpr_get_performance_state; in cpr_probe()
1738 drv->pd.attach_dev = cpr_pd_attach_dev; in cpr_probe()
1740 ret = pm_genpd_init(&drv->pd, NULL, true); in cpr_probe()
1744 ret = of_genpd_add_provider_simple(dev->of_node, &drv->pd); in cpr_probe()
1748 platform_set_drvdata(pdev, drv); in cpr_probe()
1749 cpr_debugfs_init(drv); in cpr_probe()
1751 return 0; in cpr_probe()
1754 pm_genpd_remove(&drv->pd); in cpr_probe()
1760 struct cpr_drv *drv = platform_get_drvdata(pdev); in cpr_remove() local
1762 if (cpr_is_allowed(drv)) { in cpr_remove()
1763 cpr_ctl_disable(drv); in cpr_remove()
1764 cpr_irq_set(drv, 0); in cpr_remove()
1767 of_genpd_del_provider(pdev->dev.of_node); in cpr_remove()
1768 pm_genpd_remove(&drv->pd); in cpr_remove()
1770 debugfs_remove_recursive(drv->debugfs); in cpr_remove()
1772 return 0; in cpr_remove()
1776 { .compatible = "qcom,qcs404-cpr", .data = &qcs404_cpr_acc_desc },
1785 .name = "qcom-cpr",