Skip to contentSkip to conversation

Adaptive Body-Bias for OMAP

RFC PATCH New Mike Turquette 5 participants 15 messages Oct 4, 2012 – Oct 16, 2012

Subsystems (4)
lore
Share & tools
lore
#0 lore raw

cover Adaptive Body-Bias for OMAP

From: Mike Turquette <[email protected]>

Adaptive Body-Bias ldos are present for some voltage domains starting with OMAP3630. They have three modes of operation:

* Bypass - the default, it just follows the vdd voltage
* Foward Body-Bias - applies voltage bias to increase transistor performance at the cost of power. Used to operate safely at high OPPs
* Reverse Body-Bias - applies voltage bias to decrease leakage and save power. Used to save power at lower OPPs

This series adds the ABB code and per-voltage domain data for OMAP3630 and OMAP4430. Newer OMAP4 chips and OMAP5 will need this data populated once those platforms have OPP and voltage tables. The voltage domain scaling sequence is modified use these new functions.

This series build on top my previous series, "Introduce .get_voltage callback into voltdm"[1]. While not strictly necessary that series does take some steps to eliminate one combination of ABB and VP/VC modes that is out-of-spec.

[1] http://marc.info/?l=linux-omap&m=134931341818379&w=2

Mike Turquette (7):
ARM: omap: add 3630 PRM register definitions
ARM: omap: add ABB PRM_IRQSTATUS handlers
ARM: omap: Adaptive Body-Bias structures & data
ARM: omap: opp: add ABB data to voltage tables
ARM: omap: voltage: per-voltage domain ABB data
ARM: omap: abb: init & transition functions
ARM: omap: voltage: add ABB to voltage scaling

 arch/arm/mach-omap2/Makefile                  |    8 +-
 arch/arm/mach-omap2/abb.c                     |  322 +++++++++++++++++++++++++
 arch/arm/mach-omap2/abb.h                     |   94 ++++++++
 arch/arm/mach-omap2/abb36xx_data.c            |   39 +++
 arch/arm/mach-omap2/abb44xx_data.c            |   45 ++++
 arch/arm/mach-omap2/omap_opp_data.h           |    5 +-
 arch/arm/mach-omap2/opp3xxx_data.c            |   37 +--
 arch/arm/mach-omap2/opp4xxx_data.c            |   25 +-
 arch/arm/mach-omap2/prm-regbits-34xx.h        |   34 +++
 arch/arm/mach-omap2/prm2xxx_3xxx.c            |   36 +++
 arch/arm/mach-omap2/prm2xxx_3xxx.h            |    8 +
 arch/arm/mach-omap2/prm44xx.c                 |   44 ++++
 arch/arm/mach-omap2/prm44xx.h                 |    4 +
 arch/arm/mach-omap2/voltage.c                 |   28 ++-
 arch/arm/mach-omap2/voltage.h                 |    1 +
 arch/arm/mach-omap2/voltagedomains3xxx_data.c |    2 +
 arch/arm/mach-omap2/voltagedomains44xx_data.c |    3 +
 arch/arm/plat-omap/include/plat/voltage.h     |    1 +
 18 files changed, 699 insertions(+), 37 deletions(-)
 create mode 100644 arch/arm/mach-omap2/abb.c
 create mode 100644 arch/arm/mach-omap2/abb.h
 create mode 100644 arch/arm/mach-omap2/abb36xx_data.c
 create mode 100644 arch/arm/mach-omap2/abb44xx_data.c
Signature · 1 line
1.7.9.5
#1 lore raw

PATCH 1/7 ARM: omap: add 3630 PRM register definitions

OMAP3630 supports an Adaptive Body-Bias ldo as well as some MPU interrupts related to voltage control that are not present on OMAP34XX. This patch adds the offsets, register addresses, bitfield shifts and masks to support this feature.

---
 arch/arm/mach-omap2/prm-regbits-34xx.h |   34 ++++++++++++++++++++++++++++++++
 arch/arm/mach-omap2/prm2xxx_3xxx.h     |    4 ++++
 2 files changed, 38 insertions(+)
arch/arm/mach-omap2/prm-regbits-34xx.h +34 -0
index 64c087a..0309ff6 100644
@@ -216,6 +216,12 @@
 /* PRM_SYSCONFIG specific bits */
 
 /* PRM_IRQSTATUS_MPU specific bits */
+#define OMAP3630_VC_BYPASS_ACK_ST_SHIFT			28
+#define OMAP3630_VC_BYPASS_ACK_ST_MASK			(1 << 28)
+#define OMAP3630_VC_VP1_ACK_ST_SHIFT			27
+#define OMAP3630_VC_VP1_ACK_ST_MASK			(1 << 27)
+#define OMAP3630_ABB_LDO_TRANXDONE_ST_SHIFT		26
+#define OMAP3630_ABB_LDO_TRANXDONE_ST_MASK		(1 << 26)
 #define OMAP3430ES2_SND_PERIPH_DPLL_ST_SHIFT		25
 #define OMAP3430ES2_SND_PERIPH_DPLL_ST_MASK		(1 << 25)
 #define OMAP3430_VC_TIMEOUTERR_ST_MASK			(1 << 24)
@@ -248,6 +254,12 @@
 #define OMAP3430_FS_USB_WKUP_ST_MASK			(1 << 1)
 
 /* PRM_IRQENABLE_MPU specific bits */
+#define OMAP3630_VC_BYPASS_ACK_EN_SHIFT				28
+#define OMAP3630_VC_BYPASS_ACK_EN_MASK				(1 << 28)
+#define OMAP3630_VC_VP1_ACK_EN_SHIFT				27
+#define OMAP3630_VC_VP1_ACK_EN_MASK				(1 << 27)
+#define OMAP3630_ABB_LDO_TRANXDONE_EN_SHIFT			26
+#define OMAP3630_ABB_LDO_TRANXDONE_EN_MASK			(1 << 26)
 #define OMAP3430ES2_SND_PERIPH_DPLL_RECAL_EN_SHIFT		25
 #define OMAP3430ES2_SND_PERIPH_DPLL_RECAL_EN_MASK		(1 << 25)
 #define OMAP3430_VC_TIMEOUTERR_EN_MASK				(1 << 24)
@@ -587,6 +599,28 @@
 
 /* PRM_VP2_STATUS specific bits */
 
+/* PRM_LDO_ABB_SETUP specific bits */
+#define OMAP3630_SR2_IN_TRANSITION_SHIFT		6
+#define OMAP3630_SR2_IN_TRANSITION_MASK			(1 << 6)
+#define OMAP3630_SR2_STATUS_SHIFT			3
+#define OMAP3630_SR2_STATUS_MASK			(3 << 3)
+#define OMAP3630_OPP_CHANGE_SHIFT			2
+#define OMAP3630_OPP_CHANGE_MASK			(1 << 2)
+#define OMAP3630_OPP_SEL_SHIFT				0
+#define OMAP3630_OPP_SEL_MASK				(3 << 0)
+
+/* PRM_LDO_ABB_CTRL specific bits */
+#define OMAP3630_SR2_WTCNT_VALUE_SHIFT			8
+#define OMAP3630_SR2_WTCNT_VALUE_MASK			(0xff << 8)
+#define OMAP3630_SLEEP_RBB_SEL_SHIFT			3
+#define OMAP3630_SLEEP_RBB_SEL_MASK			(1 << 3)
+#define OMAP3630_ACTIVE_FBB_SEL_SHIFT			2
+#define OMAP3630_ACTIVE_FBB_SEL_MASK			(1 << 2)
+#define OMAP3630_ACTIVE_RBB_SEL_SHIFT			1
+#define OMAP3630_ACTIVE_RBB_SEL_MASK			(1 << 1)
+#define OMAP3630_SR2EN_SHIFT				0
+#define OMAP3630_SR2EN_MASK				(1 << 0)
+
 /* RM_RSTST_NEON specific bits */
 
 /* PM_WKDEP_NEON specific bits */
arch/arm/mach-omap2/prm2xxx_3xxx.h +4 -0
index c19d249..c9eea9a 100644
@@ -167,6 +167,10 @@
 #define OMAP3430_PRM_VP2_VOLTAGE	OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x00e0)
 #define OMAP3_PRM_VP2_STATUS_OFFSET	0x00e4
 #define OMAP3430_PRM_VP2_STATUS		OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x00e4)
+#define OMAP3_PRM_LDO_ABB_SETUP_OFFSET	0x00f0
+#define OMAP3630_PRM_LDO_ABB_SETUP	OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x00f0)
+#define OMAP3_PRM_LDO_ABB_CTRL_OFFSET	0x00f4
+#define OMAP3630_PRM_LDO_ABB_CTRL	OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x00f4)
 
 #define OMAP3_PRM_CLKSEL_OFFSET	0x0040
 #define OMAP3430_PRM_CLKSEL		OMAP34XX_PRM_REGADDR(OMAP3430_CCR_MOD, 0x0040)
Signature · 1 line
1.7.9.5
#2 lore raw

PATCH 2/7 ARM: omap: add ABB PRM_IRQSTATUS handlers

In reply to Mike Turquette

Some PRM_IRQSTATUS registers contain a bit to signal that an ABB LDO transition has completed. These tranxdone bits exist for every instance of an ABB LDO; thus these tranxdone bits are supported on 36xx variants for the MPU voltage domain, and on 44xx variants for the MPU and IVA voltage domains.

This patch introduces some data structures and helper functions for checking on and clearing the TRANXDONE bits. They are a copy-paste of existing VP functions of similar nature and will be used in forthcoming patches that control the ABB programming sequence during a DVFS transition.

Some previous discussion on the design of the ABB PRM handlers can be found here:
http://article.gmane.org/gmane.linux.ports.arm.omap/63609

---
 arch/arm/mach-omap2/prm2xxx_3xxx.c |   36 +++++++++++++++++++++++++++++
 arch/arm/mach-omap2/prm2xxx_3xxx.h |    4 ++++
 arch/arm/mach-omap2/prm44xx.c      |   44 ++++++++++++++++++++++++++++++++++++
 arch/arm/mach-omap2/prm44xx.h      |    4 ++++
 4 files changed, 88 insertions(+)
arch/arm/mach-omap2/prm2xxx_3xxx.c +36 -0
index a0309de..8d3c63f 100644
@@ -364,3 +364,39 @@ static int __init omap3xxx_prcm_init(void)
 	return ret;
 }
 subsys_initcall(omap3xxx_prcm_init);
+
+/* PRM ABB */
+
+/*
+ * struct omap36xx_abb - OMAP3 ABB register access description
+ * @tranxdone_status: ABB_xxx_DONE_ST bitmask in PRM_IRQSTATUS reg
+ */
+struct omap36xx_abb {
+	u32 tranxdone_status;
+};
+
+static struct omap36xx_abb omap36xx_abb[] = {
+	[OMAP3_VP_VDD_MPU_ID] = {
+		.tranxdone_status = OMAP3630_ABB_LDO_TRANXDONE_ST_MASK,
+	},
+};
+
+#define MAX_ABB_ID ARRAY_SIZE(omap36xx_abb);
+
+u32 omap3_prm_abb_check_txdone(u8 abb_id)
+{
+	struct omap36xx_abb *abb = &omap36xx_abb[abb_id];
+	u32 irqstatus;
+
+	irqstatus = omap2_prm_read_mod_reg(OCP_MOD,
+					   OMAP3_PRM_IRQSTATUS_MPU_OFFSET);
+	return irqstatus & abb->tranxdone_status;
+}
+
+void omap3_prm_abb_clear_txdone(u8 abb_id)
+{
+	struct omap36xx_abb *abb = &omap36xx_abb[abb_id];
+
+	omap2_prm_write_mod_reg(abb->tranxdone_status,
+				OCP_MOD, OMAP3_PRM_IRQSTATUS_MPU_OFFSET);
+}
arch/arm/mach-omap2/prm2xxx_3xxx.h +4 -0
index c9eea9a..c24c039 100644
@@ -249,6 +249,10 @@ extern int omap2_prm_deassert_hardreset(s16 prm_mod, u8 rst_shift, u8 st_shift);
 u32 omap3_prm_vp_check_txdone(u8 vp_id);
 void omap3_prm_vp_clear_txdone(u8 vp_id);
 
+/* OMAP36xx-specific ABB functions */
+u32 omap3_prm_abb_check_txdone(u8 vp_id);
+void omap3_prm_abb_clear_txdone(u8 vp_id);
+
 /*
  * OMAP3 access functions for voltage controller (VC) and
  * voltage proccessor (VP) in the PRM.
arch/arm/mach-omap2/prm44xx.c +44 -0

47 lines not on this page · raw message

arch/arm/mach-omap2/prm44xx.h +4 -0
index ee72ae6..6a0a00c 100644
@@ -755,6 +755,10 @@ extern u32 omap4_prm_rmw_inst_reg_bits(u32 mask, u32 bits, s16 inst, s16 idx);
 u32 omap4_prm_vp_check_txdone(u8 vp_id);
 void omap4_prm_vp_clear_txdone(u8 vp_id);
 
+/* OMAP4-specific ABB functions */
+u32 omap4_prm_abb_check_txdone(u8 abb_id);
+void omap4_prm_abb_clear_txdone(u8 abb_id);
+
 /*
  * OMAP4 access functions for voltage controller (VC) and
  * voltage proccessor (VP) in the PRM.
Signature · 1 line
1.7.9.5
#3 lore raw

PATCH 3/7 ARM: omap: Adaptive Body-Bias structures & data

In reply to Mike Turquette

Starting with OMAP36XX, some voltage domains have an ldo for biasing voltage to the transistors within that domain.

This ldo has three modes of operation. The first is Forward Body-Bias mode (FBB) which boosts performance of transistors at high OPPs by providng a positive voltage bias. This comes at a cost of power.

The second mode is Reverse Body-Bias or RBB. This mode provides a negative voltage bias which saves on static leakage at lower OPPs.

Finally ABB can also be bypassed (the default state) in which case it will just follow the voltage of the VP/VC.

This patch introduces the data structures needed to represent the ABB ldo's in the voltage layer, and populates the appropriate data for 3630 and OMAP4.

Not all voltage domains have an ABB ldo; on OMAP36XX the CORE voltage domain does not have an ABB ldo, and there are none on OMAP34xx. In such cases the voltage data will be marked with OMAP_ABB_NO_LDO.

---
 arch/arm/mach-omap2/Makefile       |    6 ++-
 arch/arm/mach-omap2/abb.h          |   85 ++++++++++++++++++++++++++++++++++++
 arch/arm/mach-omap2/abb36xx_data.c |   39 +++++++++++++++++
 arch/arm/mach-omap2/abb44xx_data.c |   45 +++++++++++++++++++
 4 files changed, 173 insertions(+), 2 deletions(-)
 create mode 100644 arch/arm/mach-omap2/abb.h
 create mode 100644 arch/arm/mach-omap2/abb36xx_data.c
 create mode 100644 arch/arm/mach-omap2/abb44xx_data.c
arch/arm/mach-omap2/Makefile +4 -2
index 34c2c7f..57e053e 100644
@@ -95,11 +95,13 @@ endif
 # PRCM
 omap-prcm-4-5-common			=  prcm.o cminst44xx.o cm44xx.o \
 					   prcm_mpu44xx.o prminst44xx.o \
-					   vc44xx_data.o vp44xx_data.o
+					   vc44xx_data.o vp44xx_data.o \
+					   abb44xx_data.o
 obj-y					+= prm_common.o
 obj-$(CONFIG_ARCH_OMAP2)		+= prcm.o cm2xxx_3xxx.o prm2xxx_3xxx.o
 obj-$(CONFIG_ARCH_OMAP3)		+= prcm.o cm2xxx_3xxx.o prm2xxx_3xxx.o
-obj-$(CONFIG_ARCH_OMAP3)		+= vc3xxx_data.o vp3xxx_data.o
+obj-$(CONFIG_ARCH_OMAP3)		+= vc3xxx_data.o vp3xxx_data.o \
+					   abb36xx_data.o
 obj-$(CONFIG_SOC_AM33XX)		+= prcm.o prm33xx.o cm33xx.o
 obj-$(CONFIG_ARCH_OMAP4)		+= $(omap-prcm-4-5-common) prm44xx.o
 obj-$(CONFIG_SOC_OMAP5)			+= $(omap-prcm-4-5-common)
arch/arm/mach-omap2/abb.h new file +85 -0

85 lines not on this page · raw message

arch/arm/mach-omap2/abb36xx_data.c new file +39 -0
new file mode 100644
index 0000000..21c9267
@@ -0,0 +1,39 @@
+/*
+ * OMAP36xx Adaptive Body-Bias (ABB) data
+ *
+ * Copyright (C) 2011 Texas Instruments, Inc.
+ * Mike Turquette <[email protected]>
+ *
+ * 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 "abb.h"
+#include "vp.h"
+#include "prm2xxx_3xxx.h"
+#include "prm-regbits-34xx.h"
+
+static const struct omap_abb_ops omap36xx_abb_ops = {
+	.check_tranxdone   = &omap3_prm_abb_check_txdone,
+	.clear_tranxdone   = &omap3_prm_abb_clear_txdone,
+};
+
+static const struct omap_abb_common omap36xx_abb_common = {
+	.opp_sel_mask		= OMAP3630_OPP_SEL_MASK,
+	.opp_change_mask	= OMAP3630_OPP_CHANGE_MASK,
+	.sr2en_mask		= OMAP3630_SR2EN_MASK,
+	.active_fbb_sel_mask	= OMAP3630_ACTIVE_FBB_SEL_MASK,
+	.sr2_wtcnt_value_mask	= OMAP3630_SR2_WTCNT_VALUE_MASK,
+	.settling_time		= 30,
+	.clock_cycles		= 8,
+	.ops			= &omap36xx_abb_ops,
+};
+
+/* SETUP & CTRL registers swapped names in OMAP4; thus 36xx looks strange */
+struct omap_abb_instance omap36xx_abb_mpu = {
+	.setup_offs		= OMAP3_PRM_LDO_ABB_CTRL_OFFSET,
+	.ctrl_offs		= OMAP3_PRM_LDO_ABB_SETUP_OFFSET,
+	.prm_irq_id		= OMAP3_VP_VDD_MPU_ID,
+	.common			= &omap36xx_abb_common,
+};
arch/arm/mach-omap2/abb44xx_data.c new file +45 -0

45 lines not on this page · raw message

Signature · 1 line
1.7.9.5
#4 lore raw

PATCH 4/7 ARM: omap: opp: add ABB data to voltage tables

In reply to Mike Turquette

The operating mode of the Adaptive Body-Bias ldo is a function of the voltage at which the VDD is operating and silicon characteristics.

NOMINAL_OPP causes the ABB ldo to be in bypass at that specific voltage. FAST_OPP causes the ldo to operate in Forward Body-Bias mode. SLOW_OPP puts the ldo in Reverse Body-Bias mode.

This patch models this relationship by adding an opp_sel paramter to struct omap_volt_data and populates this data in the 3630 and 4430 voltage tables.

Not all voltage domains have an ABB ldo and 3430 doesn't have one at all. In such cases voltages are marked with OMAP_ABB_NO_LDO.

---
 arch/arm/mach-omap2/omap_opp_data.h       |    5 ++--
 arch/arm/mach-omap2/opp3xxx_data.c        |   37 +++++++++++++++--------------
 arch/arm/mach-omap2/opp4xxx_data.c        |   25 +++++++++----------
 arch/arm/plat-omap/include/plat/voltage.h |    1 +
 4 files changed, 36 insertions(+), 32 deletions(-)
arch/arm/mach-omap2/omap_opp_data.h +3 -2
index c784c12..1facc52 100644
@@ -71,12 +71,13 @@ struct omap_opp_def {
  * Initialization wrapper used to define SmartReflex process data
  * XXX Is this needed?  Just use C99 initializers in data files?
  */
-#define VOLT_DATA_DEFINE(_v_nom, _efuse_offs, _errminlimit, _errgain)  \
+#define VOLT_DATA_DEFINE(_v_nom, _efuse_offs, _errminlimit, _errgain, _opp_sel) \
 {								       \
 	.volt_nominal	= _v_nom,				       \
 	.sr_efuse_offs	= _efuse_offs,				       \
 	.sr_errminlimit = _errminlimit,				       \
-	.vp_errgain	= _errgain				       \
+	.vp_errgain	= _errgain,				       \
+	.opp_sel	= _opp_sel,				       \
 }
 
 /* Use this to initialize the default table */
arch/arm/mach-omap2/opp3xxx_data.c +19 -18
index d95f3f9..12fc2da 100644
@@ -24,6 +24,7 @@
 #include "control.h"
 #include "omap_opp_data.h"
 #include "pm.h"
+#include "abb.h"
 
 /* 34xx */
 
@@ -36,12 +37,12 @@
 #define OMAP3430_VDD_MPU_OPP5_UV		1350000
 
 struct omap_volt_data omap34xx_vddmpu_volt_data[] = {
-	VOLT_DATA_DEFINE(OMAP3430_VDD_MPU_OPP1_UV, OMAP343X_CONTROL_FUSE_OPP1_VDD1, 0xf4, 0x0c),
-	VOLT_DATA_DEFINE(OMAP3430_VDD_MPU_OPP2_UV, OMAP343X_CONTROL_FUSE_OPP2_VDD1, 0xf4, 0x0c),
-	VOLT_DATA_DEFINE(OMAP3430_VDD_MPU_OPP3_UV, OMAP343X_CONTROL_FUSE_OPP3_VDD1, 0xf9, 0x18),
-	VOLT_DATA_DEFINE(OMAP3430_VDD_MPU_OPP4_UV, OMAP343X_CONTROL_FUSE_OPP4_VDD1, 0xf9, 0x18),
-	VOLT_DATA_DEFINE(OMAP3430_VDD_MPU_OPP5_UV, OMAP343X_CONTROL_FUSE_OPP5_VDD1, 0xf9, 0x18),
-	VOLT_DATA_DEFINE(0, 0, 0, 0),
+	VOLT_DATA_DEFINE(OMAP3430_VDD_MPU_OPP1_UV, OMAP343X_CONTROL_FUSE_OPP1_VDD1, 0xf4, 0x0c, OMAP_ABB_NO_LDO),
+	VOLT_DATA_DEFINE(OMAP3430_VDD_MPU_OPP2_UV, OMAP343X_CONTROL_FUSE_OPP2_VDD1, 0xf4, 0x0c, OMAP_ABB_NO_LDO),
+	VOLT_DATA_DEFINE(OMAP3430_VDD_MPU_OPP3_UV, OMAP343X_CONTROL_FUSE_OPP3_VDD1, 0xf9, 0x18, OMAP_ABB_NO_LDO),
+	VOLT_DATA_DEFINE(OMAP3430_VDD_MPU_OPP4_UV, OMAP343X_CONTROL_FUSE_OPP4_VDD1, 0xf9, 0x18, OMAP_ABB_NO_LDO),
+	VOLT_DATA_DEFINE(OMAP3430_VDD_MPU_OPP5_UV, OMAP343X_CONTROL_FUSE_OPP5_VDD1, 0xf9, 0x18, OMAP_ABB_NO_LDO),
+	VOLT_DATA_DEFINE(0, 0, 0, 0, 0),
 };
 
 /* VDD2 */
@@ -51,10 +52,10 @@ struct omap_volt_data omap34xx_vddmpu_volt_data[] = {
 #define OMAP3430_VDD_CORE_OPP3_UV		1150000
 
 struct omap_volt_data omap34xx_vddcore_volt_data[] = {
-	VOLT_DATA_DEFINE(OMAP3430_VDD_CORE_OPP1_UV, OMAP343X_CONTROL_FUSE_OPP1_VDD2, 0xf4, 0x0c),
-	VOLT_DATA_DEFINE(OMAP3430_VDD_CORE_OPP2_UV, OMAP343X_CONTROL_FUSE_OPP2_VDD2, 0xf4, 0x0c),
-	VOLT_DATA_DEFINE(OMAP3430_VDD_CORE_OPP3_UV, OMAP343X_CONTROL_FUSE_OPP3_VDD2, 0xf9, 0x18),
-	VOLT_DATA_DEFINE(0, 0, 0, 0),
+	VOLT_DATA_DEFINE(OMAP3430_VDD_CORE_OPP1_UV, OMAP343X_CONTROL_FUSE_OPP1_VDD2, 0xf4, 0x0c, OMAP_ABB_NO_LDO),
+	VOLT_DATA_DEFINE(OMAP3430_VDD_CORE_OPP2_UV, OMAP343X_CONTROL_FUSE_OPP2_VDD2, 0xf4, 0x0c, OMAP_ABB_NO_LDO),
+	VOLT_DATA_DEFINE(OMAP3430_VDD_CORE_OPP3_UV, OMAP343X_CONTROL_FUSE_OPP3_VDD2, 0xf9, 0x18, OMAP_ABB_NO_LDO),
+	VOLT_DATA_DEFINE(0, 0, 0, 0, 0),
 };
 
 /* 36xx */
@@ -67,11 +68,11 @@ struct omap_volt_data omap34xx_vddcore_volt_data[] = {
 #define OMAP3630_VDD_MPU_OPP1G_UV		1375000
 
 struct omap_volt_data omap36xx_vddmpu_volt_data[] = {
-	VOLT_DATA_DEFINE(OMAP3630_VDD_MPU_OPP50_UV, OMAP3630_CONTROL_FUSE_OPP50_VDD1, 0xf4, 0x0c),
-	VOLT_DATA_DEFINE(OMAP3630_VDD_MPU_OPP100_UV, OMAP3630_CONTROL_FUSE_OPP100_VDD1, 0xf9, 0x16),
-	VOLT_DATA_DEFINE(OMAP3630_VDD_MPU_OPP120_UV, OMAP3630_CONTROL_FUSE_OPP120_VDD1, 0xfa, 0x23),
-	VOLT_DATA_DEFINE(OMAP3630_VDD_MPU_OPP1G_UV, OMAP3630_CONTROL_FUSE_OPP1G_VDD1, 0xfa, 0x27),
-	VOLT_DATA_DEFINE(0, 0, 0, 0),
+	VOLT_DATA_DEFINE(OMAP3630_VDD_MPU_OPP50_UV, OMAP3630_CONTROL_FUSE_OPP50_VDD1, 0xf4, 0x0c, OMAP_ABB_NOMINAL_OPP),
+	VOLT_DATA_DEFINE(OMAP3630_VDD_MPU_OPP100_UV, OMAP3630_CONTROL_FUSE_OPP100_VDD1, 0xf9, 0x16, OMAP_ABB_NOMINAL_OPP),
+	VOLT_DATA_DEFINE(OMAP3630_VDD_MPU_OPP120_UV, OMAP3630_CONTROL_FUSE_OPP120_VDD1, 0xfa, 0x23, OMAP_ABB_NOMINAL_OPP),
+	VOLT_DATA_DEFINE(OMAP3630_VDD_MPU_OPP1G_UV, OMAP3630_CONTROL_FUSE_OPP1G_VDD1, 0xfa, 0x27, OMAP_ABB_FAST_OPP),
+	VOLT_DATA_DEFINE(0, 0, 0, 0, 0),
 };
 
 /* VDD2 */
@@ -80,9 +81,9 @@ struct omap_volt_data omap36xx_vddmpu_volt_data[] = {
 #define OMAP3630_VDD_CORE_OPP100_UV		1200000
 
 struct omap_volt_data omap36xx_vddcore_volt_data[] = {
-	VOLT_DATA_DEFINE(OMAP3630_VDD_CORE_OPP50_UV, OMAP3630_CONTROL_FUSE_OPP50_VDD2, 0xf4, 0x0c),
-	VOLT_DATA_DEFINE(OMAP3630_VDD_CORE_OPP100_UV, OMAP3630_CONTROL_FUSE_OPP100_VDD2, 0xf9, 0x16),
-	VOLT_DATA_DEFINE(0, 0, 0, 0),
+	VOLT_DATA_DEFINE(OMAP3630_VDD_CORE_OPP50_UV, OMAP3630_CONTROL_FUSE_OPP50_VDD2, 0xf4, 0x0c, OMAP_ABB_NO_LDO),
+	VOLT_DATA_DEFINE(OMAP3630_VDD_CORE_OPP100_UV, OMAP3630_CONTROL_FUSE_OPP100_VDD2, 0xf9, 0x16, OMAP_ABB_NO_LDO),
+	VOLT_DATA_DEFINE(0, 0, 0, 0, 0),
 };
 
 /* OPP data */
arch/arm/mach-omap2/opp4xxx_data.c +13 -12
index c95415d..c9b8e8a 100644
@@ -25,6 +25,7 @@
 #include "control.h"
 #include "omap_opp_data.h"
 #include "pm.h"
+#include "abb.h"
 
 /*
  * Structures containing OMAP4430 voltage supported and various
@@ -37,11 +38,11 @@
 #define OMAP4430_VDD_MPU_OPPNITRO_UV		1375000
 
 struct omap_volt_data omap44xx_vdd_mpu_volt_data[] = {
-	VOLT_DATA_DEFINE(OMAP4430_VDD_MPU_OPP50_UV, OMAP44XX_CONTROL_FUSE_MPU_OPP50, 0xf4, 0x0c),
-	VOLT_DATA_DEFINE(OMAP4430_VDD_MPU_OPP100_UV, OMAP44XX_CONTROL_FUSE_MPU_OPP100, 0xf9, 0x16),
-	VOLT_DATA_DEFINE(OMAP4430_VDD_MPU_OPPTURBO_UV, OMAP44XX_CONTROL_FUSE_MPU_OPPTURBO, 0xfa, 0x23),
-	VOLT_DATA_DEFINE(OMAP4430_VDD_MPU_OPPNITRO_UV, OMAP44XX_CONTROL_FUSE_MPU_OPPNITRO, 0xfa, 0x27),
-	VOLT_DATA_DEFINE(0, 0, 0, 0),
+	VOLT_DATA_DEFINE(OMAP4430_VDD_MPU_OPP50_UV, OMAP44XX_CONTROL_FUSE_MPU_OPP50, 0xf4, 0x0c, OMAP_ABB_NOMINAL_OPP),
+	VOLT_DATA_DEFINE(OMAP4430_VDD_MPU_OPP100_UV, OMAP44XX_CONTROL_FUSE_MPU_OPP100, 0xf9, 0x16, OMAP_ABB_NOMINAL_OPP),
+	VOLT_DATA_DEFINE(OMAP4430_VDD_MPU_OPPTURBO_UV, OMAP44XX_CONTROL_FUSE_MPU_OPPTURBO, 0xfa, 0x23, OMAP_ABB_NOMINAL_OPP),
+	VOLT_DATA_DEFINE(OMAP4430_VDD_MPU_OPPNITRO_UV, OMAP44XX_CONTROL_FUSE_MPU_OPPNITRO, 0xfa, 0x27, OMAP_ABB_FAST_OPP),
+	VOLT_DATA_DEFINE(0, 0, 0, 0, 0),
 };
 
 #define OMAP4430_VDD_IVA_OPP50_UV		1013000
@@ -49,19 +50,19 @@ struct omap_volt_data omap44xx_vdd_mpu_volt_data[] = {
 #define OMAP4430_VDD_IVA_OPPTURBO_UV		1300000
 
 struct omap_volt_data omap44xx_vdd_iva_volt_data[] = {
-	VOLT_DATA_DEFINE(OMAP4430_VDD_IVA_OPP50_UV, OMAP44XX_CONTROL_FUSE_IVA_OPP50, 0xf4, 0x0c),
-	VOLT_DATA_DEFINE(OMAP4430_VDD_IVA_OPP100_UV, OMAP44XX_CONTROL_FUSE_IVA_OPP100, 0xf9, 0x16),
-	VOLT_DATA_DEFINE(OMAP4430_VDD_IVA_OPPTURBO_UV, OMAP44XX_CONTROL_FUSE_IVA_OPPTURBO, 0xfa, 0x23),
-	VOLT_DATA_DEFINE(0, 0, 0, 0),
+	VOLT_DATA_DEFINE(OMAP4430_VDD_IVA_OPP50_UV, OMAP44XX_CONTROL_FUSE_IVA_OPP50, 0xf4, 0x0c, OMAP_ABB_NOMINAL_OPP),
+	VOLT_DATA_DEFINE(OMAP4430_VDD_IVA_OPP100_UV, OMAP44XX_CONTROL_FUSE_IVA_OPP100, 0xf9, 0x16, OMAP_ABB_NOMINAL_OPP),
+	VOLT_DATA_DEFINE(OMAP4430_VDD_IVA_OPPTURBO_UV, OMAP44XX_CONTROL_FUSE_IVA_OPPTURBO, 0xfa, 0x23, OMAP_ABB_NOMINAL_OPP),
+	VOLT_DATA_DEFINE(0, 0, 0, 0, 0),
 };
 
 #define OMAP4430_VDD_CORE_OPP50_UV		1025000
 #define OMAP4430_VDD_CORE_OPP100_UV		1200000
 
 struct omap_volt_data omap44xx_vdd_core_volt_data[] = {
-	VOLT_DATA_DEFINE(OMAP4430_VDD_CORE_OPP50_UV, OMAP44XX_CONTROL_FUSE_CORE_OPP50, 0xf4, 0x0c),
-	VOLT_DATA_DEFINE(OMAP4430_VDD_CORE_OPP100_UV, OMAP44XX_CONTROL_FUSE_CORE_OPP100, 0xf9, 0x16),
-	VOLT_DATA_DEFINE(0, 0, 0, 0),
+	VOLT_DATA_DEFINE(OMAP4430_VDD_CORE_OPP50_UV, OMAP44XX_CONTROL_FUSE_CORE_OPP50, 0xf4, 0x0c, OMAP_ABB_NO_LDO),
+	VOLT_DATA_DEFINE(OMAP4430_VDD_CORE_OPP100_UV, OMAP44XX_CONTROL_FUSE_CORE_OPP100, 0xf9, 0x16, OMAP_ABB_NO_LDO),
+	VOLT_DATA_DEFINE(0, 0, 0, 0, 0),
 };
 
 
arch/arm/plat-omap/include/plat/voltage.h +1 -0
index 5be4d5d..dd7b1f8 100644
@@ -28,6 +28,7 @@ struct omap_volt_data {
 	u32	sr_efuse_offs;
 	u8	sr_errminlimit;
 	u8	vp_errgain;
+	u8	opp_sel;
 };
 struct voltagedomain;
 
Signature · 1 line
1.7.9.5
#5 lore raw

PATCH 5/7 ARM: omap: voltage: per-voltage domain ABB data

In reply to Mike Turquette

This patch adds struct omap_abb_instance to struct voltagedomain and populates the data for those voltage domains that have an ABB ldo on both 36xx and 44xx silicon.

---
 arch/arm/mach-omap2/voltage.h                 |    1 +
 arch/arm/mach-omap2/voltagedomains3xxx_data.c |    2 ++
 arch/arm/mach-omap2/voltagedomains44xx_data.c |    3 +++
 3 files changed, 6 insertions(+)
arch/arm/mach-omap2/voltage.h +1 -0
index 0ded54f..546b3d7 100644
@@ -73,6 +73,7 @@ struct voltagedomain {
 	struct omap_vc_channel *vc;
 	const struct omap_vfsm_instance *vfsm;
 	struct omap_vp_instance *vp;
+	struct omap_abb_instance *abb;
 	struct omap_voltdm_pmic *pmic;
 
 	/* VC/VP register access functions: SoC specific */
arch/arm/mach-omap2/voltagedomains3xxx_data.c +2 -0
index d0103c8..f6c8a59 100644
@@ -26,6 +26,7 @@
 #include "voltage.h"
 #include "vc.h"
 #include "vp.h"
+#include "abb.h"
 
 /*
  * VDD data
@@ -112,6 +113,7 @@ void __init omap3xxx_voltagedomains_init(void)
 	if (cpu_is_omap3630()) {
 		omap3_voltdm_mpu.volt_data = omap36xx_vddmpu_volt_data;
 		omap3_voltdm_core.volt_data = omap36xx_vddcore_volt_data;
+		omap3_voltdm_mpu.abb = &omap36xx_abb_mpu;
 	} else {
 		omap3_voltdm_mpu.volt_data = omap34xx_vddmpu_volt_data;
 		omap3_voltdm_core.volt_data = omap34xx_vddcore_volt_data;
arch/arm/mach-omap2/voltagedomains44xx_data.c +3 -0
index c3115f6..da4c70b 100644
@@ -31,6 +31,7 @@
 #include "omap_opp_data.h"
 #include "vc.h"
 #include "vp.h"
+#include "abb.h"
 
 static const struct omap_vfsm_instance omap4_vdd_mpu_vfsm = {
 	.voltsetup_reg = OMAP4_PRM_VOLTSETUP_MPU_RET_SLEEP_OFFSET,
@@ -53,6 +54,7 @@ static struct voltagedomain omap4_voltdm_mpu = {
 	.vc = &omap4_vc_mpu,
 	.vfsm = &omap4_vdd_mpu_vfsm,
 	.vp = &omap4_vp_mpu,
+	.abb = &omap4_abb_mpu,
 };
 
 static struct voltagedomain omap4_voltdm_iva = {
@@ -64,6 +66,7 @@ static struct voltagedomain omap4_voltdm_iva = {
 	.vc = &omap4_vc_iva,
 	.vfsm = &omap4_vdd_iva_vfsm,
 	.vp = &omap4_vp_iva,
+	.abb = &omap4_abb_iva,
 };
 
 static struct voltagedomain omap4_voltdm_core = {
Signature · 1 line
1.7.9.5
#6 lore raw

PATCH 6/7 ARM: omap: abb: init & transition functions

In reply to Mike Turquette

The Adaptive Body-Bias ldo can be set to bypass, Forward Body-Bias or Reverse Body-Bias during a voltage transition. The ABB programming sequence depends on whether voltage is scaling up or down.

This patch implements the Adaptive Body-Bias ldo initialization routine and the transition sequence which is needed after any voltage scaling operation.

Note that this sequence will need to be revisited someday when the various SmartReflex AVS features, fixes and improvements are upstreamed and enabled for OMAP2+ kernels.

---
 arch/arm/mach-omap2/Makefile |    2 +-
 arch/arm/mach-omap2/abb.c    |  322 ++++++++++++++++++++++++++++++++++++++++++
 arch/arm/mach-omap2/abb.h    |    9 ++
 3 files changed, 332 insertions(+), 1 deletion(-)
 create mode 100644 arch/arm/mach-omap2/abb.c
arch/arm/mach-omap2/Makefile +1 -1
index 57e053e..a262aaa 100644
@@ -107,7 +107,7 @@ obj-$(CONFIG_ARCH_OMAP4)		+= $(omap-prcm-4-5-common) prm44xx.o
 obj-$(CONFIG_SOC_OMAP5)			+= $(omap-prcm-4-5-common)
 
 # OMAP voltage domains
-voltagedomain-common			:= voltage.o vc.o vp.o
+voltagedomain-common			:= voltage.o vc.o vp.o abb.o
 obj-$(CONFIG_ARCH_OMAP2)		+= $(voltagedomain-common)
 obj-$(CONFIG_ARCH_OMAP2)		+= voltagedomains2xxx_data.o
 obj-$(CONFIG_ARCH_OMAP3)		+= $(voltagedomain-common)
arch/arm/mach-omap2/abb.c new file +322 -0

322 lines not on this page · raw message

arch/arm/mach-omap2/abb.h +9 -0
index 2acc187..b18305f 100644
@@ -82,4 +82,13 @@ 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, u8 opp_sel);
+int omap_abb_pre_scale(struct voltagedomain *voltdm,
+		unsigned long target_volt);
+int omap_abb_post_scale(struct voltagedomain *voltdm,
+		unsigned long target_volt);
+
 #endif
Signature · 1 line
1.7.9.5
#7 lore raw

PATCH 6/7 ARM: omap: abb: init & transition functions

Quoted 324 lines · Mike Turquette

The Adaptive Body-Bias ldo can be set to bypass, Forward Body-Bias or Reverse Body-Bias during a voltage transition. The ABB programming sequence depends on whether voltage is scaling up or down.

This patch implements the Adaptive Body-Bias ldo initialization routine and the transition sequence which is needed after any voltage scaling operation.

Note that this sequence will need to be revisited someday when the various SmartReflex AVS features, fixes and improvements are upstreamed and enabled for OMAP2+ kernels.

---
 arch/arm/mach-omap2/Makefile |    2 +-
 arch/arm/mach-omap2/abb.c    |  322 ++++++++++++++++++++++++++++++++++++++++++
 arch/arm/mach-omap2/abb.h    |    9 ++
 3 files changed, 332 insertions(+), 1 deletion(-)
 create mode 100644 arch/arm/mach-omap2/abb.c
arch/arm/mach-omap2/Makefile +1 -1
index 57e053e..a262aaa 100644
@@ -107,7 +107,7 @@ obj-$(CONFIG_ARCH_OMAP4)            += $(omap-prcm-4-5-common) prm44xx.o
 obj-$(CONFIG_SOC_OMAP5)                        += $(omap-prcm-4-5-common)
 
 # OMAP voltage domains
-voltagedomain-common                   := voltage.o vc.o vp.o
+voltagedomain-common                   := voltage.o vc.o vp.o abb.o
 obj-$(CONFIG_ARCH_OMAP2)               += $(voltagedomain-common)
 obj-$(CONFIG_ARCH_OMAP2)               += voltagedomains2xxx_data.o
 obj-$(CONFIG_ARCH_OMAP3)               += $(voltagedomain-common)
arch/arm/mach-omap2/abb.c new file +284 -0
new file mode 100644
index 0000000..e8a3ae0
@@ -0,0 +1,322 @@
+/*
+ * OMAP Adaptive Body-Bias core
+ *
+ * Copyright (C) 2011 Texas Instruments, Inc.
+ * Mike Turquette <[email protected]>
+ *
+ * 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 - voltage domain that just finished scaling voltage
+ * @opp_sel - target ABB ldo operating mode
+ *
+ * Program the ABB ldo to the new state (if necessary), clearing the
+ * PRM_IRQSTATUS bit before and after the transition.  Returns 0 on
+ * success, -ETIMEDOUT otherwise.
+ */
+int omap_abb_set_opp(struct voltagedomain *voltdm, u8 opp_sel)
+{
+       struct omap_abb_instance *abb = voltdm->abb;
+       int ret, timeout;
+
+       /* 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_warn("%s: vdd_%s ABB TRANXDONE timeout\n",
+                               __func__, voltdm->name);
+               return -ETIMEDOUT;
+       }
+
+       /* program the setup register */
+       switch (opp_sel) {
+       case OMAP_ABB_NOMINAL_OPP:
+               voltdm->rmw(abb->common->active_fbb_sel_mask,
+                               0x0,
+                               abb->setup_offs);
+               break;
+       case OMAP_ABB_FAST_OPP:
+               voltdm->rmw(abb->common->active_fbb_sel_mask,
+                               abb->common->active_fbb_sel_mask,
+                               abb->setup_offs);
+               break;
+       }
+
+       /* 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_warn("%s: vdd_%s ABB TRANXDONE timeout\n",
+                               __func__, voltdm->name);
+               return -ETIMEDOUT;
+       }
+
+       /* track internal state */
+       abb->_opp_sel = opp_sel;
+
+       return 0;
+}
+
+/**
+ * omap_abb_pre_scale - ABB transition pre-voltage scale, if needed
+ *
+ * @voltdm - voltage domain that is about to scale
+ * @target_volt - voltage that voltdm is scaling towards
+ *
+ * Changes the ABB ldo mode prior to scaling the voltage domain.
+ * Returns 0 on success, otherwise an error code.
+ */
+int omap_abb_pre_scale(struct voltagedomain *voltdm,
+               unsigned long target_volt)
+{
+       struct omap_abb_instance *abb = voltdm->abb;
+       struct omap_volt_data *cur_volt_data;
+       struct omap_volt_data *target_volt_data;
+       u8 opp_sel;
+
+       /* sanity */
+       if (!voltdm)
+               return -EINVAL;
+
+       if (!abb)
+               return 0;
+
+       /*
+        * XXX boot-time corner case: voltdm->nominal volt might be zero
+        *
+        * This implies that we're running at the default PMIC voltage,
+        * since voltdm->nominal_volt should have been populated in
+        * omap_voltage_late_init if the voltage had been scaled
+        * previously.  The best way to fix this is for DT data to pass
+        * in PMIC boot voltage.
+        *
+        * For now, handle this by returning success (0) to not block
+        * the rest of the transition.
+        */
+       if (!voltdm->nominal_volt)
+               return 0;
+
+       cur_volt_data = omap_voltage_get_voltdata(voltdm, voltdm->nominal_volt);
+       target_volt_data = omap_voltage_get_voltdata(voltdm, target_volt);
+
+       if (IS_ERR(cur_volt_data))
+               return PTR_ERR(cur_volt_data);
+
+       if (IS_ERR(target_volt_data))
+               return PTR_ERR(target_volt_data);
+
+       /* bail if the sequence is wrong */
+       if (target_volt_data->volt_nominal > cur_volt_data->volt_nominal)
+               return 0;
+
+       opp_sel = target_volt_data->opp_sel;
+
+       /* bail early if no transition is necessary */
+       if (opp_sel == abb->_opp_sel)
+               return 0;
+
+       return omap_abb_set_opp(voltdm, opp_sel);
+}
+
+/**
+ * omap_abb_post_scale - ABB transition post-voltage scale, if needed
+ * @voltdm - voltage domain that just finished scaling
+ * @target_volt - voltage that voltdm is scaling towards
+ *
+ * Changes the ABB ldo mode prior to scaling the voltage domain.
+ * Returns 0 on success, otherwise an error code.
+ */
+int omap_abb_post_scale(struct voltagedomain *voltdm,
+               unsigned long target_volt)
+{
+       struct omap_abb_instance *abb = voltdm->abb;
+       struct omap_volt_data *cur_volt_data;
+       struct omap_volt_data *target_volt_data;
+       u8 opp_sel;
+
+       /* sanity */
+       if (!voltdm)
+               return -EINVAL;
+
+       if (!abb)
+               return 0;
+
+       cur_volt_data = omap_voltage_get_voltdata(voltdm, voltdm->nominal_volt);
+       if (IS_ERR(cur_volt_data))
+               return PTR_ERR(cur_volt_data);
+
+       target_volt_data = omap_voltage_get_voltdata(voltdm, target_volt);
+       if (IS_ERR(target_volt_data))
+               return PTR_ERR(target_volt_data);
+
+       /* bail if the sequence is wrong */
+       if (target_volt_data->volt_nominal < cur_volt_data->volt_nominal)
+               return 0;
+
+       opp_sel = target_volt_data->opp_sel;
+
+       /* bail early if no transition is necessary */
+       if (opp_sel == abb->_opp_sel)
+               return 0;
+
+       return omap_abb_set_opp(voltdm, opp_sel);
+}
+
+/*
+ * 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)
+        *

arch/arm/mach-omap2/abb.c line 294

Quoted 10 lines
arch/arm/mach-omap2/abb.c new file +10 -0
+        * 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);

There is a possible small rounding error here. Depending on SYS_CLK_rate value, you might loose significant digits when converting from Hz to MHz.

Also, wouldn't it be safer to do all multiplications first and then divisions, like:
SR2_WTCNT_VALUE = ((settling time * SYS_CLK_rate_kHz) / # SYS_CLK cycles ) / 1000

Quoted 53 lines
arch/arm/mach-omap2/abb.c new file +28 -0
+       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);
+
+       /* 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;
+}
arch/arm/mach-omap2/abb.h +9 -1
index 2acc187..b18305f 100644
@@ -82,4 +82,13 @@ 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, u8 opp_sel);
+int omap_abb_pre_scale(struct voltagedomain *voltdm,
+               unsigned long target_volt);
+int omap_abb_post_scale(struct voltagedomain *voltdm,
+               unsigned long target_volt);
+
 #endif
--

1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majordomo at vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html

#8 lore raw

PATCH 7/7 ARM: omap: voltage: add ABB to voltage scaling

In reply to Mike Turquette

Adaptive Body-Bias ldo state should be transitioned (if necessary) during any voltage scaling operation.

This patch initializes ABB LDO's as a part of the greater voltage domain initialization sequence and adds the ABB transition callbacks to the primary voltage domain scaling function, voltdm_scale().

---
 arch/arm/mach-omap2/voltage.c |   28 ++++++++++++++++++++++++++--
 1 file changed, 26 insertions(+), 2 deletions(-)
arch/arm/mach-omap2/voltage.c +26 -2
index f45716c..9cac9fe 100644
@@ -41,6 +41,7 @@
 
 #include "vc.h"
 #include "vp.h"
+#include "abb.h"
 
 static LIST_HEAD(voltdm_list);
 
@@ -101,10 +102,30 @@ int voltdm_scale(struct voltagedomain *voltdm,
 		return -EINVAL;
 	}
 
+	ret = omap_abb_pre_scale(voltdm, volt);
+	if (ret) {
+		pr_err("%s: abb prescale failed for vdd%s: %d\n",
+				__func__, voltdm->name, ret);
+		goto out;
+	}
+
 	ret = voltdm->scale(voltdm, volt);
-	if (!ret)
-		voltdm->nominal_volt = volt;
+	if (ret) {
+		pr_err("%s: vdd_%s failed to scale: %d\n",
+				__func__, voltdm->name, ret);
+		goto out;
+	}
+
+	voltdm->nominal_volt = volt;
 
+	ret = omap_abb_post_scale(voltdm, volt);
+	if (ret) {
+		pr_err("%s: abb postscale failed for vdd%s: %d\n",
+				__func__, voltdm->name, ret);
+		goto out;
+	}
+
+out:
 	return ret;
 }
 
@@ -300,6 +321,9 @@ int __init omap_voltage_late_init(void)
 			omap_vp_init(voltdm);
 		}
 
+		if (voltdm->abb)
+			omap_abb_init(voltdm);
+
 		/*
 		 * XXX If voltdm->nominal_volt is zero after calling
 		 * voltdm->get_voltage then we are likely running this
Signature · 1 line
1.7.9.5
#9 lore raw

cover Adaptive Body-Bias for OMAP

In reply to Mike Turquette
Quoted 1 line · Mike Turquette

From: Mike Turquette <[email protected]>

[...]

Quoted 4 lines
 arch/arm/mach-omap2/Makefile                  |    8 +-
 arch/arm/mach-omap2/abb.c                     |  322 +++++++++++++++++++++++++
 arch/arm/mach-omap2/abb.h                     |   94 ++++++++

[...]

Quoted 6 lines
 arch/arm/plat-omap/include/plat/voltage.h     |    1 +
 18 files changed, 699 insertions(+), 37 deletions(-)
 create mode 100644 arch/arm/mach-omap2/abb.c
 create mode 100644 arch/arm/mach-omap2/abb.h
 create mode 100644 arch/arm/mach-omap2/abb36xx_data.c
 create mode 100644 arch/arm/mach-omap2/abb44xx_data.c

dumb question: with the request to move everything out of mach-omap2 directory, do we still want to add more files into mach-omap2?

Regards,
NM

#10 lore raw

cover Adaptive Body-Bias for OMAP

Quoting Nishanth Menon (2012-10-11 06:33:04)

Quoted 15 lines · Mike Turquette
Quoted 1 line

From: Mike Turquette <[email protected]>

[...]

Quoted 4 lines
 arch/arm/mach-omap2/Makefile                  |    8 +-
 arch/arm/mach-omap2/abb.c                     |  322 +++++++++++++++++++++++++
 arch/arm/mach-omap2/abb.h                     |   94 ++++++++

[...]

Quoted 6 lines
 arch/arm/plat-omap/include/plat/voltage.h     |    1 +
 18 files changed, 699 insertions(+), 37 deletions(-)
 create mode 100644 arch/arm/mach-omap2/abb.c
 create mode 100644 arch/arm/mach-omap2/abb.h
 create mode 100644 arch/arm/mach-omap2/abb36xx_data.c
 create mode 100644 arch/arm/mach-omap2/abb44xx_data.c
Quoted 3 lines

dumb question: with the request to move everything out of mach-omap2 directory, do we still want to add more files into mach-omap2?

Not a dumb question at all. I approached this problem by modeling it after existing voltage layer code (in particular the vp and vc drivers).

My hope is to get it merged as-is and then bundle the abb code up with the vp/vc migration to drivers/* when that happens some day. People using omap36xx and above need this code now, so it seems prudent to take this approach today.

Regards,
Mike

Quoted 2 lines

Regards,
NM

maintainer
#11 lore raw

cover Adaptive Body-Bias for OMAP

Quoted 20 lines · Mike Turquette

Quoting Nishanth Menon (2012-10-11 06:33:04)

Quoted 15 lines · Mike Turquette
Quoted 1 line

From: Mike Turquette <[email protected]>

[...]

Quoted 4 lines
 arch/arm/mach-omap2/Makefile                  |    8 +-
 arch/arm/mach-omap2/abb.c                     |  322 +++++++++++++++++++++++++
 arch/arm/mach-omap2/abb.h                     |   94 ++++++++

[...]

Quoted 6 lines
 arch/arm/plat-omap/include/plat/voltage.h     |    1 +
 18 files changed, 699 insertions(+), 37 deletions(-)
 create mode 100644 arch/arm/mach-omap2/abb.c
 create mode 100644 arch/arm/mach-omap2/abb.h
 create mode 100644 arch/arm/mach-omap2/abb36xx_data.c
 create mode 100644 arch/arm/mach-omap2/abb44xx_data.c
Quoted 3 lines

dumb question: with the request to move everything out of mach-omap2 directory, do we still want to add more files into mach-omap2?

Quoted 7 lines

Not a dumb question at all. I approached this problem by modeling it after existing voltage layer code (in particular the vp and vc drivers).

My hope is to get it merged as-is and then bundle the abb code up with the vp/vc migration to drivers/* when that happens some day. People using omap36xx and above need this code now, so it seems prudent to take this approach today.

This is needed, but makes moving the vc code to drivers a bit more complex.

So we also need a plan to move this all to drivers in the follow up patches. And we need a maintainer for the code. Who is going to be doing all that?

Regards,

Tony

#12 lore raw

cover Adaptive Body-Bias for OMAP

Quoting Tony Lindgren (2012-10-16 09:32:25)

Quoted 29 lines · Mike Turquette
Quoted 20 lines

Quoting Nishanth Menon (2012-10-11 06:33:04)

Quoted 15 lines · Mike Turquette
Quoted 1 line

From: Mike Turquette <[email protected]>

[...]

Quoted 4 lines
 arch/arm/mach-omap2/Makefile                  |    8 +-
 arch/arm/mach-omap2/abb.c                     |  322 +++++++++++++++++++++++++
 arch/arm/mach-omap2/abb.h                     |   94 ++++++++

[...]

Quoted 6 lines
 arch/arm/plat-omap/include/plat/voltage.h     |    1 +
 18 files changed, 699 insertions(+), 37 deletions(-)
 create mode 100644 arch/arm/mach-omap2/abb.c
 create mode 100644 arch/arm/mach-omap2/abb.h
 create mode 100644 arch/arm/mach-omap2/abb36xx_data.c
 create mode 100644 arch/arm/mach-omap2/abb44xx_data.c
Quoted 3 lines

dumb question: with the request to move everything out of mach-omap2 directory, do we still want to add more files into mach-omap2?

Quoted 7 lines

Not a dumb question at all. I approached this problem by modeling it after existing voltage layer code (in particular the vp and vc drivers).

My hope is to get it merged as-is and then bundle the abb code up with the vp/vc migration to drivers/* when that happens some day. People using omap36xx and above need this code now, so it seems prudent to take this approach today.

Quoted 7 lines

This is needed, but makes moving the vc code to drivers a bit more complex.

So we also need a plan to move this all to drivers in the follow up patches. And we need a maintainer for the code. Who is going to be doing all that?

Is there already somebody committed to moving vp/vc code out to drivers? If so then I can take responsibility for moving the abb code and coordinate with that person. If nobody has put the vp/vc migration onto their todo list then that is a bigger question.

Regards,
Mike

Quoted 3 lines

Regards,

Tony

#13 lore raw

cover Adaptive Body-Bias for OMAP

Quoted 33 lines · Mike Turquette

Quoting Tony Lindgren (2012-10-16 09:32:25)

Quoted 32 lines · Mike Turquette
Quoted 20 lines

Quoting Nishanth Menon (2012-10-11 06:33:04)

Quoted 15 lines · Mike Turquette
Quoted 1 line

From: Mike Turquette <[email protected]>

[...]

Quoted 4 lines
 arch/arm/mach-omap2/Makefile                  |    8 +-
 arch/arm/mach-omap2/abb.c                     |  322 +++++++++++++++++++++++++
 arch/arm/mach-omap2/abb.h                     |   94 ++++++++

[...]

Quoted 6 lines
 arch/arm/plat-omap/include/plat/voltage.h     |    1 +
 18 files changed, 699 insertions(+), 37 deletions(-)
 create mode 100644 arch/arm/mach-omap2/abb.c
 create mode 100644 arch/arm/mach-omap2/abb.h
 create mode 100644 arch/arm/mach-omap2/abb36xx_data.c
 create mode 100644 arch/arm/mach-omap2/abb44xx_data.c
Quoted 3 lines

dumb question: with the request to move everything out of mach-omap2 directory, do we still want to add more files into mach-omap2?

Quoted 7 lines

Not a dumb question at all. I approached this problem by modeling it after existing voltage layer code (in particular the vp and vc drivers).

My hope is to get it merged as-is and then bundle the abb code up with the vp/vc migration to drivers/* when that happens some day. People using omap36xx and above need this code now, so it seems prudent to take this approach today.

This is needed, but makes moving the vc code to drivers a bit more complex.

Quoted 6 lines
Quoted 4 lines

So we also need a plan to move this all to drivers in the follow up patches. And we need a maintainer for the code. Who is going to be doing all that?

Is there already somebody committed to moving vp/vc code out to drivers?

Yes, VC/VP is part of the bigger PRM/CM move in progress.

For now, I'm ok with adding a little more VC/VP stuff since it's already well isolated in the prmXXXX.c files (though it might need a rebase on Paul's recent PRM/CM cleanup stuff.)

Quoted 2 lines

If so then I can take responsibility for moving the abb code and coordinate with that person.

Thanks,

Kevin

maintainer
#14 lore raw

cover Adaptive Body-Bias for OMAP

Quoted 40 lines · Kevin Hilman
Quoted 38 lines · Mike Turquette

Quoting Tony Lindgren (2012-10-16 09:32:25)

Quoted 36 lines · Mike Turquette
Quoted 20 lines

Quoting Nishanth Menon (2012-10-11 06:33:04)

Quoted 15 lines · Mike Turquette
Quoted 1 line

From: Mike Turquette <[email protected]>

[...]

Quoted 4 lines
 arch/arm/mach-omap2/Makefile                  |    8 +-
 arch/arm/mach-omap2/abb.c                     |  322 +++++++++++++++++++++++++
 arch/arm/mach-omap2/abb.h                     |   94 ++++++++

[...]

Quoted 6 lines
 arch/arm/plat-omap/include/plat/voltage.h     |    1 +
 18 files changed, 699 insertions(+), 37 deletions(-)
 create mode 100644 arch/arm/mach-omap2/abb.c
 create mode 100644 arch/arm/mach-omap2/abb.h
 create mode 100644 arch/arm/mach-omap2/abb36xx_data.c
 create mode 100644 arch/arm/mach-omap2/abb44xx_data.c
Quoted 3 lines

dumb question: with the request to move everything out of mach-omap2 directory, do we still want to add more files into mach-omap2?

Quoted 7 lines

Not a dumb question at all. I approached this problem by modeling it after existing voltage layer code (in particular the vp and vc drivers).

My hope is to get it merged as-is and then bundle the abb code up with the vp/vc migration to drivers/* when that happens some day. People using omap36xx and above need this code now, so it seems prudent to take this approach today.

This is needed, but makes moving the vc code to drivers a bit more complex.

So we also need a plan to move this all to drivers in the follow up patches. And we need a maintainer for the code. Who is going to be doing all that?

Quoted 10 lines
Quoted 1 line

Is there already somebody committed to moving vp/vc code out to drivers?

Yes, VC/VP is part of the bigger PRM/CM move in progress.

For now, I'm ok with adding a little more VC/VP stuff since it's already well isolated in the prmXXXX.c files (though it might need a rebase on Paul's recent PRM/CM cleanup stuff.)

Quoted 2 lines

If so then I can take responsibility for moving the abb code and coordinate with that person.

Thanks Mike & Kevin, sounds good to me.

Regards,

Tony