mirror of
https://git.yoctoproject.org/meta-ti
synced 2026-07-27 14:28:05 +00:00
linux 3.0: updates
* Bump SRCREV to latest 3.0rc from Linux * Merge in pm-voltdm patches * Merge in ABB support * Merge in expansion-board support (unfished) * Add hack for switch to GPTIMER1 * Set default cpufreq governor to performance Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
This commit is contained in:
+274
@@ -0,0 +1,274 @@
|
||||
From d9dd20e6220aa04f17ec44f64a0b1545407ae8f9 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
|
||||
|
||||
Reference in New Issue
Block a user