mirror of
https://git.yoctoproject.org/meta-ti
synced 2026-07-16 22:38:04 +00:00
ad47faedaf
This makes 'git am' work again, patch is more forgiving with fuzz. Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
275 lines
8.1 KiB
Diff
275 lines
8.1 KiB
Diff
From 35fc68e090a4f4241c7b3488fd24e82b3f839994 Mon Sep 17 00:00:00 2001
|
|
From: Mike Turquette <mturquette@ti.com>
|
|
Date: Wed, 29 Jun 2011 17:25:59 -0700
|
|
Subject: [PATCH 7/8] OMAP3+: ABB: initialization & transition functions
|
|
|
|
The Adaptive Body-Bias ldo can be set to bypass or Forward Body-Bias
|
|
after voltage scaling is performed.
|
|
|
|
This patch implements the Adaptive Body-Bias ldo initialization routine
|
|
and the transition sequence which is needed after a vc_bypass or
|
|
vp_forceupdate sequence completes.
|
|
|
|
Signed-off-by: Mike Turquette <mturquette@ti.com>
|
|
---
|
|
arch/arm/mach-omap2/Makefile | 2 +-
|
|
arch/arm/mach-omap2/abb.c | 218 ++++++++++++++++++++++++++++++++++++++++++
|
|
arch/arm/mach-omap2/abb.h | 5 +
|
|
3 files changed, 224 insertions(+), 1 deletions(-)
|
|
create mode 100644 arch/arm/mach-omap2/abb.c
|
|
|
|
diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
|
|
index 5bc306c..d0dd488 100644
|
|
--- a/arch/arm/mach-omap2/Makefile
|
|
+++ b/arch/arm/mach-omap2/Makefile
|
|
@@ -94,7 +94,7 @@ obj-$(CONFIG_ARCH_OMAP4) += prcm.o cm2xxx_3xxx.o cminst44xx.o \
|
|
|
|
# OMAP voltage domains
|
|
ifeq ($(CONFIG_PM),y)
|
|
-voltagedomain-common := voltage.o vc.o vp.o
|
|
+voltagedomain-common := voltage.o vc.o vp.o abb.o
|
|
obj-$(CONFIG_ARCH_OMAP2) += $(voltagedomain-common) \
|
|
voltagedomains2xxx_data.o
|
|
obj-$(CONFIG_ARCH_OMAP3) += $(voltagedomain-common) \
|
|
diff --git a/arch/arm/mach-omap2/abb.c b/arch/arm/mach-omap2/abb.c
|
|
new file mode 100644
|
|
index 0000000..4d42b67
|
|
--- /dev/null
|
|
+++ b/arch/arm/mach-omap2/abb.c
|
|
@@ -0,0 +1,218 @@
|
|
+/*
|
|
+ * OMAP Adaptive Body-Bias core
|
|
+ *
|
|
+ * Copyright (C) 2011 Texas Instruments, Inc.
|
|
+ * Mike Turquette <mturquette@ti.com>
|
|
+ *
|
|
+ * This program is free software; you can redistribute it and/or modify
|
|
+ * it under the terms of the GNU General Public License version 2 as
|
|
+ * published by the Free Software Foundation.
|
|
+ */
|
|
+
|
|
+#include <linux/init.h>
|
|
+#include <linux/delay.h>
|
|
+
|
|
+#include "abb.h"
|
|
+#include "voltage.h"
|
|
+
|
|
+/*
|
|
+ * omap_abb_set_opp - program ABB ldo based on new voltage
|
|
+ *
|
|
+ * @voltdm - pointer to voltage domain that just finished scaling voltage
|
|
+ *
|
|
+ * Look up the ABB ldo state for the new voltage that voltdm just finished
|
|
+ * transitioning to and compare it to current ldo state. If a change is needed
|
|
+ * then clear appropriate PRM_IRQSTATUS bit, transition ldo and then clear
|
|
+ * PRM_IRQSTATUS bit again. Returns 0 on success, -EERROR otherwise.
|
|
+ */
|
|
+int omap_abb_set_opp(struct voltagedomain *voltdm)
|
|
+{
|
|
+ struct omap_abb_instance *abb = voltdm->abb;
|
|
+ struct omap_volt_data *volt_data;
|
|
+ int ret, timeout;
|
|
+ u8 opp_sel;
|
|
+
|
|
+ /* fetch the ABB ldo OPP_SEL value for the new voltage */
|
|
+ volt_data = omap_voltage_get_voltdata(voltdm, voltdm->nominal_volt);
|
|
+
|
|
+ if (IS_ERR_OR_NULL(volt_data))
|
|
+ return -EINVAL;
|
|
+
|
|
+ opp_sel = volt_data->opp_sel;
|
|
+
|
|
+ /* bail early if no transition is necessary */
|
|
+ if (opp_sel == abb->_opp_sel)
|
|
+ return 0;
|
|
+
|
|
+ /* clear interrupt status */
|
|
+ timeout = 0;
|
|
+ while (timeout++ < ABB_TRANXDONE_TIMEOUT) {
|
|
+ abb->common->ops->clear_tranxdone(abb->prm_irq_id);
|
|
+
|
|
+ ret = abb->common->ops->check_tranxdone(abb->prm_irq_id);
|
|
+ if (!ret)
|
|
+ break;
|
|
+
|
|
+ udelay(1);
|
|
+ }
|
|
+
|
|
+ if (timeout>= ABB_TRANXDONE_TIMEOUT) {
|
|
+ pr_warning("%s: vdd_%s ABB TRANXDONE timeout\n",
|
|
+ __func__, voltdm->name);
|
|
+ return -ETIMEDOUT;
|
|
+ }
|
|
+
|
|
+ /* program next state of ABB ldo */
|
|
+ voltdm->rmw(abb->common->opp_sel_mask,
|
|
+ opp_sel << __ffs(abb->common->opp_sel_mask),
|
|
+ abb->ctrl_offs);
|
|
+
|
|
+ /* initiate ABB ldo change */
|
|
+ voltdm->rmw(abb->common->opp_change_mask,
|
|
+ abb->common->opp_change_mask,
|
|
+ abb->ctrl_offs);
|
|
+
|
|
+ /* clear interrupt status */
|
|
+ timeout = 0;
|
|
+ while (timeout++ < ABB_TRANXDONE_TIMEOUT) {
|
|
+ abb->common->ops->clear_tranxdone(abb->prm_irq_id);
|
|
+
|
|
+ ret = abb->common->ops->check_tranxdone(abb->prm_irq_id);
|
|
+ if (!ret)
|
|
+ break;
|
|
+
|
|
+ udelay(1);
|
|
+ }
|
|
+
|
|
+ if (timeout>= ABB_TRANXDONE_TIMEOUT) {
|
|
+ pr_warning("%s: vdd_%s ABB TRANXDONE timeout\n",
|
|
+ __func__, voltdm->name);
|
|
+ return -ETIMEDOUT;
|
|
+ }
|
|
+
|
|
+ /* track internal state */
|
|
+ abb->_opp_sel = opp_sel;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * omap_abb_enable - enable ABB ldo on a particular voltage domain
|
|
+ *
|
|
+ * @voltdm - pointer to particular voltage domain
|
|
+ */
|
|
+void omap_abb_enable(struct voltagedomain *voltdm)
|
|
+{
|
|
+ struct omap_abb_instance *abb = voltdm->abb;
|
|
+
|
|
+ if (abb->enabled)
|
|
+ return;
|
|
+
|
|
+ abb->enabled = true;
|
|
+
|
|
+ voltdm->rmw(abb->common->sr2en_mask, abb->common->sr2en_mask,
|
|
+ abb->setup_offs);
|
|
+}
|
|
+
|
|
+/*
|
|
+ * omap_abb_disable - disable ABB ldo on a particular voltage domain
|
|
+ *
|
|
+ * @voltdm - pointer to particular voltage domain
|
|
+ *
|
|
+ * Included for completeness. Not currently used but will be needed in the
|
|
+ * future if ABB is converted to a loadable module.
|
|
+ */
|
|
+void omap_abb_disable(struct voltagedomain *voltdm)
|
|
+{
|
|
+ struct omap_abb_instance *abb = voltdm->abb;
|
|
+
|
|
+ if (!abb->enabled)
|
|
+ return;
|
|
+
|
|
+ abb->enabled = false;
|
|
+
|
|
+ voltdm->rmw(abb->common->sr2en_mask,
|
|
+ (0 << __ffs(abb->common->sr2en_mask)),
|
|
+ abb->setup_offs);
|
|
+}
|
|
+
|
|
+/*
|
|
+ * omap_abb_init - Initialize an ABB ldo instance
|
|
+ *
|
|
+ * @voltdm: voltage domain upon which ABB ldo resides
|
|
+ *
|
|
+ * Initializes an individual ABB ldo for Forward Body-Bias. FBB is used to
|
|
+ * insure stability at higher voltages. Note that some older OMAP chips have a
|
|
+ * Reverse Body-Bias mode meant to save power at low voltage, but that mode is
|
|
+ * unsupported and phased out on newer chips.
|
|
+ */
|
|
+void __init omap_abb_init(struct voltagedomain *voltdm)
|
|
+{
|
|
+ struct omap_abb_instance *abb = voltdm->abb;
|
|
+ u32 sys_clk_rate;
|
|
+ u32 sr2_wt_cnt_val;
|
|
+ u32 clock_cycles;
|
|
+ u32 settling_time;
|
|
+ u32 val;
|
|
+
|
|
+ if(IS_ERR_OR_NULL(abb))
|
|
+ return;
|
|
+
|
|
+ /*
|
|
+ * SR2_WTCNT_VALUE is the settling time for the ABB ldo after a
|
|
+ * transition and must be programmed with the correct time at boot.
|
|
+ * The value programmed into the register is the number of SYS_CLK
|
|
+ * clock cycles that match a given wall time profiled for the ldo.
|
|
+ * This value depends on:
|
|
+ * settling time of ldo in micro-seconds (varies per OMAP family)
|
|
+ * # of clock cycles per SYS_CLK period (varies per OMAP family)
|
|
+ * the SYS_CLK frequency in MHz (varies per board)
|
|
+ * The formula is:
|
|
+ *
|
|
+ * ldo settling time (in micro-seconds)
|
|
+ * SR2_WTCNT_VALUE = ------------------------------------------
|
|
+ * (# system clock cycles) * (sys_clk period)
|
|
+ *
|
|
+ * Put another way:
|
|
+ *
|
|
+ * SR2_WTCNT_VALUE = settling time / (# SYS_CLK cycles / SYS_CLK rate))
|
|
+ *
|
|
+ * To avoid dividing by zero multiply both "# clock cycles" and
|
|
+ * "settling time" by 10 such that the final result is the one we want.
|
|
+ */
|
|
+
|
|
+ /* convert SYS_CLK rate to MHz & prevent divide by zero */
|
|
+ sys_clk_rate = DIV_ROUND_CLOSEST(voltdm->sys_clk.rate, 1000000);
|
|
+ clock_cycles = abb->common->clock_cycles * 10;
|
|
+ settling_time = abb->common->settling_time * 10;
|
|
+
|
|
+ /* calculate cycle rate */
|
|
+ clock_cycles = DIV_ROUND_CLOSEST(clock_cycles, sys_clk_rate);
|
|
+
|
|
+ /* calulate SR2_WTCNT_VALUE */
|
|
+ sr2_wt_cnt_val = DIV_ROUND_CLOSEST(settling_time, clock_cycles);
|
|
+
|
|
+ voltdm->rmw(abb->common->sr2_wtcnt_value_mask,
|
|
+ (sr2_wt_cnt_val << __ffs(abb->common->sr2_wtcnt_value_mask)),
|
|
+ abb->setup_offs);
|
|
+
|
|
+ /* allow Forward Body-Bias */
|
|
+ voltdm->rmw(abb->common->active_fbb_sel_mask,
|
|
+ abb->common->active_fbb_sel_mask,
|
|
+ abb->setup_offs);
|
|
+
|
|
+ /* did bootloader set OPP_SEL? */
|
|
+ val = voltdm->read(abb->ctrl_offs);
|
|
+ val &= abb->common->opp_sel_mask;
|
|
+ abb->_opp_sel = val >> __ffs(abb->common->opp_sel_mask);
|
|
+
|
|
+ /* enable the ldo if not done by bootloader */
|
|
+ val = voltdm->read(abb->setup_offs);
|
|
+ val &= abb->common->sr2en_mask;
|
|
+ if (val)
|
|
+ abb->enabled = true;
|
|
+ else
|
|
+ omap_abb_enable(voltdm);
|
|
+
|
|
+ return;
|
|
+}
|
|
diff --git a/arch/arm/mach-omap2/abb.h b/arch/arm/mach-omap2/abb.h
|
|
index 74f2044..c06c7d6 100644
|
|
--- a/arch/arm/mach-omap2/abb.h
|
|
+++ b/arch/arm/mach-omap2/abb.h
|
|
@@ -82,4 +82,9 @@ extern struct omap_abb_instance omap36xx_abb_mpu;
|
|
extern struct omap_abb_instance omap4_abb_mpu;
|
|
extern struct omap_abb_instance omap4_abb_iva;
|
|
|
|
+void omap_abb_init(struct voltagedomain *voltdm);
|
|
+void omap_abb_enable(struct voltagedomain *voltdm);
|
|
+void omap_abb_disble(struct voltagedomain *voltdm);
|
|
+int omap_abb_set_opp(struct voltagedomain *voltdm);
|
|
+
|
|
#endif
|
|
--
|
|
1.6.6.1
|
|
|