Lines Matching full:abb
3 * Texas Instruments SoC Adaptive Body Bias(ABB) Regulator
24 * ABB LDO operating states:
25 * NOMINAL_OPP: bypasses the ABB LDO
26 * FAST_OPP: sets ABB LDO to Forward Body-Bias
27 * SLOW_OPP: sets ABB LDO to Reverse Body-Bias
34 * struct ti_abb_info - ABB information per voltage setting
47 * struct ti_abb_reg - Register description for ABB block
73 * struct ti_abb - ABB instance data
75 * @clk: clock(usually sysclk) supplying ABB block
76 * @base: base address of ABB block
77 * @setup_reg: setup register of ABB block
78 * @control_reg: control register of ABB block
80 * @efuse_base: (optional) efuse base address for ABB modes
82 * @regs: pointer to struct ti_abb_reg for ABB block
87 * @info: array to per voltage ABB configuration
133 * ti_abb_check_txdone() - handy wrapper to check ABB tranxdone status
134 * @abb: pointer to the abb instance
138 static inline bool ti_abb_check_txdone(const struct ti_abb *abb) in ti_abb_check_txdone() argument
140 return !!(readl(abb->int_base) & abb->txdone_mask); in ti_abb_check_txdone()
144 * ti_abb_clear_txdone() - handy wrapper to clear ABB tranxdone status
145 * @abb: pointer to the abb instance
147 static inline void ti_abb_clear_txdone(const struct ti_abb *abb) in ti_abb_clear_txdone() argument
149 writel(abb->txdone_mask, abb->int_base); in ti_abb_clear_txdone()
153 * ti_abb_wait_txdone() - waits for ABB tranxdone event
155 * @abb: pointer to the abb instance
159 static int ti_abb_wait_txdone(struct device *dev, struct ti_abb *abb) in ti_abb_wait_txdone() argument
164 while (timeout++ <= abb->settling_time) { in ti_abb_wait_txdone()
165 status = ti_abb_check_txdone(abb); in ti_abb_wait_txdone()
173 __func__, timeout, readl(abb->int_base)); in ti_abb_wait_txdone()
178 * ti_abb_clear_all_txdone() - clears ABB tranxdone event
180 * @abb: pointer to the abb instance
184 static int ti_abb_clear_all_txdone(struct device *dev, const struct ti_abb *abb) in ti_abb_clear_all_txdone() argument
189 while (timeout++ <= abb->settling_time) { in ti_abb_clear_all_txdone()
190 ti_abb_clear_txdone(abb); in ti_abb_clear_all_txdone()
192 status = ti_abb_check_txdone(abb); in ti_abb_clear_all_txdone()
200 __func__, timeout, readl(abb->int_base)); in ti_abb_clear_all_txdone()
207 * @abb: pointer to the abb instance
208 * @info: ABB info to program
210 static void ti_abb_program_ldovbb(struct device *dev, const struct ti_abb *abb, in ti_abb_program_ldovbb() argument
215 val = readl(abb->ldo_base); in ti_abb_program_ldovbb()
217 val &= ~(abb->ldovbb_override_mask | abb->ldovbb_vset_mask); in ti_abb_program_ldovbb()
222 val |= abb->ldovbb_override_mask; in ti_abb_program_ldovbb()
223 val |= info->vset << __ffs(abb->ldovbb_vset_mask); in ti_abb_program_ldovbb()
227 writel(val, abb->ldo_base); in ti_abb_program_ldovbb()
231 * ti_abb_set_opp() - Setup ABB and LDO VBB for required bias
233 * @abb: pointer to the abb instance
234 * @info: ABB info to program
238 static int ti_abb_set_opp(struct regulator_dev *rdev, struct ti_abb *abb, in ti_abb_set_opp() argument
241 const struct ti_abb_reg *regs = abb->regs; in ti_abb_set_opp()
245 ret = ti_abb_clear_all_txdone(dev, abb); in ti_abb_set_opp()
249 ti_abb_rmw(regs->fbb_sel_mask | regs->rbb_sel_mask, 0, abb->setup_reg); in ti_abb_set_opp()
253 ti_abb_rmw(regs->rbb_sel_mask, 1, abb->setup_reg); in ti_abb_set_opp()
256 ti_abb_rmw(regs->fbb_sel_mask, 1, abb->setup_reg); in ti_abb_set_opp()
260 /* program next state of ABB ldo */ in ti_abb_set_opp()
261 ti_abb_rmw(regs->opp_sel_mask, info->opp_sel, abb->control_reg); in ti_abb_set_opp()
268 if (abb->ldo_base && info->opp_sel != TI_ABB_NOMINAL_OPP) in ti_abb_set_opp()
269 ti_abb_program_ldovbb(dev, abb, info); in ti_abb_set_opp()
271 /* Initiate ABB ldo change */ in ti_abb_set_opp()
272 ti_abb_rmw(regs->opp_change_mask, 1, abb->control_reg); in ti_abb_set_opp()
274 /* Wait for ABB LDO to complete transition to new Bias setting */ in ti_abb_set_opp()
275 ret = ti_abb_wait_txdone(dev, abb); in ti_abb_set_opp()
279 ret = ti_abb_clear_all_txdone(dev, abb); in ti_abb_set_opp()
288 if (abb->ldo_base && info->opp_sel == TI_ABB_NOMINAL_OPP) in ti_abb_set_opp()
289 ti_abb_program_ldovbb(dev, abb, info); in ti_abb_set_opp()
296 * ti_abb_set_voltage_sel() - regulator accessor function to set ABB LDO
298 * @sel: selector to index into required ABB LDO settings (maps to
306 struct ti_abb *abb = rdev_get_drvdata(rdev); in ti_abb_set_voltage_sel() local
311 if (!abb) { in ti_abb_set_voltage_sel()
317 if (!desc->n_voltages || !abb->info) { in ti_abb_set_voltage_sel()
331 if (sel == abb->current_info_idx) { in ti_abb_set_voltage_sel()
336 info = &abb->info[sel]; in ti_abb_set_voltage_sel()
343 if (abb->current_info_idx == -EINVAL) in ti_abb_set_voltage_sel()
347 oinfo = &abb->info[abb->current_info_idx]; in ti_abb_set_voltage_sel()
350 sel, abb->current_info_idx); in ti_abb_set_voltage_sel()
355 ret = ti_abb_set_opp(rdev, abb, info); in ti_abb_set_voltage_sel()
359 abb->current_info_idx = sel; in ti_abb_set_voltage_sel()
369 * ti_abb_get_voltage_sel() - Regulator accessor to get current ABB LDO setting
377 struct ti_abb *abb = rdev_get_drvdata(rdev); in ti_abb_get_voltage_sel() local
380 if (!abb) { in ti_abb_get_voltage_sel()
386 if (!desc->n_voltages || !abb->info) { in ti_abb_get_voltage_sel()
393 if (abb->current_info_idx >= (int)desc->n_voltages) { in ti_abb_get_voltage_sel()
395 __func__, abb->current_info_idx, desc->n_voltages); in ti_abb_get_voltage_sel()
399 return abb->current_info_idx; in ti_abb_get_voltage_sel()
403 * ti_abb_init_timings() - setup ABB clock timing for the current platform
405 * @abb: pointer to the abb instance
409 static int ti_abb_init_timings(struct device *dev, struct ti_abb *abb) in ti_abb_init_timings() argument
413 const struct ti_abb_reg *regs = abb->regs; in ti_abb_init_timings()
418 ret = of_property_read_u32(dev->of_node, pname, &abb->settling_time); in ti_abb_init_timings()
424 /* ABB LDO cannot be settle in 0 time */ in ti_abb_init_timings()
425 if (!abb->settling_time) { in ti_abb_init_timings()
436 /* ABB LDO cannot be settle in 0 clock cycles */ in ti_abb_init_timings()
442 abb->clk = devm_clk_get(dev, NULL); in ti_abb_init_timings()
443 if (IS_ERR(abb->clk)) { in ti_abb_init_timings()
444 ret = PTR_ERR(abb->clk); in ti_abb_init_timings()
450 * SR2_WTCNT_VALUE is the settling time for the ABB ldo after a in ti_abb_init_timings()
473 clk_rate = DIV_ROUND_CLOSEST(clk_get_rate(abb->clk), 1000000); in ti_abb_init_timings()
479 sr2_wt_cnt_val = DIV_ROUND_CLOSEST(abb->settling_time * 10, cycle_rate); in ti_abb_init_timings()
482 clk_get_rate(abb->clk), sr2_wt_cnt_val); in ti_abb_init_timings()
484 ti_abb_rmw(regs->sr2_wtcnt_value_mask, sr2_wt_cnt_val, abb->setup_reg); in ti_abb_init_timings()
490 * ti_abb_init_table() - Initialize ABB table from device tree
492 * @abb: pointer to the abb instance
497 static int ti_abb_init_table(struct device *dev, struct ti_abb *abb, in ti_abb_init_table() argument
510 * of voltage and a set of detection logic for ABB information for that in ti_abb_init_table()
530 abb->info = info; in ti_abb_init_table()
537 abb->rdesc.n_voltages = num_entries; in ti_abb_init_table()
538 abb->rdesc.volt_table = volt_table; in ti_abb_init_table()
540 abb->current_info_idx = -EINVAL; in ti_abb_init_table()
561 "[%d]v=%d ABB=%d ef=0x%x rbb=0x%x fbb=0x%x vset=0x%x\n", in ti_abb_init_table()
571 if (!abb->efuse_base) { in ti_abb_init_table()
579 efuse_val = readl(abb->efuse_base + efuse_offset); in ti_abb_init_table()
581 /* Use ABB recommendation from Efuse */ in ti_abb_init_table()
590 "[%d]v=%d efusev=0x%x final ABB=%d\n", in ti_abb_init_table()
594 if (!abb->ldo_base) { in ti_abb_init_table()
610 dev_err(dev, "%s:[%d]v=%d, ABB=%d is invalid! Abort!\n", in ti_abb_init_table()
630 /* Default ABB block offsets, IF this changes in future, create new one */
669 {.compatible = "ti,abb-v1", .data = &abb_regs_v1},
670 {.compatible = "ti,abb-v2", .data = &abb_regs_v2},
671 {.compatible = "ti,abb-v3", .data = &abb_regs_generic},
678 * ti_abb_probe() - Initialize an ABB ldo instance
679 * @pdev: ABB platform device
681 * Initializes an individual ABB LDO for required Body-Bias. ABB is used to
691 struct ti_abb *abb; in ti_abb_probe() local
700 abb = devm_kzalloc(dev, sizeof(struct ti_abb), GFP_KERNEL); in ti_abb_probe()
701 if (!abb) in ti_abb_probe()
704 abb->regs = device_get_match_data(dev); in ti_abb_probe()
705 if (!abb->regs) { in ti_abb_probe()
710 /* Map ABB resources */ in ti_abb_probe()
711 if (abb->regs->setup_off || abb->regs->control_off) { in ti_abb_probe()
712 abb->base = devm_platform_ioremap_resource_byname(pdev, "base-address"); in ti_abb_probe()
713 if (IS_ERR(abb->base)) in ti_abb_probe()
714 return PTR_ERR(abb->base); in ti_abb_probe()
716 abb->setup_reg = abb->base + abb->regs->setup_off; in ti_abb_probe()
717 abb->control_reg = abb->base + abb->regs->control_off; in ti_abb_probe()
720 abb->control_reg = devm_platform_ioremap_resource_byname(pdev, "control-address"); in ti_abb_probe()
721 if (IS_ERR(abb->control_reg)) in ti_abb_probe()
722 return PTR_ERR(abb->control_reg); in ti_abb_probe()
724 abb->setup_reg = devm_platform_ioremap_resource_byname(pdev, "setup-address"); in ti_abb_probe()
725 if (IS_ERR(abb->setup_reg)) in ti_abb_probe()
726 return PTR_ERR(abb->setup_reg); in ti_abb_probe()
737 * shared between regulator-abb-{ivahd,dspeve,gpu} driver in ti_abb_probe()
742 abb->int_base = devm_ioremap(dev, res->start, in ti_abb_probe()
744 if (!abb->int_base) { in ti_abb_probe()
762 abb->efuse_base = devm_ioremap(dev, res->start, in ti_abb_probe()
764 if (!abb->efuse_base) { in ti_abb_probe()
776 abb->ldo_base = devm_ioremap_resource(dev, res); in ti_abb_probe()
777 if (IS_ERR(abb->ldo_base)) in ti_abb_probe()
778 return PTR_ERR(abb->ldo_base); in ti_abb_probe()
784 &abb->ldovbb_override_mask); in ti_abb_probe()
789 if (!abb->ldovbb_override_mask) { in ti_abb_probe()
797 &abb->ldovbb_vset_mask); in ti_abb_probe()
802 if (!abb->ldovbb_vset_mask) { in ti_abb_probe()
811 &abb->txdone_mask); in ti_abb_probe()
816 if (!abb->txdone_mask) { in ti_abb_probe()
822 &abb->rdesc); in ti_abb_probe()
829 /* init ABB opp_sel table */ in ti_abb_probe()
830 ret = ti_abb_init_table(dev, abb, initdata); in ti_abb_probe()
834 /* init ABB timing */ in ti_abb_probe()
835 ret = ti_abb_init_timings(dev, abb); in ti_abb_probe()
839 desc = &abb->rdesc; in ti_abb_probe()
852 config.driver_data = abb; in ti_abb_probe()
865 ti_abb_rmw(abb->regs->sr2_en_mask, 1, abb->setup_reg); in ti_abb_probe()
882 MODULE_DESCRIPTION("Texas Instruments ABB LDO regulator driver");