* [PATCH v2 13/18] omap3+: sr: introduce notifiers flags
From: Nishanth Menon @ 2011-03-02 10:55 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1299063331-27968-1-git-send-email-nm@ti.com>
SmartReflex IP v1 and v2 have different registers and offsets.
Currently, we pass the status as is to the class driver. However,
since we dont pass the version of the underlying SR hardware
to the Class driver, it will not be unable to make consistent
sense of the status bits coming over to it.
A class driver should be able to function without dependency
on the exact IP version it is actually running on. We hence
introduce our own translation in s/w level for a generic
notification flag.
As part of this change, we will now call the notifier iff we get
a match with the notifier flags that the class driver requested.
Signed-off-by: Nishanth Menon <nm@ti.com>
---
arch/arm/mach-omap2/smartreflex.c | 73 ++++++++++++++++++++++++-
arch/arm/plat-omap/include/plat/smartreflex.h | 6 ++
2 files changed, 76 insertions(+), 3 deletions(-)
diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c
index 4fc679e..2657ba1 100644
--- a/arch/arm/mach-omap2/smartreflex.c
+++ b/arch/arm/mach-omap2/smartreflex.c
@@ -123,27 +123,94 @@ static struct omap_sr *_sr_lookup(struct voltagedomain *voltdm)
return ERR_PTR(-ENODATA);
}
+static inline u32 notifier_to_irqen_v1(u8 notify_flags)
+{
+ u32 val;
+ val = (notify_flags & SR_NOTIFY_MCUACCUM) ?
+ ERRCONFIG_MCUACCUMINTEN : 0;
+ val |= (notify_flags & SR_NOTIFY_MCUVALID) ?
+ ERRCONFIG_MCUVALIDINTEN : 0;
+ val |= (notify_flags & SR_NOTIFY_MCUBOUND) ?
+ ERRCONFIG_MCUBOUNDINTEN : 0;
+ val |= (notify_flags & SR_NOTIFY_MCUDISACK) ?
+ ERRCONFIG_MCUDISACKINTEN : 0;
+ return val;
+}
+
+static inline u32 notifier_to_irqen_v2(u8 notify_flags)
+{
+ u32 val;
+ val = (notify_flags & SR_NOTIFY_MCUACCUM) ?
+ IRQENABLE_MCUACCUMINT : 0;
+ val |= (notify_flags & SR_NOTIFY_MCUVALID) ?
+ IRQENABLE_MCUVALIDINT : 0;
+ val |= (notify_flags & SR_NOTIFY_MCUBOUND) ?
+ IRQENABLE_MCUBOUNDSINT : 0;
+ val |= (notify_flags & SR_NOTIFY_MCUDISACK) ?
+ IRQENABLE_MCUDISABLEACKINT : 0;
+ return val;
+}
+
+static inline u8 irqstat_to_notifier_v1(u32 status)
+{
+ u8 val;
+ val = (status & ERRCONFIG_MCUACCUMINTST) ?
+ SR_NOTIFY_MCUACCUM : 0;
+ val |= (status & ERRCONFIG_MCUVALIDINTEN) ?
+ SR_NOTIFY_MCUVALID : 0;
+ val |= (status & ERRCONFIG_MCUBOUNDINTEN) ?
+ SR_NOTIFY_MCUBOUND : 0;
+ val |= (status & ERRCONFIG_MCUDISACKINTEN) ?
+ SR_NOTIFY_MCUDISACK : 0;
+ return val;
+}
+
+static inline u8 irqstat_to_notifier_v2(u32 status)
+{
+ u8 val;
+ val = (status & IRQENABLE_MCUACCUMINT) ?
+ SR_NOTIFY_MCUACCUM : 0;
+ val |= (status & IRQENABLE_MCUVALIDINT) ?
+ SR_NOTIFY_MCUVALID : 0;
+ val |= (status & IRQENABLE_MCUBOUNDSINT) ?
+ SR_NOTIFY_MCUBOUND : 0;
+ val |= (status & IRQENABLE_MCUDISABLEACKINT) ?
+ SR_NOTIFY_MCUDISACK : 0;
+ return val;
+}
+
+
static irqreturn_t sr_interrupt(int irq, void *data)
{
struct omap_sr *sr_info = (struct omap_sr *)data;
u32 status = 0;
+ u32 value = 0;
if (sr_info->ip_type == SR_TYPE_V1) {
+ /* Status bits are one bit before enable bits in v1 */
+ value = notifier_to_irqen_v1(sr_class->notify_flags) >> 1;
+
/* Read the status bits */
status = sr_read_reg(sr_info, ERRCONFIG_V1);
+ status &= value;
/* Clear them by writing back */
- sr_write_reg(sr_info, ERRCONFIG_V1, status);
+ sr_modify_reg(sr_info, ERRCONFIG_V1, value, status);
+
+ value = irqstat_to_notifier_v1(status);
} else if (sr_info->ip_type == SR_TYPE_V2) {
+ value = notifier_to_irqen_v2(sr_class->notify_flags);
/* Read the status bits */
- sr_read_reg(sr_info, IRQSTATUS);
+ status = sr_read_reg(sr_info, IRQSTATUS);
+ status &= value;
/* Clear them by writing back */
sr_write_reg(sr_info, IRQSTATUS, status);
+ value = irqstat_to_notifier_v2(status);
}
if (sr_class->notify)
- sr_class->notify(sr_info->voltdm, status);
+ sr_class->notify(sr_info->voltdm, value);
return IRQ_HANDLED;
}
diff --git a/arch/arm/plat-omap/include/plat/smartreflex.h b/arch/arm/plat-omap/include/plat/smartreflex.h
index 8b6ecd9..ff07d1e 100644
--- a/arch/arm/plat-omap/include/plat/smartreflex.h
+++ b/arch/arm/plat-omap/include/plat/smartreflex.h
@@ -141,6 +141,12 @@
#define OMAP3430_SR_ERRWEIGHT 0x04
#define OMAP3430_SR_ERRMAXLIMIT 0x02
+/* Smart reflex notifiers for class drivers to use */
+#define SR_NOTIFY_MCUACCUM (0x1 << 0)
+#define SR_NOTIFY_MCUVALID (0x1 << 1)
+#define SR_NOTIFY_MCUBOUND (0x1 << 2)
+#define SR_NOTIFY_MCUDISACK (0x1 << 3)
+
/**
* struct omap_sr_pmic_data - Strucutre to be populated by pmic code to pass
* pmic specific info to smartreflex driver
--
1.7.1
^ permalink raw reply related
* [PATCH v2 12/18] omap3+: sr: enable/disable SR only on need
From: Nishanth Menon @ 2011-03-02 10:55 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1299063331-27968-1-git-send-email-nm@ti.com>
Since we already know the state of the autocomp enablement, we can
see if the requested state is different from the current state and
enable/disable SR only on the need basis.
Signed-off-by: Nishanth Menon <nm@ti.com>
---
arch/arm/mach-omap2/smartreflex.c | 11 +++++++----
1 files changed, 7 insertions(+), 4 deletions(-)
diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c
index 8cad92d..4fc679e 100644
--- a/arch/arm/mach-omap2/smartreflex.c
+++ b/arch/arm/mach-omap2/smartreflex.c
@@ -819,10 +819,13 @@ static int omap_sr_autocomp_store(void *data, u64 val)
return -EINVAL;
}
- if (!val)
- sr_stop_vddautocomp(sr_info);
- else
- sr_start_vddautocomp(sr_info);
+ /* control enable/disable only if there is a delta in value */
+ if (sr_info->autocomp_active ^ val) {
+ if (!val)
+ sr_stop_vddautocomp(sr_info);
+ else
+ sr_start_vddautocomp(sr_info);
+ }
return 0;
}
--
1.7.1
^ permalink raw reply related
* [PATCH v2 11/18] omap3+: sr: disable interrupt by default
From: Nishanth Menon @ 2011-03-02 10:55 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1299063331-27968-1-git-send-email-nm@ti.com>
We will enable and disable interrupt on a need basis in the class
driver. we need to keep the irq disabled by default else the
forceupdate or vcbypass events could trigger events that we dont
need/expect to handle.
Signed-off-by: Nishanth Menon <nm@ti.com>
---
arch/arm/mach-omap2/smartreflex.c | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c
index a4e9f2d..8cad92d 100644
--- a/arch/arm/mach-omap2/smartreflex.c
+++ b/arch/arm/mach-omap2/smartreflex.c
@@ -281,6 +281,7 @@ static int sr_late_init(struct omap_sr *sr_info)
IRQF_DISABLED, name, (void *)sr_info);
if (ret)
goto error;
+ disable_irq(sr_info->irq);
}
if (pdata && pdata->enable_on_init)
--
1.7.1
^ permalink raw reply related
* [PATCH v2 10/18] omap3+: sr: call handler with interrupt disabled
From: Nishanth Menon @ 2011-03-02 10:55 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1299063331-27968-1-git-send-email-nm@ti.com>
Request the handler irq such that there is no nesting for calls.
the notifiers are not expected to be nested, further the interrupt
events for status change should be handled prior to the next event
else there is a risk of loosing events.
Signed-off-by: Nishanth Menon <nm@ti.com>
---
arch/arm/mach-omap2/smartreflex.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c
index 99e4c4f..a4e9f2d 100644
--- a/arch/arm/mach-omap2/smartreflex.c
+++ b/arch/arm/mach-omap2/smartreflex.c
@@ -278,7 +278,7 @@ static int sr_late_init(struct omap_sr *sr_info)
goto error;
}
ret = request_irq(sr_info->irq, sr_interrupt,
- 0, name, (void *)sr_info);
+ IRQF_DISABLED, name, (void *)sr_info);
if (ret)
goto error;
}
--
1.7.1
^ permalink raw reply related
* [PATCH v2 09/18] omap3+: sr: fix cosmetic indentation
From: Nishanth Menon @ 2011-03-02 10:55 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1299063331-27968-1-git-send-email-nm@ti.com>
Error label case seems to have a 2 tab indentation when just 1 is
necessary.
Signed-off-by: Nishanth Menon <nm@ti.com>
---
arch/arm/mach-omap2/smartreflex.c | 18 +++++++++---------
1 files changed, 9 insertions(+), 9 deletions(-)
diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c
index 35658a2..99e4c4f 100644
--- a/arch/arm/mach-omap2/smartreflex.c
+++ b/arch/arm/mach-omap2/smartreflex.c
@@ -289,15 +289,15 @@ static int sr_late_init(struct omap_sr *sr_info)
return ret;
error:
- iounmap(sr_info->base);
- mem = platform_get_resource(sr_info->pdev, IORESOURCE_MEM, 0);
- release_mem_region(mem->start, resource_size(mem));
- list_del(&sr_info->node);
- dev_err(&sr_info->pdev->dev, "%s: ERROR in registering"
- "interrupt handler. Smartreflex will"
- "not function as desired\n", __func__);
- kfree(sr_info);
- return ret;
+ iounmap(sr_info->base);
+ mem = platform_get_resource(sr_info->pdev, IORESOURCE_MEM, 0);
+ release_mem_region(mem->start, resource_size(mem));
+ list_del(&sr_info->node);
+ dev_err(&sr_info->pdev->dev, "%s: ERROR in registering"
+ "interrupt handler. Smartreflex will"
+ "not function as desired\n", __func__);
+ kfree(sr_info);
+ return ret;
}
static void sr_v1_disable(struct omap_sr *sr)
--
1.7.1
^ permalink raw reply related
* [PATCH v2 08/18] omap3+: sr: introduce class init, deinit and priv data
From: Nishanth Menon @ 2011-03-02 10:55 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1299063331-27968-1-git-send-email-nm@ti.com>
Certain class drivers such as class 1.5 drivers, will need specific
notification that they have to be started up or stopped independent
of smart reflex operation. They also may need private data to be
used for operations of their own, provide the same.
Signed-off-by: Nishanth Menon <nm@ti.com>
---
arch/arm/mach-omap2/smartreflex.c | 14 ++++++++++++++
arch/arm/plat-omap/include/plat/smartreflex.h | 7 +++++++
2 files changed, 21 insertions(+), 0 deletions(-)
diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c
index 08e1ee4..35658a2 100644
--- a/arch/arm/mach-omap2/smartreflex.c
+++ b/arch/arm/mach-omap2/smartreflex.c
@@ -220,6 +220,13 @@ static void sr_start_vddautocomp(struct omap_sr *sr)
return;
}
+ if (sr_class->class_init &&
+ sr_class->class_init(sr->voltdm, sr_class->class_priv_data)) {
+ dev_err(&sr->pdev->dev,
+ "%s: SRClass initialization failed\n", __func__);
+ return;
+ }
+
if (!sr_class->enable(sr->voltdm))
sr->autocomp_active = true;
}
@@ -235,6 +242,13 @@ static void sr_stop_vddautocomp(struct omap_sr *sr)
if (sr->autocomp_active) {
sr_class->disable(sr->voltdm, 1);
+ if (sr_class->class_deinit &&
+ sr_class->class_deinit(sr->voltdm,
+ sr_class->class_priv_data)) {
+ dev_err(&sr->pdev->dev,
+ "%s: SR[%d]Class deinitialization failed\n",
+ __func__, sr->srid);
+ }
sr->autocomp_active = false;
}
}
diff --git a/arch/arm/plat-omap/include/plat/smartreflex.h b/arch/arm/plat-omap/include/plat/smartreflex.h
index 6568c88..8b6ecd9 100644
--- a/arch/arm/plat-omap/include/plat/smartreflex.h
+++ b/arch/arm/plat-omap/include/plat/smartreflex.h
@@ -167,6 +167,8 @@ struct omap_sr_pmic_data {
*
* @enable: API to enable a particular class smaartreflex.
* @disable: API to disable a particular class smartreflex.
+ * @class_init: API to do class specific initialization (optional)
+ * @class_deinit: API to do class specific initialization (optional)
* @configure: API to configure a particular class smartreflex.
* @notify: API to notify the class driver about an event in SR.
* Not needed for class3.
@@ -174,14 +176,19 @@ struct omap_sr_pmic_data {
* @class_type: specify which smartreflex class.
* Can be used by the SR driver to take any class
* based decisions.
+ * @class_priv_data: Class specific private data (optional)
*/
struct omap_sr_class_data {
int (*enable)(struct voltagedomain *voltdm);
int (*disable)(struct voltagedomain *voltdm, int is_volt_reset);
+ int (*class_init)(struct voltagedomain *voltdm, void *class_priv_data);
+ int (*class_deinit)(struct voltagedomain *voltdm,
+ void *class_priv_data);
int (*configure)(struct voltagedomain *voltdm);
int (*notify)(struct voltagedomain *voltdm, u32 status);
u8 notify_flags;
u8 class_type;
+ void *class_priv_data;
};
/**
--
1.7.1
^ permalink raw reply related
* [PATCH v2 07/18] omap3+: sr: make notify independent of class
From: Nishanth Menon @ 2011-03-02 10:55 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1299063331-27968-1-git-send-email-nm@ti.com>
Interrupt notification mechanism of SmartReflex can be used by the
choice of implementation of the class driver. For example, Class 2 and
Class 1.5 of SmartReflex can both use the interrupt notification to
identify the transition of voltage or other events.
Hence, the actual class does not matter for notifier. Let the class
driver's handling decide how it should be used. smartreflex driver
should provide just the primitives.
Signed-off-by: Nishanth Menon <nm@ti.com>
---
arch/arm/mach-omap2/smartreflex.c | 6 ++----
1 files changed, 2 insertions(+), 4 deletions(-)
diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c
index a1f532e..08e1ee4 100644
--- a/arch/arm/mach-omap2/smartreflex.c
+++ b/arch/arm/mach-omap2/smartreflex.c
@@ -142,7 +142,7 @@ static irqreturn_t sr_interrupt(int irq, void *data)
sr_write_reg(sr_info, IRQSTATUS, status);
}
- if (sr_class->class_type == SR_CLASS2 && sr_class->notify)
+ if (sr_class->notify)
sr_class->notify(sr_info->voltdm, status);
return IRQ_HANDLED;
@@ -257,9 +257,7 @@ static int sr_late_init(struct omap_sr *sr_info)
struct resource *mem;
int ret = 0;
- if (sr_class->class_type == SR_CLASS2 &&
- sr_class->notify_flags && sr_info->irq) {
-
+ if (sr_class->notify && sr_class->notify_flags && sr_info->irq) {
name = kasprintf(GFP_KERNEL, "sr_%s", sr_info->voltdm->name);
if (name == NULL) {
ret = -ENOMEM;
--
1.7.1
^ permalink raw reply related
* [PATCH v2 06/18] omap3+: voltage: add transdone apis
From: Nishanth Menon @ 2011-03-02 10:55 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1299063331-27968-1-git-send-email-nm@ti.com>
Transdone event in Voltage processor gives us fine grained status on
the current status of the voltage communication with the PMIC.
Unfortunately, irq generation by VP is based on the start of the
transmission to VC from VP, not at the end (or the completion of
the voltage setting). Hence any users of voltage layer who need
to know fine grained information such as confirmation if the voltage
is actually send to PMIC, needs to depend on this status.
Signed-off-by: Nishanth Menon <nm@ti.com>
---
arch/arm/mach-omap2/voltage.c | 64 ++++++++++++++++++++++-------
arch/arm/plat-omap/include/plat/voltage.h | 2 +
2 files changed, 51 insertions(+), 15 deletions(-)
diff --git a/arch/arm/mach-omap2/voltage.c b/arch/arm/mach-omap2/voltage.c
index 50a6913..3cbe450 100644
--- a/arch/arm/mach-omap2/voltage.c
+++ b/arch/arm/mach-omap2/voltage.c
@@ -644,8 +644,8 @@ static int vp_forceupdate_scale_voltage(struct omap_vdd_info *vdd,
struct omap_volt_data *target_volt)
{
u32 vpconfig;
- u16 mod, ocp_mod;
- u8 target_vsel, current_vsel, prm_irqst_reg;
+ u16 mod;
+ u8 target_vsel, current_vsel;
int ret, timeout = 0;
ret = _pre_volt_scale(vdd, target_volt, &target_vsel, ¤t_vsel);
@@ -653,18 +653,13 @@ static int vp_forceupdate_scale_voltage(struct omap_vdd_info *vdd,
return ret;
mod = vdd->vp_reg.prm_mod;
- ocp_mod = vdd->ocp_mod;
- prm_irqst_reg = vdd->prm_irqst_reg;
-
/*
* Clear all pending TransactionDone interrupt/status. Typical latency
* is <3us
*/
while (timeout++ < VP_TRANXDONE_TIMEOUT) {
- vdd->write_reg(vdd->vp_reg.tranxdone_status,
- ocp_mod, prm_irqst_reg);
- if (!(vdd->read_reg(ocp_mod, prm_irqst_reg) &
- vdd->vp_reg.tranxdone_status))
+ omap_vp_clear_transdone(&vdd->voltdm);
+ if (!omap_vp_is_transdone(&vdd->voltdm))
break;
udelay(1);
}
@@ -696,7 +691,7 @@ static int vp_forceupdate_scale_voltage(struct omap_vdd_info *vdd,
* Depends on SMPSWAITTIMEMIN/MAX and voltage change
*/
timeout = 0;
- omap_test_timeout((vdd->read_reg(ocp_mod, prm_irqst_reg) &
+ omap_test_timeout((vdd->read_reg(vdd->ocp_mod, vdd->prm_irqst_reg) &
vdd->vp_reg.tranxdone_status),
VP_TRANXDONE_TIMEOUT, timeout);
if (timeout >= VP_TRANXDONE_TIMEOUT)
@@ -712,11 +707,9 @@ static int vp_forceupdate_scale_voltage(struct omap_vdd_info *vdd,
*/
timeout = 0;
while (timeout++ < VP_TRANXDONE_TIMEOUT) {
- vdd->write_reg(vdd->vp_reg.tranxdone_status,
- ocp_mod, prm_irqst_reg);
- if (!(vdd->read_reg(ocp_mod, prm_irqst_reg) &
- vdd->vp_reg.tranxdone_status))
- break;
+ omap_vp_clear_transdone(&vdd->voltdm);
+ if (!omap_vp_is_transdone(&vdd->voltdm))
+ break;
udelay(1);
}
@@ -1274,6 +1267,47 @@ void omap_vp_disable(struct voltagedomain *voltdm)
}
/**
+ * omap_vp_is_transdone() - is voltage transfer done on vp?
+ * @voltdm: pointer to the VDD which is to be scaled.
+ *
+ * VP's transdone bit is the only way to ensure that the transfer
+ * of the voltage value has actually been send over to the PMIC
+ * This is hence useful for all users of voltage domain to precisely
+ * identify once the PMIC voltage has been set by the voltage processor
+ */
+bool omap_vp_is_transdone(struct voltagedomain *voltdm)
+{
+ struct omap_vdd_info *vdd;
+
+ if (IS_ERR_OR_NULL(voltdm)) {
+ pr_warning("%s: Bad Params vdm=%p\n", __func__, voltdm);
+ return false;
+ }
+
+ vdd = container_of(voltdm, struct omap_vdd_info, voltdm);
+ return (vdd->read_reg(vdd->ocp_mod, vdd->prm_irqst_reg) &
+ vdd->vp_reg.tranxdone_status) ? true : false;
+}
+
+/**
+ * omap_vp_clear_transdone() - clear voltage transfer done status on vp
+ * @voltdm: pointer to the VDD which is to be scaled.
+ */
+bool omap_vp_clear_transdone(struct voltagedomain *voltdm)
+{
+ struct omap_vdd_info *vdd;
+
+ if (IS_ERR_OR_NULL(voltdm)) {
+ pr_warning("%s: Bad Params vdm=%p\n", __func__, voltdm);
+ return false;
+ }
+
+ vdd = container_of(voltdm, struct omap_vdd_info, voltdm);
+ vdd->write_reg(vdd->vp_reg.tranxdone_status,
+ vdd->ocp_mod, vdd->prm_irqst_reg);
+ return true;
+}
+/**
* omap_voltage_scale_vdd() - API to scale voltage of a particular
* voltage domain.
* @voltdm: pointer to the VDD which is to be scaled.
diff --git a/arch/arm/plat-omap/include/plat/voltage.h b/arch/arm/plat-omap/include/plat/voltage.h
index 00fcfb4..816a785 100644
--- a/arch/arm/plat-omap/include/plat/voltage.h
+++ b/arch/arm/plat-omap/include/plat/voltage.h
@@ -124,6 +124,8 @@ void omap_voltage_get_volttable(struct voltagedomain *voltdm,
struct omap_volt_data *omap_voltage_get_voltdata(struct voltagedomain *voltdm,
unsigned long volt);
struct omap_volt_data *omap_voltage_get_nom_volt(struct voltagedomain *voltdm);
+bool omap_vp_is_transdone(struct voltagedomain *voltdm);
+bool omap_vp_clear_transdone(struct voltagedomain *voltdm);
struct dentry *omap_voltage_get_dbgdir(struct voltagedomain *voltdm);
#ifdef CONFIG_PM
int omap_voltage_register_pmic(struct voltagedomain *voltdm,
--
1.7.1
^ permalink raw reply related
* [PATCH v2 05/18] omap3+: voltage: use volt_data pointer instead values
From: Nishanth Menon @ 2011-03-02 10:55 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1299063331-27968-1-git-send-email-nm@ti.com>
Voltage values can get confusing in meaning with various Smartreflex
classes being active. Depending on the class used, the actual voltage
selected might be a variant. For example:
with SmartReflex AVS class 3:
a) if we dont have SR enabled, we will go to volt_nominal
b) if have SR enabled, we go to volt_nominal, then enable SR and
expect it to adjust voltage. We dont really care about the
resultant voltage
Essentially, when we ask voltage layer to scale to voltage x for OPP
y, it always means x is the nominal voltage for OPP y.
Now, once we introduce SmartReflex AVS class 1.5:
a) If you are booting for the first time OR if you never enable SR
before, we always go to volt_nominal
b) If you enable SR and the OPP is calibrated, we will not enable SR
again when that OPP is accessed anymore, but when we set voltage for
an OPP, the voltage achieved will be volt_calibrated
c) If recalibration timeout triggers,or SR is disabled after a
calibration, the calibrated values are not valid anymore, at this point,
setting the voltage will mean volt_dynamic_nominal.
So, depending on which state the system is at, voltage for that OPP
we are setting has not 1 single value anymore, but 3 possible valid
values.
For upper layers(dvfs/cpufreq OMAP SoC layers) to use voltage values, it
will need to know which type of voltage AVS strategy is being used and
the corresponding system state from voltage layer perspective. This
would replicate the role of voltage layer, SmartReflex AVS in the upper
layers and make the corresponding implementations complex.
Since each voltage domain contains a set of volt_data structs representing
a voltage point that is supported for that domain, volt_data is a more
accurate representation of the voltage point we are interested in going to,
and the actual translation of this voltage point to the voltage value is
done inside the voltage layer. Doing this allows the users of the voltage
layer to be blissfully ignorant of any complexity of the underneath
layers and simplify the implementation of dependent layers.
Signed-off-by: Nishanth Menon <nm@ti.com>
---
arch/arm/mach-omap2/pm.c | 3 +-
arch/arm/mach-omap2/smartreflex-class3.c | 3 +-
arch/arm/mach-omap2/voltage.c | 77 ++++++++++++++++-------------
arch/arm/plat-omap/include/plat/voltage.h | 13 ++++-
4 files changed, 58 insertions(+), 38 deletions(-)
diff --git a/arch/arm/mach-omap2/pm.c b/arch/arm/mach-omap2/pm.c
index d5a102c..669998b 100644
--- a/arch/arm/mach-omap2/pm.c
+++ b/arch/arm/mach-omap2/pm.c
@@ -209,7 +209,8 @@ static int __init omap2_set_init_voltage(char *vdd_name, char *clk_name,
goto exit;
}
- omap_voltage_scale_vdd(voltdm, bootup_volt);
+ omap_voltage_scale_vdd(voltdm,
+ omap_voltage_get_voltdata(voltdm, bootup_volt));
return 0;
exit:
diff --git a/arch/arm/mach-omap2/smartreflex-class3.c b/arch/arm/mach-omap2/smartreflex-class3.c
index 60e7055..2195668 100644
--- a/arch/arm/mach-omap2/smartreflex-class3.c
+++ b/arch/arm/mach-omap2/smartreflex-class3.c
@@ -15,7 +15,8 @@
static int sr_class3_enable(struct voltagedomain *voltdm)
{
- unsigned long volt = omap_voltage_get_nom_volt(voltdm);
+ unsigned long volt = omap_get_operation_voltage(
+ omap_voltage_get_nom_volt(voltdm));
if (!volt) {
pr_warning("%s: Curr voltage unknown. Cannot enable sr_%s\n",
diff --git a/arch/arm/mach-omap2/voltage.c b/arch/arm/mach-omap2/voltage.c
index 3ee8a80..50a6913 100644
--- a/arch/arm/mach-omap2/voltage.c
+++ b/arch/arm/mach-omap2/voltage.c
@@ -146,14 +146,14 @@ struct omap_vdd_info {
struct vc_reg_info vc_reg;
struct voltagedomain voltdm;
struct dentry *debug_dir;
- u32 curr_volt;
+ struct omap_volt_data *curr_volt;
u16 ocp_mod;
u8 prm_irqst_reg;
bool vp_enabled;
u32 (*read_reg) (u16 mod, u8 offset);
void (*write_reg) (u32 val, u16 mod, u8 offset);
int (*volt_scale) (struct omap_vdd_info *vdd,
- unsigned long target_volt);
+ struct omap_volt_data *target_volt);
};
static struct omap_vdd_info *vdd_info;
@@ -361,13 +361,20 @@ static int vp_volt_debug_get(void *data, u64 *val)
static int nom_volt_debug_get(void *data, u64 *val)
{
struct omap_vdd_info *vdd = (struct omap_vdd_info *) data;
+ struct omap_volt_data *volt_data;
if (!vdd) {
pr_warning("Wrong paramater passed\n");
return -EINVAL;
}
- *val = omap_voltage_get_nom_volt(&vdd->voltdm);
+ volt_data = omap_voltage_get_nom_volt(&vdd->voltdm);
+ if (IS_ERR_OR_NULL(volt_data)) {
+ pr_warning("%s: No voltage/domain?\n", __func__);
+ return -ENODEV;
+ }
+
+ *val = volt_data->volt_nominal;
return 0;
}
@@ -382,7 +389,8 @@ static void vp_latch_vsel(struct omap_vdd_info *vdd)
unsigned long uvdc;
char vsel;
- uvdc = omap_voltage_get_nom_volt(&vdd->voltdm);
+ uvdc = omap_get_operation_voltage(
+ omap_voltage_get_nom_volt(&vdd->voltdm));
if (!uvdc) {
pr_warning("%s: unable to find current voltage for vdd_%s\n",
__func__, vdd->voltdm.name);
@@ -505,12 +513,18 @@ static void __init vdd_debugfs_init(struct omap_vdd_info *vdd)
/* Voltage scale and accessory APIs */
static int _pre_volt_scale(struct omap_vdd_info *vdd,
- unsigned long target_volt, u8 *target_vsel, u8 *current_vsel)
+ struct omap_volt_data *target_volt, u8 *target_vsel,
+ u8 *current_vsel)
{
- struct omap_volt_data *volt_data;
u32 vc_cmdval, vp_errgain_val;
u16 vp_mod, vc_mod;
+ if (IS_ERR_OR_NULL(target_volt) || IS_ERR_OR_NULL(vdd) ||
+ !target_vsel || !current_vsel) {
+ pr_err("%s: invalid parms!\n", __func__);
+ return -EINVAL;
+ }
+
/* Check if suffiecient pmic info is available for this vdd */
if (!vdd->pmic_info) {
pr_err("%s: Insufficient pmic info to scale the vdd_%s\n",
@@ -534,12 +548,8 @@ static int _pre_volt_scale(struct omap_vdd_info *vdd,
vp_mod = vdd->vp_reg.prm_mod;
vc_mod = vdd->vc_reg.prm_mod;
- /* Get volt_data corresponding to target_volt */
- volt_data = omap_voltage_get_voltdata(&vdd->voltdm, target_volt);
- if (IS_ERR(volt_data))
- volt_data = NULL;
-
- *target_vsel = vdd->pmic_info->uv_to_vsel(target_volt);
+ *target_vsel = vdd->pmic_info->uv_to_vsel(
+ omap_get_operation_voltage(target_volt));
*current_vsel = vdd->read_reg(vp_mod, vdd->vp_offs.voltage);
/* Setting the ON voltage to the new target voltage */
@@ -549,22 +559,21 @@ static int _pre_volt_scale(struct omap_vdd_info *vdd,
vdd->write_reg(vc_cmdval, vc_mod, vdd->vc_reg.cmdval_reg);
/* Setting vp errorgain based on the voltage */
- if (volt_data) {
- vp_errgain_val = vdd->read_reg(vp_mod,
- vdd->vp_offs.vpconfig);
- vdd->vp_reg.vpconfig_errorgain = volt_data->vp_errgain;
- vp_errgain_val &= ~vdd->vp_reg.vpconfig_errorgain_mask;
- vp_errgain_val |= vdd->vp_reg.vpconfig_errorgain <<
- vdd->vp_reg.vpconfig_errorgain_shift;
- vdd->write_reg(vp_errgain_val, vp_mod,
- vdd->vp_offs.vpconfig);
- }
+ vp_errgain_val = vdd->read_reg(vp_mod,
+ vdd->vp_offs.vpconfig);
+ vdd->vp_reg.vpconfig_errorgain = target_volt->vp_errgain;
+ vp_errgain_val &= ~vdd->vp_reg.vpconfig_errorgain_mask;
+ vp_errgain_val |= vdd->vp_reg.vpconfig_errorgain <<
+ vdd->vp_reg.vpconfig_errorgain_shift;
+ vdd->write_reg(vp_errgain_val, vp_mod,
+ vdd->vp_offs.vpconfig);
return 0;
}
static void _post_volt_scale(struct omap_vdd_info *vdd,
- unsigned long target_volt, u8 target_vsel, u8 current_vsel)
+ struct omap_volt_data *target_volt, u8 target_vsel,
+ u8 current_vsel)
{
u32 smps_steps = 0, smps_delay = 0;
@@ -579,7 +588,7 @@ static void _post_volt_scale(struct omap_vdd_info *vdd,
/* vc_bypass_scale_voltage - VC bypass method of voltage scaling */
static int vc_bypass_scale_voltage(struct omap_vdd_info *vdd,
- unsigned long target_volt)
+ struct omap_volt_data *target_volt)
{
u32 loop_cnt = 0, retries_cnt = 0;
u32 vc_valid, vc_bypass_val_reg, vc_bypass_value;
@@ -632,7 +641,7 @@ static int vc_bypass_scale_voltage(struct omap_vdd_info *vdd,
/* VP force update method of voltage scaling */
static int vp_forceupdate_scale_voltage(struct omap_vdd_info *vdd,
- unsigned long target_volt)
+ struct omap_volt_data *target_volt)
{
u32 vpconfig;
u16 mod, ocp_mod;
@@ -1118,16 +1127,15 @@ static int __init omap4_vdd_data_configure(struct omap_vdd_info *vdd)
* omap_voltage_get_nom_volt() - Gets the current non-auto-compensated voltage
* @voltdm: pointer to the VDD for which current voltage info is needed
*
- * API to get the current non-auto-compensated voltage for a VDD.
- * Returns 0 in case of error else returns the current voltage for the VDD.
+ * API to get the current non-auto-compensated voltage data pointer for a VDD.
*/
-unsigned long omap_voltage_get_nom_volt(struct voltagedomain *voltdm)
+struct omap_volt_data *omap_voltage_get_nom_volt(struct voltagedomain *voltdm)
{
struct omap_vdd_info *vdd;
if (IS_ERR_OR_NULL(voltdm)) {
pr_warning("%s: VDD specified does not exist!\n", __func__);
- return 0;
+ return ERR_PTR(-ENODATA);
}
vdd = container_of(voltdm, struct omap_vdd_info, voltdm);
@@ -1269,18 +1277,19 @@ void omap_vp_disable(struct voltagedomain *voltdm)
* omap_voltage_scale_vdd() - API to scale voltage of a particular
* voltage domain.
* @voltdm: pointer to the VDD which is to be scaled.
- * @target_volt: The target voltage of the voltage domain
+ * @target_volt: The target voltage data for the voltage domain
*
* This API should be called by the kernel to do the voltage scaling
* for a particular voltage domain during dvfs or any other situation.
*/
int omap_voltage_scale_vdd(struct voltagedomain *voltdm,
- unsigned long target_volt)
+ struct omap_volt_data *target_volt)
{
struct omap_vdd_info *vdd;
- if (!voltdm || IS_ERR(voltdm)) {
- pr_warning("%s: VDD specified does not exist!\n", __func__);
+ if (IS_ERR_OR_NULL(voltdm) || IS_ERR_OR_NULL(target_volt)) {
+ pr_warning("%s: Bad Params vdm=%p tv=%p!\n", __func__,
+ voltdm, target_volt);
return -EINVAL;
}
@@ -1306,7 +1315,7 @@ int omap_voltage_scale_vdd(struct voltagedomain *voltdm,
*/
void omap_voltage_reset(struct voltagedomain *voltdm)
{
- unsigned long target_uvdc;
+ struct omap_volt_data *target_uvdc;
if (IS_ERR_OR_NULL(voltdm)) {
pr_warning("%s: VDD specified does not exist!\n", __func__);
diff --git a/arch/arm/plat-omap/include/plat/voltage.h b/arch/arm/plat-omap/include/plat/voltage.h
index 4d9bab1..00fcfb4 100644
--- a/arch/arm/plat-omap/include/plat/voltage.h
+++ b/arch/arm/plat-omap/include/plat/voltage.h
@@ -117,13 +117,13 @@ unsigned long omap_vp_get_curr_volt(struct voltagedomain *voltdm);
void omap_vp_enable(struct voltagedomain *voltdm);
void omap_vp_disable(struct voltagedomain *voltdm);
int omap_voltage_scale_vdd(struct voltagedomain *voltdm,
- unsigned long target_volt);
+ struct omap_volt_data *target_volt);
void omap_voltage_reset(struct voltagedomain *voltdm);
void omap_voltage_get_volttable(struct voltagedomain *voltdm,
struct omap_volt_data **volt_data);
struct omap_volt_data *omap_voltage_get_voltdata(struct voltagedomain *voltdm,
unsigned long volt);
-unsigned long omap_voltage_get_nom_volt(struct voltagedomain *voltdm);
+struct omap_volt_data *omap_voltage_get_nom_volt(struct voltagedomain *voltdm);
struct dentry *omap_voltage_get_dbgdir(struct voltagedomain *voltdm);
#ifdef CONFIG_PM
int omap_voltage_register_pmic(struct voltagedomain *voltdm,
@@ -152,4 +152,13 @@ static inline struct voltagedomain *omap_voltage_domain_lookup(char *name)
}
#endif
+/* convert volt data to the voltage for the voltage data */
+static inline unsigned long omap_get_operation_voltage(
+ struct omap_volt_data *vdata)
+{
+ if (IS_ERR_OR_NULL(vdata))
+ return 0;
+ return vdata->volt_nominal;
+}
+
#endif
--
1.7.1
^ permalink raw reply related
* [PATCH v2 04/18] omap3+: voltage: use IS_ERR_OR_NULL
From: Nishanth Menon @ 2011-03-02 10:55 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1299063331-27968-1-git-send-email-nm@ti.com>
Use IS_ERR_OR_NULL macro instead of just IS_ERR or !xyz || IS_ERR(xyz)
style usage.
Signed-off-by: Nishanth Menon <nm@ti.com>
---
arch/arm/mach-omap2/voltage.c | 28 ++++++++++++++--------------
1 files changed, 14 insertions(+), 14 deletions(-)
diff --git a/arch/arm/mach-omap2/voltage.c b/arch/arm/mach-omap2/voltage.c
index 992b383..3ee8a80 100644
--- a/arch/arm/mach-omap2/voltage.c
+++ b/arch/arm/mach-omap2/voltage.c
@@ -471,7 +471,7 @@ static void __init vdd_debugfs_init(struct omap_vdd_info *vdd)
vdd->debug_dir = debugfs_create_dir(name, voltage_dir);
kfree(name);
- if (IS_ERR(vdd->debug_dir)) {
+ if (IS_ERR_OR_NULL(vdd->debug_dir)) {
pr_warning("%s: Unable to create debugfs directory for"
" vdd_%s\n", __func__, vdd->voltdm.name);
vdd->debug_dir = NULL;
@@ -851,7 +851,7 @@ static int __init omap3_vdd_data_configure(struct omap_vdd_info *vdd)
* smpswaittimemin and smpswaittimemax.
*/
sys_ck = clk_get(NULL, "sys_ck");
- if (IS_ERR(sys_ck)) {
+ if (IS_ERR_OR_NULL(sys_ck)) {
pr_warning("%s: Could not get the sys clk to calculate"
"various vdd_%s params\n", __func__, vdd->voltdm.name);
return -EINVAL;
@@ -1041,7 +1041,7 @@ static int __init omap4_vdd_data_configure(struct omap_vdd_info *vdd)
* smpswaittimemin and smpswaittimemax.
*/
sys_ck = clk_get(NULL, "sys_clkin_ck");
- if (IS_ERR(sys_ck)) {
+ if (IS_ERR_OR_NULL(sys_ck)) {
pr_warning("%s: Could not get the sys clk to calculate"
"various vdd_%s params\n", __func__, vdd->voltdm.name);
return -EINVAL;
@@ -1125,7 +1125,7 @@ unsigned long omap_voltage_get_nom_volt(struct voltagedomain *voltdm)
{
struct omap_vdd_info *vdd;
- if (!voltdm || IS_ERR(voltdm)) {
+ if (IS_ERR_OR_NULL(voltdm)) {
pr_warning("%s: VDD specified does not exist!\n", __func__);
return 0;
}
@@ -1146,7 +1146,7 @@ unsigned long omap_vp_get_curr_volt(struct voltagedomain *voltdm)
struct omap_vdd_info *vdd;
u8 curr_vsel;
- if (!voltdm || IS_ERR(voltdm)) {
+ if (IS_ERR_OR_NULL(voltdm)) {
pr_warning("%s: VDD specified does not exist!\n", __func__);
return 0;
}
@@ -1183,7 +1183,7 @@ void omap_vp_enable(struct voltagedomain *voltdm)
u32 vpconfig;
u16 mod;
- if (!voltdm || IS_ERR(voltdm)) {
+ if (IS_ERR_OR_NULL(voltdm)) {
pr_warning("%s: VDD specified does not exist!\n", __func__);
return;
}
@@ -1224,7 +1224,7 @@ void omap_vp_disable(struct voltagedomain *voltdm)
u16 mod;
int timeout;
- if (!voltdm || IS_ERR(voltdm)) {
+ if (IS_ERR_OR_NULL(voltdm)) {
pr_warning("%s: VDD specified does not exist!\n", __func__);
return;
}
@@ -1308,7 +1308,7 @@ void omap_voltage_reset(struct voltagedomain *voltdm)
{
unsigned long target_uvdc;
- if (!voltdm || IS_ERR(voltdm)) {
+ if (IS_ERR_OR_NULL(voltdm)) {
pr_warning("%s: VDD specified does not exist!\n", __func__);
return;
}
@@ -1340,7 +1340,7 @@ void omap_voltage_get_volttable(struct voltagedomain *voltdm,
{
struct omap_vdd_info *vdd;
- if (!voltdm || IS_ERR(voltdm)) {
+ if (IS_ERR_OR_NULL(voltdm)) {
pr_warning("%s: VDD specified does not exist!\n", __func__);
return;
}
@@ -1371,7 +1371,7 @@ struct omap_volt_data *omap_voltage_get_voltdata(struct voltagedomain *voltdm,
struct omap_vdd_info *vdd;
int i;
- if (!voltdm || IS_ERR(voltdm)) {
+ if (IS_ERR_OR_NULL(voltdm)) {
pr_warning("%s: VDD specified does not exist!\n", __func__);
return ERR_PTR(-EINVAL);
}
@@ -1409,7 +1409,7 @@ int omap_voltage_register_pmic(struct voltagedomain *voltdm,
{
struct omap_vdd_info *vdd;
- if (!voltdm || IS_ERR(voltdm)) {
+ if (IS_ERR_OR_NULL(voltdm)) {
pr_warning("%s: VDD specified does not exist!\n", __func__);
return -EINVAL;
}
@@ -1436,7 +1436,7 @@ struct dentry *omap_voltage_get_dbgdir(struct voltagedomain *voltdm)
{
struct omap_vdd_info *vdd;
- if (!voltdm || IS_ERR(voltdm)) {
+ if (IS_ERR_OR_NULL(voltdm)) {
pr_warning("%s: VDD specified does not exist!\n", __func__);
return NULL;
}
@@ -1461,7 +1461,7 @@ void omap_change_voltscale_method(struct voltagedomain *voltdm,
{
struct omap_vdd_info *vdd;
- if (!voltdm || IS_ERR(voltdm)) {
+ if (IS_ERR_OR_NULL(voltdm)) {
pr_warning("%s: VDD specified does not exist!\n", __func__);
return;
}
@@ -1531,7 +1531,7 @@ int __init omap_voltage_late_init(void)
}
voltage_dir = debugfs_create_dir("voltage", NULL);
- if (IS_ERR(voltage_dir))
+ if (IS_ERR_OR_NULL(voltage_dir))
pr_err("%s: Unable to create voltage debugfs main dir\n",
__func__);
for (i = 0; i < nr_scalable_vdd; i++) {
--
1.7.1
^ permalink raw reply related
* [PATCH v2 03/18] omap3+: voltage: remove spurious pr_notice for debugfs
From: Nishanth Menon @ 2011-03-02 10:55 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1299063331-27968-1-git-send-email-nm@ti.com>
cat of debugfs entry for vp_volt provides voltage. The additional pr_notice
is just spam on console and provides no additional information.
Signed-off-by: Nishanth Menon <nm@ti.com>
---
arch/arm/mach-omap2/voltage.c | 1 -
1 files changed, 0 insertions(+), 1 deletions(-)
diff --git a/arch/arm/mach-omap2/voltage.c b/arch/arm/mach-omap2/voltage.c
index 280ee12..992b383 100644
--- a/arch/arm/mach-omap2/voltage.c
+++ b/arch/arm/mach-omap2/voltage.c
@@ -347,7 +347,6 @@ static int vp_volt_debug_get(void *data, u64 *val)
}
vsel = vdd->read_reg(vdd->vp_reg.prm_mod, vdd->vp_offs.voltage);
- pr_notice("curr_vsel = %x\n", vsel);
if (!vdd->pmic_info->vsel_to_uv) {
pr_warning("PMIC function to convert vsel to voltage"
--
1.7.1
^ permalink raw reply related
* [PATCH v2 02/18] omap3+: voltage: remove initial voltage
From: Nishanth Menon @ 2011-03-02 10:55 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1299063331-27968-1-git-send-email-nm@ti.com>
omap2_set_init_voltage should setup the curr_volt based on which OPP
the system is functioning at. Blindly setting a 1.2v setting in the
initial structure may not even match the default voltages stored in
the voltage table which are supported for the domain.
For example, OMAP3430 core domain does not use 1.2v and ends up
generating a warning on the first transition.
Signed-off-by: Nishanth Menon <nm@ti.com>
---
arch/arm/mach-omap2/voltage.c | 2 --
1 files changed, 0 insertions(+), 2 deletions(-)
diff --git a/arch/arm/mach-omap2/voltage.c b/arch/arm/mach-omap2/voltage.c
index 12be525..280ee12 100644
--- a/arch/arm/mach-omap2/voltage.c
+++ b/arch/arm/mach-omap2/voltage.c
@@ -863,7 +863,6 @@ static int __init omap3_vdd_data_configure(struct omap_vdd_info *vdd)
sys_clk_speed /= 1000;
/* Generic voltage parameters */
- vdd->curr_volt = 1200000;
vdd->ocp_mod = OCP_MOD;
vdd->prm_irqst_reg = OMAP3_PRM_IRQSTATUS_MPU_OFFSET;
vdd->read_reg = omap3_voltage_read_reg;
@@ -1054,7 +1053,6 @@ static int __init omap4_vdd_data_configure(struct omap_vdd_info *vdd)
sys_clk_speed /= 1000;
/* Generic voltage parameters */
- vdd->curr_volt = 1200000;
vdd->ocp_mod = OMAP4430_PRM_OCP_SOCKET_INST;
vdd->read_reg = omap4_voltage_read_reg;
vdd->write_reg = omap4_voltage_write_reg;
--
1.7.1
^ permalink raw reply related
* [PATCH v2 01/18] omap3: hwmod: add smartreflex irqs
From: Nishanth Menon @ 2011-03-02 10:55 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1299063331-27968-1-git-send-email-nm@ti.com>
OMAP3 smartreflex irqs in hwmod structures with the same naming as
present in OMAP4. Without these IRQs being registered, SmartReflex
driver will be unable to get the irq numbers to handle notifications
Signed-off-by: Nishanth Menon <nm@ti.com>
---
arch/arm/mach-omap2/omap_hwmod_3xxx_data.c | 17 +++++++++++++++++
1 files changed, 17 insertions(+), 0 deletions(-)
diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
index 8d81813..ea1f49a 100644
--- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
@@ -265,6 +265,15 @@ static struct omap_hwmod_ocp_if omap3_l4_core__i2c3 = {
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
+
+static struct omap_hwmod_irq_info omap3_smartreflex_mpu_irqs[] = {
+ {.name = "sr1_irq", .irq = 18},
+};
+
+static struct omap_hwmod_irq_info omap3_smartreflex_core_irqs[] = {
+ {.name = "sr2_irq", .irq = 19},
+};
+
/* L4 CORE -> SR1 interface */
static struct omap_hwmod_addr_space omap3_sr1_addr_space[] = {
{
@@ -1289,6 +1298,8 @@ static struct omap_hwmod omap34xx_sr1_hwmod = {
CHIP_IS_OMAP3430ES3_0 |
CHIP_IS_OMAP3430ES3_1),
.flags = HWMOD_SET_DEFAULT_CLOCKACT,
+ .mpu_irqs = omap3_smartreflex_mpu_irqs,
+ .mpu_irqs_cnt = ARRAY_SIZE(omap3_smartreflex_mpu_irqs),
};
static struct omap_hwmod omap36xx_sr1_hwmod = {
@@ -1308,6 +1319,8 @@ static struct omap_hwmod omap36xx_sr1_hwmod = {
.slaves = omap3_sr1_slaves,
.slaves_cnt = ARRAY_SIZE(omap3_sr1_slaves),
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3630ES1),
+ .mpu_irqs = omap3_smartreflex_mpu_irqs,
+ .mpu_irqs_cnt = ARRAY_SIZE(omap3_smartreflex_mpu_irqs),
};
/* SR2 */
@@ -1335,6 +1348,8 @@ static struct omap_hwmod omap34xx_sr2_hwmod = {
CHIP_IS_OMAP3430ES3_0 |
CHIP_IS_OMAP3430ES3_1),
.flags = HWMOD_SET_DEFAULT_CLOCKACT,
+ .mpu_irqs = omap3_smartreflex_core_irqs,
+ .mpu_irqs_cnt = ARRAY_SIZE(omap3_smartreflex_core_irqs),
};
static struct omap_hwmod omap36xx_sr2_hwmod = {
@@ -1354,6 +1369,8 @@ static struct omap_hwmod omap36xx_sr2_hwmod = {
.slaves = omap3_sr2_slaves,
.slaves_cnt = ARRAY_SIZE(omap3_sr2_slaves),
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3630ES1),
+ .mpu_irqs = omap3_smartreflex_core_irqs,
+ .mpu_irqs_cnt = ARRAY_SIZE(omap3_smartreflex_core_irqs),
};
static __initdata struct omap_hwmod *omap3xxx_hwmods[] = {
--
1.7.1
^ permalink raw reply related
* [PATCH v2 00/18] OMAP3+: PM: introduce SR class 1.5
From: Nishanth Menon @ 2011-03-02 10:55 UTC (permalink / raw)
To: linux-arm-kernel
Hi,
This series intends to introduce SmartReflex AVS Class 1.5 support which
is now the recommended AVS class for usage in OMAP3630, OMAP4 and potentially
in later generation of silicon as well. Smartreflex class 1.5 is a software
controlled hardware calibration mechanism designed to improve dvfs latencies
and system performance as well as helping bring in additional benefits to the
system from h/w perspective. The corresponding patch has details on this class
and the implementation as well.
The series eventually results in OMAP343x based platforms using class3 and
OMAP3630, OMAP4 platforms using class1.5 automatically without modifications
or additions to board files.
This series is Based on:
a) k.org 2.6.38-rc7 (b2.6.38-rc7)
b) The following branches Kevin Hilman's tree: (pm-base-v2)
'pm/for_2.6.38/pm-fixes', 'pm/for_2.6.39/pm-misc' and 'pm/pm-wip/cpufreq'
http://git.kernel.org/?p=linux/kernel/git/khilman/linux-omap-pm.git;a=summary
Rationale: there are some sr-cleanups done here which makes at least 1 patch
create a minor conflict (kasprintf for sr name), but should reasonably
apply to k.org as well, and since this series is targeted for 39-rc1, builds
on previously accepted patches.
Some good fixes needed are here (optional):
c) sr-fixes: (sr-baseline-v2)
http://marc.info/?l=linux-omap&m=129783708019505&w=2
http://marc.info/?l=linux-omap&m=129679846322563&w=2
Other interesting series:
i) http://marc.info/?t=129825445100003&r=1&w=2 cleanups of voltage.c
- rebase should be minor effort
ii) http://marc.info/?l=linux-omap&m=129783700319445&w=2 fixes for omap4
- might conflict on macro cleanup with (i)
- should not conflict with the current series.
This series is also available at:
git://gitorious.org/linux-omap-nm-sr/linux-omap-sr.git
Branch: sr-1.5-v2
Note: There is also a branch dvfs-test-v2 in my tree which contains the test
version of code for OMAP3 based on Vishwa's DVFS series which is currently
being revamped. if run on OMAP4, it just throws up a bit of warnings, but
wont crash.
The series contains a bunch of bugfixes and improvements needed to introduce
Smartreflex class 1.5.
Changes in v2 since v1:
* I dropped patch 2/19 for 3630 ES revision, based on the discussion in:
http://marc.info/?t=129811710300003&r=1&w=2
NOTE: 3630 ES revision fixes need to be cleanly done at a later point,
and there is not much use doing a temporary hackup job just for SR. Since
it ain't broke atm for higher ES revs for SR, I will leave it alone.
* Fixed the bug exposed by bootloaders which setup an OPP which is not enabled
in kernel http://marc.info/?t=129811710500010&r=1&w=2
- parameter checks were necessary, impacted patches 5 and 17
* Documentation update following the explanation required for
http://marc.info/?t=129811710300007&r=1&w=2 for patch 5
- example provided in the discussion is useful for reviewer perspective in
commit message
Comments not incorporated from v1:
* http://marc.info/?t=129811710500007&r=1&w=2 - there is no reason to allow
sr notifiers after class has been deinitialized, so not allowing it.
* http://marc.info/?t=129811710300004&r=1&w=2 - the omap2_init_voltage fix
is not the intent of this series. infact handling of mpurate and
omap2_init_voltage needs to be merged in at some future point of time.
v1: http://marc.info/?l=linux-omap&m=129811693118173&w=2
Nishanth Menon (18):
omap3: hwmod: add smartreflex irqs
omap3+: voltage: remove initial voltage
omap3+: voltage: remove spurious pr_notice for debugfs
omap3+: voltage: use IS_ERR_OR_NULL
omap3+: voltage: use volt_data pointer instead values
omap3+: voltage: add transdone apis
omap3+: sr: make notify independent of class
omap3+: sr: introduce class init,deinit and priv data
omap3+: sr: fix cosmetic indentation
omap3+: sr: call handler with interrupt disabled
omap3+: sr: disable interrupt by default
omap3+: sr: enable/disable SR only on need
omap3+: sr: introduce notifiers flags
omap3+: sr: introduce notifier_control
omap3+: sr: disable spamming interrupts
omap3+: sr: make enable path use volt_data pointer
omap3630+: sr: add support for class 1.5
omap3430: sr: class3: restrict cpu to run on
arch/arm/mach-omap2/Makefile | 1 +
arch/arm/mach-omap2/omap_hwmod_3xxx_data.c | 17 +
arch/arm/mach-omap2/pm.c | 3 +-
arch/arm/mach-omap2/smartreflex-class1p5.c | 582 +++++++++++++++++++++++++
arch/arm/mach-omap2/smartreflex-class3.c | 21 +-
arch/arm/mach-omap2/smartreflex.c | 249 +++++++++--
arch/arm/mach-omap2/voltage.c | 251 ++++++++---
arch/arm/plat-omap/Kconfig | 17 +
arch/arm/plat-omap/include/plat/smartreflex.h | 42 ++-
arch/arm/plat-omap/include/plat/voltage.h | 36 ++-
10 files changed, 1097 insertions(+), 122 deletions(-)
create mode 100644 arch/arm/mach-omap2/smartreflex-class1p5.c
Testing performed:
Testing with dvfs-test-v2 - http://pastebin.mozilla.org/1117872
- transitions from all opps to all other opps,sr enabled, disable
- platforms: SDP3430(OMAP3430), SDP3630(OMAP3630)
(note: dvfs series does'nt support OMAP4 yet)
Testing with sr-1.5-v2 - http://pastebin.mozilla.org/1117880
- enable disable in domain combinations, test the new debugfs entries
etc..
- platforms: SDP3430(OMAP3430), SDP3630(OMAP3630), PandaBoard(OMAP4430)
Regards,
Nishanth Menon
^ permalink raw reply
* [PATCH] ARM: mxs/mx28evk: add flexcan devices
From: Shawn Guo @ 2011-03-02 10:54 UTC (permalink / raw)
To: linux-arm-kernel
Signed-off-by: Shawn Guo <shawn.guo@freescale.com>
---
arch/arm/mach-mxs/Kconfig | 1 +
arch/arm/mach-mxs/mach-mx28evk.c | 37 +++++++++++++++++++++++++++++++++++++
2 files changed, 38 insertions(+), 0 deletions(-)
diff --git a/arch/arm/mach-mxs/Kconfig b/arch/arm/mach-mxs/Kconfig
index 55bf075..9a1f2cb 100644
--- a/arch/arm/mach-mxs/Kconfig
+++ b/arch/arm/mach-mxs/Kconfig
@@ -31,6 +31,7 @@ config MACH_MX28EVK
select MXS_HAVE_AMBA_DUART
select MXS_HAVE_PLATFORM_AUART
select MXS_HAVE_PLATFORM_FEC
+ select MXS_HAVE_PLATFORM_FLEXCAN
select MXS_OCOTP
default y
help
diff --git a/arch/arm/mach-mxs/mach-mx28evk.c b/arch/arm/mach-mxs/mach-mx28evk.c
index 1f0b708..3cefb73 100644
--- a/arch/arm/mach-mxs/mach-mx28evk.c
+++ b/arch/arm/mach-mxs/mach-mx28evk.c
@@ -28,6 +28,7 @@
#include "devices-mx28.h"
#include "gpio.h"
+#define MX28EVK_FLEXCAN_SWITCH MXS_GPIO_NR(2, 13)
#define MX28EVK_FEC_PHY_POWER MXS_GPIO_NR(2, 15)
#define MX28EVK_FEC_PHY_RESET MXS_GPIO_NR(4, 13)
@@ -95,6 +96,15 @@ static const iomux_cfg_t mx28evk_pads[] __initconst = {
/* phy reset line */
MX28_PAD_ENET0_RX_CLK__GPIO_4_13 |
(MXS_PAD_4MA | MXS_PAD_3V3 | MXS_PAD_NOPULL),
+
+ /* flexcan0 */
+ MX28_PAD_GPMI_RDY2__CAN0_TX,
+ MX28_PAD_GPMI_RDY3__CAN0_RX,
+ /* flexcan1 */
+ MX28_PAD_GPMI_CE2N__CAN1_TX,
+ MX28_PAD_GPMI_CE3N__CAN1_RX,
+ /* transceiver power control */
+ MX28_PAD_SSP1_CMD__GPIO_2_13,
};
/* fec */
@@ -178,8 +188,28 @@ error:
return -ETIMEDOUT;
}
+/* flexcan */
+static void mx28evk_flexcan_switch(int enable)
+{
+ static int count;
+
+ if (enable) {
+ if (!count++)
+ gpio_set_value(MX28EVK_FLEXCAN_SWITCH, 1);
+ } else {
+ if (!--count)
+ gpio_set_value(MX28EVK_FLEXCAN_SWITCH, 0);
+ }
+}
+
+static const struct flexcan_platform_data mx28evk_flexcan_pdata __initconst = {
+ .transceiver_switch = mx28evk_flexcan_switch,
+};
+
static void __init mx28evk_init(void)
{
+ int ret;
+
mxs_iomux_setup_multiple_pads(mx28evk_pads, ARRAY_SIZE(mx28evk_pads));
mx28_add_duart();
@@ -192,6 +222,13 @@ static void __init mx28evk_init(void)
mx28evk_fec_reset();
mx28_add_fec(0, &mx28_fec_pdata[0]);
mx28_add_fec(1, &mx28_fec_pdata[1]);
+
+ ret = gpio_request_one(MX28EVK_FLEXCAN_SWITCH, GPIOF_DIR_OUT,
+ "flexcan-switch");
+ if (ret)
+ pr_warn("failed to request gpio flexcan-switch: %d\n", ret);
+ mx28_add_flexcan(0, &mx28evk_flexcan_pdata);
+ mx28_add_flexcan(1, &mx28evk_flexcan_pdata);
}
static void __init mx28evk_timer_init(void)
--
1.7.1
^ permalink raw reply related
* [PATCHv5 0/3] Introduce the /proc/socinfo and use it to export OMAP data
From: Maxime Coquelin @ 2011-03-02 10:53 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <AANLkTimJh_uGP6SYo=9ndz4xiUs1Tbg7z70ng0aFcWyG@mail.gmail.com>
On 03/02/2011 11:36 AM, Linus Walleij wrote:
> On Wed, Mar 2, 2011 at 9:23 AM, Maxime Coquelin
> <maxime.coquelin-nonst@stericsson.com> wrote:
>
>> I think we should have a tree like this :
>>
>> /sys/devices/system/soc/
>> /sys/devices/system/soc/unique_id<- Unified way to export an ID for all machs
> Arbitrary number of bits? Some will have a 64-bit ID, some will have 32-bit
> etc.
Yes, here is the difficulty. For example, in our case, the SoC unique ID
is 160 bits long.
Maybe it would be a better solution to get rid of this unified file, and
keep only mach specific entries? I mean :
/sys/devices/system/soc/
/sys/devices/system/soc/mach_name
/sys/devices/system/soc/foo_id
/sys/devices/system/soc/bar_id
> Should we say it's a hex string of 64 bits?
>
>> /sys/devices/system/soc/mach/
>> /sys/devices/system/soc/mach/name<- Name of the mach
>> /sys/devices/system/soc/mach/foo_id
>> /sys/devices/system/soc/mach/bar_id<- Vendors may have several/different IDs
>> to export (IDCODE for OMAP, Production ID...)
> For Ux500 we can export the stuff we print today in mach-ux500/id.c,
> put in place earlier by Rabin, I'd prefer if you hook in the new ID stuff
> there as well, since it's so little platform code, and a logical place to
> have it in.
I agree.
Regards,
Maxime
^ permalink raw reply
* [PATCH 2/7] OMAP2+: mux: Enable wakeup for wakeup enable requested pads
From: Govindraj @ 2011-03-02 10:40 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <AANLkTim8tTO5wDvzXxy8G35vYMBsXP2fJu=KHDHpw7aC@mail.gmail.com>
On Wed, Mar 2, 2011 at 10:19 AM, Varadarajan, Charulatha <charu@ti.com> wrote:
> Govind,
>
> Couple of minor comments.
>
> On Mon, Feb 28, 2011 at 20:09, Govindraj.R <govindraj.raja@ti.com> wrote:
>> For device pads which have OMAP_DEVICE_PAD_WAKEUP set (which means they
>> are wakeup capable) enable the IO-daisy wakeup capability.
>> During re-muxing avoid direct write with val as this can disturb if any
>> mux done at bootloader level so read the pad then write back.
>>
>> Also add a api to fetch the wake-up status bit is set for given omap-hwmod
>
> %s/a api/an API/
>
>> device using available mux info which is added during omap_hwmod_mux_init.
>> Wakeup status bit is needed for uart_resume_idle call from sram_idle path
>> based on wake-up event has occurred for given uart we can enable clocks back.
>>
>> Signed-off-by: Rajendra Nayak <rnayak@ti.com>
>> Signed-off-by: Govindraj.R <govindraj.raja@ti.com>
>> ---
>> ?arch/arm/mach-omap2/mux.c ? ? ? ? ? ? ? ? ? ?| ? 23 +++++++++++++++++++++++
>> ?arch/arm/mach-omap2/mux.h ? ? ? ? ? ? ? ? ? ?| ? 13 +++++++++++++
>> ?arch/arm/mach-omap2/omap_hwmod.c ? ? ? ? ? ? | ? 13 +++++++++++++
>> ?arch/arm/plat-omap/include/plat/omap_hwmod.h | ? ?1 +
>> ?4 files changed, 50 insertions(+), 0 deletions(-)
>>
>> diff --git a/arch/arm/mach-omap2/mux.c b/arch/arm/mach-omap2/mux.c
>> index 98148b6..5338b93 100644
>> --- a/arch/arm/mach-omap2/mux.c
>> +++ b/arch/arm/mach-omap2/mux.c
>> @@ -317,6 +317,24 @@ err1:
>> ? ? ? ?return NULL;
>> ?}
>>
>> +/* Gets the wakeup status of given pad from omap-hwmod */
>> +int omap_hwmod_mux_wakeup(struct omap_hwmod_mux_info *hmux)
>> +{
>> + ? ? ? int i;
>> + ? ? ? unsigned int val = -EINVAL;
>> +
>> + ? ? ? for (i = 0; i < hmux->nr_pads; i++) {
>> + ? ? ? ? ? ? ? struct omap_device_pad *pad = &hmux->pads[i];
>> +
>> + ? ? ? ? ? ? ? val = omap_mux_read(pad->partition, pad->mux->reg_offset);
>> + ? ? ? }
>> +
>> + ? ? ? if (val > 0 && val & OMAP_WAKEUP_EVENT)
>> + ? ? ? ? ? ? ? return 1;
>> + ? ? ? else
>
> No need of else here.
Yes correct.
I am resending this patch with some more modifications
to fix one more issue in the above loop.
--
Thanks,
Govindraj.R
<<SNIP>>
^ permalink raw reply
* [PATCHv5 0/3] Introduce the /proc/socinfo and use it to export OMAP data
From: Linus Walleij @ 2011-03-02 10:36 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <4D6DFE67.3020801@stericsson.com>
On Wed, Mar 2, 2011 at 9:23 AM, Maxime Coquelin
<maxime.coquelin-nonst@stericsson.com> wrote:
> I think we should have a tree like this :
>
> /sys/devices/system/soc/
> /sys/devices/system/soc/unique_id<- Unified way to export an ID for all machs
Arbitrary number of bits? Some will have a 64-bit ID, some will have 32-bit
etc.
Should we say it's a hex string of 64 bits?
> /sys/devices/system/soc/mach/
> /sys/devices/system/soc/mach/name<- Name of the mach
> /sys/devices/system/soc/mach/foo_id
> /sys/devices/system/soc/mach/bar_id<- Vendors may have several/different IDs
> to export (IDCODE for OMAP, Production ID...)
For Ux500 we can export the stuff we print today in mach-ux500/id.c,
put in place earlier by Rabin, I'd prefer if you hook in the new ID stuff
there as well, since it's so little platform code, and a logical place to
have it in.
> Linus, do you agree?
Yeah, sounds good.
Yours,
Linus Walleij
^ permalink raw reply
* MMC quirks relating to performance/lifetime.
From: Andrei Warkentin @ 2011-03-02 10:34 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <201103012011.51855.arnd@arndb.de>
On Tue, Mar 1, 2011 at 1:11 PM, Arnd Bergmann <arnd@arndb.de> wrote:
> On Tuesday 01 March 2011 19:48:17 Jens Axboe wrote:
>>
>> On 2011-02-25 07:21, Arnd Bergmann wrote:
>> > On Friday 25 February 2011, Andrei Warkentin wrote:
>> >> Yup. I understand :-). ?That's the strategy I'm going to follow. For
>> >> page_size-alignment/splitting I'm looking at the block layer now. Is
>> >> that the right approach or should I still submit a (cleaned up) patch
>> >> to mmc/card/block.c for that performance improvement.
>> >
>> > I guess it should live in block/cfq-iosched in the long run, but I don't
>> > know how easy it is to implement it there for test purposes.
>>
>> I don't think I saw the original patch(es) for this?
>
> Nobody has posted one yet, only discussions. Andrei made a patch for the
> MMC block driver to split requests in some cases, but I think the
> concept has changed enough that it's probably not useful to look at
> that patch.
>
Before the generic improvements are made to the block layer, I think
there is some value
in implementing the (simpler) ones in mmc block code, as well as
expose an mmc block quirk interface by which its easy to add complex
workarounds. Some things will never be able to completely stay above
mmc block code, for example, when splitting up smaller accesses, you
need to be careful on the Toshiba card, since the 4th consecutive 8KB
block results in the entire 32KB getting pushed into the bigger 4MB
buffer. On our platform, there are a lot of accesses in the 16KB-32KB
range which benefit from the splitting. Data collected showed
splitting more than 32KB to have adverse effect on performance (I
guess that sort of makes sense, after all, why else would the
controller treat 4 consecutive 8KB accesses as a larger access and
treat it accordingly?) On the other hand, that data was collected on
code that used reliable write for every portion of the split access,
so I'm going to have to get some new data...
^ permalink raw reply
* [PATCH v2] i2c-pxa2xx: Add PCI support for PXA I2C controller
From: Sebastian Andrzej Siewior @ 2011-03-02 10:26 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <4D6D9480.7050108@fluff.org>
The Sodaville I2C controller is almost the same as found on PXA2xx. The
difference:
- the register are at a different offset
- no slave support
The PCI probe code adds three platform devices which are probed then by
the platform code.
The X86 part also adds dummy clock defines because we don't have HW
clock support.
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Dirk Brandewie <dirk.brandewie@gmail.com>
---
* Ben Dooks | 2011-03-02 00:51:12 [+0000]:
>>diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c
>>index fc2a90e..225e9a5 100644
>>--- a/drivers/i2c/busses/i2c-pxa.c
>>+++ b/drivers/i2c/busses/i2c-pxa.c
>>@@ -38,6 +38,13 @@
>>
>> #include<asm/irq.h>
>>
>>+#ifdef CONFIG_X86
>>+#define clk_get(dev, id) NULL
>>+#define clk_put(clk) do { } while (0)
>>+#define clk_disable(clk) do { } while (0)
>>+#define clk_enable(clk) do { } while (0)
>>+#endif
>>+
>
>Maybe be better on !CONFIG_HAVE_CLOCK (or whatever it is called)
Switched to #ifndef CONFIG_HAVE_CLK
drivers/i2c/busses/Kconfig | 7 +-
drivers/i2c/busses/Makefile | 1 +
drivers/i2c/busses/i2c-pxa-pci.c | 176 ++++++++++++++++++++++++++++++++++++++
drivers/i2c/busses/i2c-pxa.c | 27 +++++-
4 files changed, 206 insertions(+), 5 deletions(-)
create mode 100644 drivers/i2c/busses/i2c-pxa-pci.c
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index 113505a..deefa13 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -525,15 +525,18 @@ config I2C_PNX
config I2C_PXA
tristate "Intel PXA2XX I2C adapter"
- depends on ARCH_PXA || ARCH_MMP
+ depends on ARCH_PXA || ARCH_MMP || (X86_32 && PCI && OF)
help
If you have devices in the PXA I2C bus, say yes to this option.
This driver can also be built as a module. If so, the module
will be called i2c-pxa.
+config I2C_PXA_PCI
+ def_bool I2C_PXA && X86_32 && PCI && OF
+
config I2C_PXA_SLAVE
bool "Intel PXA2XX I2C Slave comms support"
- depends on I2C_PXA
+ depends on I2C_PXA && !X86_32
help
Support I2C slave mode communications on the PXA I2C bus. This
is necessary for systems where the PXA may be a target on the
diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
index 9d2d0ec..e95d0bf 100644
--- a/drivers/i2c/busses/Makefile
+++ b/drivers/i2c/busses/Makefile
@@ -52,6 +52,7 @@ obj-$(CONFIG_I2C_PCA_PLATFORM) += i2c-pca-platform.o
obj-$(CONFIG_I2C_PMCMSP) += i2c-pmcmsp.o
obj-$(CONFIG_I2C_PNX) += i2c-pnx.o
obj-$(CONFIG_I2C_PXA) += i2c-pxa.o
+obj-$(CONFIG_I2C_PXA_PCI) += i2c-pxa-pci.o
obj-$(CONFIG_I2C_S3C2410) += i2c-s3c2410.o
obj-$(CONFIG_I2C_S6000) += i2c-s6000.o
obj-$(CONFIG_I2C_SH7760) += i2c-sh7760.o
diff --git a/drivers/i2c/busses/i2c-pxa-pci.c b/drivers/i2c/busses/i2c-pxa-pci.c
new file mode 100644
index 0000000..6659d26
--- /dev/null
+++ b/drivers/i2c/busses/i2c-pxa-pci.c
@@ -0,0 +1,176 @@
+/*
+ * The CE4100's I2C device is more or less the same one as found on PXA.
+ * It does not support slave mode, the register slightly moved. This PCI
+ * device provides three bars, every contains a single I2C controller.
+ */
+#include <linux/pci.h>
+#include <linux/platform_device.h>
+#include <linux/i2c/pxa-i2c.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_address.h>
+
+#define CE4100_PCI_I2C_DEVS 3
+
+struct ce4100_devices {
+ struct platform_device *pdev[CE4100_PCI_I2C_DEVS];
+};
+
+static struct platform_device *add_i2c_device(struct pci_dev *dev, int bar)
+{
+ struct platform_device *pdev;
+ struct i2c_pxa_platform_data pdata;
+ struct resource res[2];
+ struct device_node *child;
+ static int devnum;
+ int ret;
+
+ memset(&pdata, 0, sizeof(struct i2c_pxa_platform_data));
+ memset(&res, 0, sizeof(res));
+
+ res[0].flags = IORESOURCE_MEM;
+ res[0].start = pci_resource_start(dev, bar);
+ res[0].end = pci_resource_end(dev, bar);
+
+ res[1].flags = IORESOURCE_IRQ;
+ res[1].start = dev->irq;
+ res[1].end = dev->irq;
+
+ for_each_child_of_node(dev->dev.of_node, child) {
+ const void *prop;
+ struct resource r;
+ int ret;
+
+ ret = of_address_to_resource(child, 0, &r);
+ if (ret < 0)
+ continue;
+ if (r.start != res[0].start)
+ continue;
+ if (r.end != res[0].end)
+ continue;
+ if (r.flags != res[0].flags)
+ continue;
+
+ prop = of_get_property(child, "fast-mode", NULL);
+ if (prop)
+ pdata.fast_mode = 1;
+
+ break;
+ }
+
+ if (!child) {
+ dev_err(&dev->dev, "failed to match a DT node for bar %d.\n",
+ bar);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ pdev = platform_device_alloc("ce4100-i2c", devnum);
+ if (!pdev) {
+ of_node_put(child);
+ ret = -ENOMEM;
+ goto out;
+ }
+ pdev->dev.parent = &dev->dev;
+ pdev->dev.of_node = child;
+
+ ret = platform_device_add_resources(pdev, res, ARRAY_SIZE(res));
+ if (ret)
+ goto err;
+
+ ret = platform_device_add_data(pdev, &pdata, sizeof(pdata));
+ if (ret)
+ goto err;
+
+ ret = platform_device_add(pdev);
+ if (ret)
+ goto err;
+ devnum++;
+ return pdev;
+err:
+ platform_device_put(pdev);
+out:
+ return ERR_PTR(ret);
+}
+
+static int __devinit ce4100_i2c_probe(struct pci_dev *dev,
+ const struct pci_device_id *ent)
+{
+ int ret;
+ int i;
+ struct ce4100_devices *sds;
+
+ ret = pci_enable_device_mem(dev);
+ if (ret)
+ return ret;
+
+ if (!dev->dev.of_node) {
+ dev_err(&dev->dev, "Missing device tree node.\n");
+ return -EINVAL;
+ }
+ sds = kzalloc(sizeof(*sds), GFP_KERNEL);
+ if (!sds)
+ goto err_mem;
+
+ for (i = 0; i < ARRAY_SIZE(sds->pdev); i++) {
+ sds->pdev[i] = add_i2c_device(dev, i);
+ if (IS_ERR(sds->pdev[i])) {
+ while (--i >= 0)
+ platform_device_unregister(sds->pdev[i]);
+ goto err_dev_add;
+ }
+ }
+ pci_set_drvdata(dev, sds);
+ return 0;
+
+err_dev_add:
+ pci_set_drvdata(dev, NULL);
+ kfree(sds);
+err_mem:
+ pci_disable_device(dev);
+ return ret;
+}
+
+static void __devexit ce4100_i2c_remove(struct pci_dev *dev)
+{
+ struct ce4100_devices *sds;
+ unsigned int i;
+
+ sds = pci_get_drvdata(dev);
+ pci_set_drvdata(dev, NULL);
+
+ for (i = 0; i < ARRAY_SIZE(sds->pdev); i++)
+ platform_device_unregister(sds->pdev[i]);
+
+ pci_disable_device(dev);
+ kfree(sds);
+}
+
+static struct pci_device_id ce4100_i2c_devices[] __devinitdata = {
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x2e68)},
+ { },
+};
+MODULE_DEVICE_TABLE(pci, ce4100_i2c_devices);
+
+static struct pci_driver ce4100_i2c_driver = {
+ .name = "ce4100_i2c",
+ .id_table = ce4100_i2c_devices,
+ .probe = ce4100_i2c_probe,
+ .remove = __devexit_p(ce4100_i2c_remove),
+};
+
+static int __init ce4100_i2c_init(void)
+{
+ return pci_register_driver(&ce4100_i2c_driver);
+}
+module_init(ce4100_i2c_init);
+
+static void __exit ce4100_i2c_exit(void)
+{
+ pci_unregister_driver(&ce4100_i2c_driver);
+}
+module_exit(ce4100_i2c_exit);
+
+MODULE_DESCRIPTION("CE4100 PCI-I2C glue code for PXA's driver");
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Sebastian Andrzej Siewior <bigeasy@linutronix.de>");
diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c
index fc2a90e..ab59b7e 100644
--- a/drivers/i2c/busses/i2c-pxa.c
+++ b/drivers/i2c/busses/i2c-pxa.c
@@ -38,6 +38,13 @@
#include <asm/irq.h>
+#ifndef CONFIG_HAVE_CLK
+#define clk_get(dev, id) NULL
+#define clk_put(clk) do { } while (0)
+#define clk_disable(clk) do { } while (0)
+#define clk_enable(clk) do { } while (0)
+#endif
+
struct pxa_reg_layout {
u32 ibmr;
u32 idbr;
@@ -49,6 +56,7 @@ struct pxa_reg_layout {
enum pxa_i2c_types {
REGS_PXA2XX,
REGS_PXA3XX,
+ REGS_CE4100,
};
/*
@@ -69,11 +77,19 @@ static struct pxa_reg_layout pxa_reg_layout[] = {
.isr = 0x18,
.isar = 0x20,
},
+ [REGS_CE4100] = {
+ .ibmr = 0x14,
+ .idbr = 0x0c,
+ .icr = 0x00,
+ .isr = 0x04,
+ /* no isar register */
+ },
};
static const struct platform_device_id i2c_pxa_id_table[] = {
{ "pxa2xx-i2c", REGS_PXA2XX },
{ "pxa3xx-pwri2c", REGS_PXA3XX },
+ { "ce4100-i2c", REGS_CE4100 },
{ },
};
MODULE_DEVICE_TABLE(platform, i2c_pxa_id_table);
@@ -442,7 +458,8 @@ static void i2c_pxa_reset(struct pxa_i2c *i2c)
writel(I2C_ISR_INIT, _ISR(i2c));
writel(readl(_ICR(i2c)) & ~ICR_UR, _ICR(i2c));
- writel(i2c->slave_addr, _ISAR(i2c));
+ if (i2c->reg_isar)
+ writel(i2c->slave_addr, _ISAR(i2c));
/* set control register values */
writel(I2C_ICR_INIT | (i2c->fast_mode ? ICR_FM : 0), _ICR(i2c));
@@ -1074,7 +1091,8 @@ static int i2c_pxa_probe(struct platform_device *dev)
i2c->reg_idbr = i2c->reg_base + pxa_reg_layout[i2c_type].idbr;
i2c->reg_icr = i2c->reg_base + pxa_reg_layout[i2c_type].icr;
i2c->reg_isr = i2c->reg_base + pxa_reg_layout[i2c_type].isr;
- i2c->reg_isar = i2c->reg_base + pxa_reg_layout[i2c_type].isar;
+ if (i2c_type != REGS_CE4100)
+ i2c->reg_isar = i2c->reg_base + pxa_reg_layout[i2c_type].isar;
i2c->iobase = res->start;
i2c->iosize = resource_size(res);
@@ -1113,7 +1131,10 @@ static int i2c_pxa_probe(struct platform_device *dev)
i2c->adap.algo_data = i2c;
i2c->adap.dev.parent = &dev->dev;
- ret = i2c_add_numbered_adapter(&i2c->adap);
+ if (i2c_type == REGS_CE4100)
+ ret = i2c_add_adapter(&i2c->adap);
+ else
+ ret = i2c_add_numbered_adapter(&i2c->adap);
if (ret < 0) {
printk(KERN_INFO "I2C: Failed to add bus\n");
goto eadapt;
--
1.7.4
Sebastian
^ permalink raw reply related
* Store buffer and l2x0_cache_sync
From: Catalin Marinas @ 2011-03-02 10:16 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <AANLkTi=CzrVuqA0V-_kRnLWOHVw7aOzDpuJfvSD9Vdhx@mail.gmail.com>
On Wed, 2011-03-02 at 01:25 +0000, Colin Cross wrote:
> l2x0_cache_sync on a PL310 has no wait after the writel_relaxed to the
> L2X0_CACHE_SYNC register, because PL310 cache operations are atomic.
> Doesn't the cpu store buffer still need to be flushed after the
> register write, either with a dsb or a dummy read?
You usually need the PL310 flush/sync (Device writes) to be ordered with
other Device write (for starting DMA for example) but since both are
Device accesses, they are ordered by the processor already.
In general it depends on what the device does. A write to a device isn't
guaranteed to change its state, in which case a read back would be
needed (rather than a DSB). My understanding of the PL310 is that the
cache sync write stalls the CPU write buffer until the operation
completed. So subsequent device writes in the buffer would wait for the
cache sync.
--
Catalin
^ permalink raw reply
* Fwd: [RFC] MMC: error handling improvements
From: Linus Walleij @ 2011-03-02 10:12 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <a8453bae3ced14c4c325d1782be92e24.squirrel@www.codeaurora.org>
Thanks for writing back Murali!
2011/3/1 Murali Krishna Palnati <palnatim@codeaurora.org>:
> Though the bulk of the MSM SDCC controller is designed around PL180, there
> are still some modifications to include flow control, SDIO support,
We have these fixes in the U300/Ux500 version of MMCI as well, I suspect
it's nothing more than altering which bits are to be poked into which
registers.
> Data
> Mover interface (DMA engine on Qualcomm MSMs) etc. Support/ability to talk
> to the Data Mover is one of the main differences when compared to original
> PL180 prime cell.
The main work would be to switch the DMA engine in MSM to using
the DMA engine in drivers/dma. This is one thing we do to avoid the
proliferation of DMA engine code in arch/arm/*, and we very early
started to use that framework for U300 and Ux500 and I must say that
it has payed off well for us, now we have much nicer interfaces and more
review than any of the custom engines under arch/arm/*.
It's some upfront work but I think it would benefit you if you could
do this.
Yours,
Linus Walleij
^ permalink raw reply
* [patch v1 2/3] arm: pmu: support pmu irq routed from CTI
From: Ming Lei @ 2011-03-02 10:10 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1299016524.5379.27.camel@jazzbox>
Hi Will,
2011/3/2 Will Deacon <will.deacon@arm.com>:
> Hi Ming Lei,
>
> It's good to see somebody looking at OMAP4 since I've been hearing from
> people having trouble getting perf going on the PandaBoard.
>
>
> On Tue, 2011-03-01 at 16:58 +0000, tom.leiming at gmail.com wrote:
>> From: Ming Lei <tom.leiming@gmail.com>
>>
>> This patch introduces pmu_platform_data struct to
>> support pmu irq routed from CTI, such as implemented
>> on OMAP4.
>>
>> Generally speaking, clearing cti irq should be done in
>> irq handler, also enabling cti module after calling
>> request_irq and disabling cti module before calling
>> free_irq.
>>
>> Signed-off-by: Ming Lei <tom.leiming@gmail.com>
>> ---
>> ?arch/arm/include/asm/pmu.h ? | ? 12 +++++++++
>> ?arch/arm/kernel/perf_event.c | ? 57 ++++++++++++++++++++++++++++++-----------
>> ?2 files changed, 53 insertions(+), 16 deletions(-)
>>
>> diff --git a/arch/arm/include/asm/pmu.h b/arch/arm/include/asm/pmu.h
>> index 7544ce6..6162aaf 100644
>> --- a/arch/arm/include/asm/pmu.h
>> +++ b/arch/arm/include/asm/pmu.h
>> @@ -13,20 +13,32 @@
>> ?#define __ARM_PMU_H__
>>
>> ?#include <linux/interrupt.h>
>> +#include <asm/cti.h>
>>
>> ?enum arm_pmu_type {
>> ? ? ? ? ARM_PMU_DEVICE_CPU ? ? ?= 0,
>> ? ? ? ? ARM_NUM_PMU_DEVICES,
>> ?};
>>
>> +#define MAX_CTI_NUM ?4
>
> Why is this in the PMU header file rather than the CTI one?
>
>> ?/*
>> ? * struct arm_pmu_platdata - ARM PMU platform data
>> ? *
>> + * @use_cti_irq: pmu irq is routed from cti
>> + * @cti_cnt: cti counts used for pmu irq routing
>> + * @cti: cti instances used to help access cti registers
>> ? * @handle_irq: an optional handler which will be called from the interrupt and
>> ? * passed the address of the low level handler, and can be used to implement
>> ? * any platform specific handling before or after calling it.
>> + *
>> + * If pmu irq is routed from CTI, @use_cti_irq, @cti_cnt and
>> + * @cti must be initialized and passed to pmu driver.
>> ? */
>> ?struct arm_pmu_platdata {
>> + ? ? ? int use_cti_irq;
>> + ? ? ? int cti_cnt;
>> + ? ? ? struct cti cti[MAX_CTI_NUM];
>> +
>> ? ? ? ? irqreturn_t (*handle_irq)(int irq, void *dev,
>> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? irq_handler_t pmu_handler);
>> ?};
>> diff --git a/arch/arm/kernel/perf_event.c b/arch/arm/kernel/perf_event.c
>> index 22e194eb..9027a8f 100644
>> --- a/arch/arm/kernel/perf_event.c
>> +++ b/arch/arm/kernel/perf_event.c
>> @@ -377,18 +377,39 @@ validate_group(struct perf_event *event)
>> ? ? ? ? return 0;
>> ?}
>>
>> -static irqreturn_t armpmu_platform_irq(int irq, void *dev)
>> +static inline int cti_irq(struct arm_pmu_platdata *data)
>> ?{
>> - ? ? ? struct arm_pmu_platdata *plat = dev_get_platdata(&pmu_device->dev);
>> + ? ? ? return data && data->use_cti_irq;
>> +}
>> +
>> +static inline struct cti *irq_to_cti(struct arm_pmu_platdata *data,
>> + ? ? ? int irq)
>> +{
>> + ? ? ? int idx;
>>
>> - ? ? ? return plat->handle_irq(irq, dev, armpmu->handle_irq);
>> + ? ? ? for(idx = 0; idx < data->cti_cnt; idx++)
>> + ? ? ? ? ? ? ? if (data->cti[idx].irq == irq)
>> + ? ? ? ? ? ? ? ? ? ? ? return &data->cti[idx];
>> + ? ? ? return NULL;
>> +}
>
> Hmm, since OMAP is the only platform using this, I'm not especially
> happy sticking this directly in the PMU code.
>
>> +static inline irqreturn_t armpmu_handle_irq(int irq_num, void *dev)
>> +{
>> + ? ? ? struct arm_pmu_platdata *plat = dev;
>> +
>> + ? ? ? if (cti_irq(plat))
>> + ? ? ? ? ? ? ? cti_irq_ack(irq_to_cti(plat, irq_num));
>> +
>> + ? ? ? if (plat && plat->handle_irq)
>> + ? ? ? ? ? ? ? return plat->handle_irq(irq_num, dev, armpmu->handle_irq);
>> + ? ? ? else
>> + ? ? ? ? ? ? ? return armpmu->handle_irq(irq_num, NULL);
>> ?}
>>
> You can use the new arm_pmu_platdata.handle_irq function to register
> your own IRQ callback. I don't think we should define the handler here.
>
>> ?static int
>> ?armpmu_reserve_hardware(void)
>> ?{
>> ? ? ? ? struct arm_pmu_platdata *plat;
>> - ? ? ? irq_handler_t handle_irq;
>> ? ? ? ? int i, err = -ENODEV, irq;
>>
>> ? ? ? ? pmu_device = reserve_pmu(ARM_PMU_DEVICE_CPU);
>> @@ -399,11 +420,7 @@ armpmu_reserve_hardware(void)
>>
>> ? ? ? ? init_pmu(ARM_PMU_DEVICE_CPU);
>>
>> - ? ? ? plat = dev_get_platdata(&pmu_device->dev);
>> - ? ? ? if (plat && plat->handle_irq)
>> - ? ? ? ? ? ? ? handle_irq = armpmu_platform_irq;
>> - ? ? ? else
>> - ? ? ? ? ? ? ? handle_irq = armpmu->handle_irq;
>> + ? ? ? plat = platform_get_drvdata(pmu_device);
>>
>> ? ? ? ? if (pmu_device->num_resources < 1) {
>> ? ? ? ? ? ? ? ? pr_err("no irqs for PMUs defined\n");
>> @@ -415,21 +432,25 @@ armpmu_reserve_hardware(void)
>> ? ? ? ? ? ? ? ? if (irq < 0)
>> ? ? ? ? ? ? ? ? ? ? ? ? continue;
>>
>> - ? ? ? ? ? ? ? err = request_irq(irq, handle_irq,
>> + ? ? ? ? ? ? ? err = request_irq(irq, armpmu_handle_irq,
>> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? IRQF_DISABLED | IRQF_NOBALANCING,
>> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? "armpmu", NULL);
>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? "armpmu", plat);
>> ? ? ? ? ? ? ? ? if (err) {
>> ? ? ? ? ? ? ? ? ? ? ? ? pr_warning("unable to request IRQ%d for ARM perf "
>> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? "counters\n", irq);
>> ? ? ? ? ? ? ? ? ? ? ? ? break;
>> - ? ? ? ? ? ? ? }
>> + ? ? ? ? ? ? ? } else if (cti_irq(plat))
>> + ? ? ? ? ? ? ? ? ? ? ? cti_enable(irq_to_cti(plat, irq));
>> ? ? ? ? }
>>
>> ? ? ? ? if (err) {
>> ? ? ? ? ? ? ? ? for (i = i - 1; i >= 0; --i) {
>> ? ? ? ? ? ? ? ? ? ? ? ? irq = platform_get_irq(pmu_device, i);
>> - ? ? ? ? ? ? ? ? ? ? ? if (irq >= 0)
>> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? free_irq(irq, NULL);
>> + ? ? ? ? ? ? ? ? ? ? ? if (irq >= 0) {
>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? if (cti_irq(plat))
>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? cti_disable(irq_to_cti(plat, irq));
>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? free_irq(irq, plat);
>> + ? ? ? ? ? ? ? ? ? ? ? }
>> ? ? ? ? ? ? ? ? }
>> ? ? ? ? ? ? ? ? release_pmu(pmu_device);
>> ? ? ? ? ? ? ? ? pmu_device = NULL;
>> @@ -442,11 +463,15 @@ static void
>> ?armpmu_release_hardware(void)
>> ?{
>> ? ? ? ? int i, irq;
>> + ? ? ? struct arm_pmu_platdata *plat = platform_get_drvdata(pmu_device);
>>
>> ? ? ? ? for (i = pmu_device->num_resources - 1; i >= 0; --i) {
>> ? ? ? ? ? ? ? ? irq = platform_get_irq(pmu_device, i);
>> - ? ? ? ? ? ? ? if (irq >= 0)
>> - ? ? ? ? ? ? ? ? ? ? ? free_irq(irq, NULL);
>> + ? ? ? ? ? ? ? if (irq >= 0) {
>> + ? ? ? ? ? ? ? ? ? ? ? if (cti_irq(plat))
>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? cti_disable(irq_to_cti(plat, irq));
>> + ? ? ? ? ? ? ? ? ? ? ? free_irq(irq, plat);
>> + ? ? ? ? ? ? ? }
>> ? ? ? ? }
>> ? ? ? ? armpmu->stop();
>>
> Right, so I think a better way to do this is to put all the CTI stuff in
> its own file. Whether this lives in the OMAP BSP is up to you (perhaps
> the best place for it at the moment, until other platforms use it too).
>
> Then we can add ->enable and ->disable hooks in the platdata which are
> not CTI-specific and may also be useful for other platforms and PMU
> implementations.
>
> Does that work for you?
Good, I will move cti code out of perf_event.c and introduce
.enable_irq and .disable_irq into platdata, which makes perf_event.c
cleaner.
thanks,
--
Lei Ming
^ permalink raw reply
* [PATCH 6/7] OMAP: Serial: Allow UART parameters to be configured from board file
From: Govindraj @ 2011-03-02 10:07 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <8ab9882cd92792e9bf2b836c0ec9c7fe@mail.gmail.com>
On Wed, Mar 2, 2011 at 1:49 PM, Sricharan R <r.sricharan@ti.com> wrote:
> Hi,
>>-----Original Message-----
>>From: Govindraj [mailto:govindraj.ti at gmail.com]
>>Sent: Wednesday, March 02, 2011 1:11 PM
>>To: Sricharan R
>>Cc: Govindraj.R; linux-omap at vger.kernel.org;
> linux-serial at vger.kernel.org;
>>linux-arm-kernel at lists.infradead.org; Jon Hunter; Tony Lindgren; Benoit
>>Cousson; Kevin Hilman; Paul Walmsley; Rajendra Nayak; Deepak Kattungal
>>Subject: Re: [PATCH 6/7] OMAP: Serial: Allow UART parameters to be
>>configured from board file
>>
>>On Wed, Mar 2, 2011 at 12:46 AM, Sricharan R <r.sricharan@ti.com> wrote:
>>> Hi,
>>>>diff --git a/arch/arm/mach-omap2/serial.c
> b/arch/arm/mach-omap2/serial.c
>>>>index 755f4aa..530e9e3 100644
>>>>--- a/arch/arm/mach-omap2/serial.c
>>>>+++ b/arch/arm/mach-omap2/serial.c
>>>>@@ -44,6 +44,15 @@
>>>>
>>>> static int omap_uart_con_id __initdata = -1;
>>>>
>>>>+static struct omap_uart_port_info omap_serial_default_info[] = {
>>>>+ ? ? ?{
>>>>+ ? ? ? ? ? ? ?.dma_enabled ? ?= 0,
>>>>+ ? ? ? ? ? ? ?.dma_rx_buf_size = DEFAULT_RXDMA_BUFSIZE,
>>>>+ ? ? ? ? ? ? ?.dma_rx_timeout = DEFAULT_RXDMA_TIMEOUT,
>>>>+ ? ? ? ? ? ? ?.idle_timeout ? = DEFAULT_IDLE_TIMEOUT,
>>>>+ ? ? ?},
>>>>+};
>>>>+
>>>> static int uart_idle_hwmod(struct omap_device *od)
>>>> {
>>>> ? ? ? omap_hwmod_idle(od->hwmods[0]);
>>>>@@ -66,6 +75,54 @@ static struct omap_device_pm_latency
>>> omap_uart_latency[]
>>>>= {
>>>> ? ? ? },
>>>> };
>>>>
>>>>+#ifdef CONFIG_OMAP_MUX
>>>>+static struct omap_device_pad default_serial0_pads[] __initdata = {
>>>>+ ? ? ?{
>>>>+ ? ? ? ? ? ? ?.name ? = "uart1_rx.uart1_rx",
>>>>+ ? ? ? ? ? ? ?.flags ?= OMAP_DEVICE_PAD_REMUX |
> OMAP_DEVICE_PAD_WAKEUP,
>>>>+ ? ? ? ? ? ? ?.enable = OMAP_MUX_MODE0,
>>>>+ ? ? ?},
>>>>+};
>>>>+
>>>>+static struct omap_device_pad default_serial1_pads[] __initdata = {
>>>>+ ? ? ?{
>>>>+ ? ? ? ? ? ? ?.name ? = "uart2_rx.uart2_rx",
>>>>+ ? ? ? ? ? ? ?.flags ?= OMAP_DEVICE_PAD_REMUX |
> OMAP_DEVICE_PAD_WAKEUP,
>>>>+ ? ? ? ? ? ? ?.enable = OMAP_MUX_MODE0,
>>>>+ ? ? ?},
>>>>+};
>>>>+
>>>>+static struct omap_device_pad default_serial2_pads[] __initdata = {
>>>>+ ? ? ?{
>>>>+ ? ? ? ? ? ? ?.name ? = "uart3_rx_irrx.uart3_rx_irrx",
>>>>+ ? ? ? ? ? ? ?.flags ?= OMAP_DEVICE_PAD_REMUX |
> OMAP_DEVICE_PAD_WAKEUP,
>>>>+ ? ? ? ? ? ? ?.enable = OMAP_MUX_MODE0,
>>>>+ ? ? ?},
>>>>+};
>>>>+
>>>>+static struct omap_device_pad default_omap36xx_serial3_pads[]
> __initdata
>>> =
>>>>{
>>>>+ ? ? ?{
>>>>+ ? ? ? ? ? ? ?.name ? = "gpmc_wait3.uart4_rx",
>>>>+ ? ? ? ? ? ? ?.flags ?= OMAP_DEVICE_PAD_REMUX |
> OMAP_DEVICE_PAD_WAKEUP,
>>>>+ ? ? ? ? ? ? ?.enable = OMAP_MUX_MODE2,
>>>>+ ? ? ?},
>>>>+};
>>>>+
>>>>+static struct omap_device_pad default_omap4_serial3_pads[] __initdata
> =
>>> {
>>>>+ ? ? ?{
>>>>+ ? ? ? ? ? ? ?.name ? = "uart4_rx.uart4_rx",
>>>>+ ? ? ? ? ? ? ?.flags ?= OMAP_DEVICE_PAD_REMUX |
> OMAP_DEVICE_PAD_WAKEUP,
>>>>+ ? ? ? ? ? ? ?.enable = OMAP_MUX_MODE0,
>>>>+ ? ? ?},
>>>>+};
>>> Here only the UART RX pins are muxed, so what about the cts, rts, tx
>>pins?
>>
>>The intention here is to enable wakeup capabilities for uart rx pad.
>>
>>AFAIK most of the boards are currently dependent on bootloader for
>>uart-muxing if any board is not dependent on bootloader then we
>>can use omap_serial_init_port along with board_mux_info from board.
>>
> Yes. The idea is to be independent of the bootloaders for mux settings.
>
>>Prior to this change uart wakeup is based on rx_pad and we were
> populating
>>offset and using omap_ctrl api's to read/write which is cleaned up now.
>>Most of boards are dependent on uart-rx wakeup to avoid breaking any
>>board support we
>>are using omap_serial_init by filling default values, which provides
>>us with same
>>environment but with right approach towards handling mux data with a
>>handshake with
>>hwmod framework.
>>
> Now, in this change only the RX pin is configured. So if some board uses
> omap_serial_init then only the RX is going to be configured.
> How will they configure the rest of the pins?
They should call omap_serial_init_port to configure each individual uart with
mux_info filled and not use omap_serial_init.
If any board is not dependent for mux from u-boot then they use above said
init_port func.
> They cannot call omap_serial_init_port after this just to configure the
> rest of the mux pins( cts, rts, tx).
No. You need to use either omap_serial_init_port or omap_serial_init
you cannot call both apis from board file please refer to both func
documentation.
Also please note i am not configuring all uart pins for pullups and pull downs
with this patch series and its not related to this patch series.
I am only enabling wakeup-enable pin for rx as it was done before.
> So data which is passed from omap_serial_init should have the
> configuration
> for all the pins, and this default data should be consistent across
> atleast
> some boards, so that they can use this. This will reduce the data
> duplication across board files.
>
> If this is not true, then all the pads can be configured from the board
> files itself using omap_serial_init_port and you can set the required
> RX wakeup capability there as well.
>
Yes that be done but currently but that is not in my intention here
with my patch
I just want to retain rx wakeup by default to avoid breaking support
for any board.
Adding pin mux for each individual pin is a separate activity where I also
need access to various boards So I am leaving that to developers who
want to configure
for the corresponding boards using init_port api.
Removing mux from u-boot level and adding it to board file is beyond
the scope of this
patch series and is a separate topic of discussion, as current patch series
assumes that uarts are muxed from u-boot level and needs to only enable wakeup
capability for rx-pin.
Hope this clarifies.
--
Thanks,
Govindraj.R
>>So if any board needs specific mux they can go ahead and add required
>>mux data in
>>board file and use map_serial_init_port instead of current
>>omap_serial_init.
>>
>>
>>> Is it consistent that across all socs that only UART3 would have
>>UART/IRDA
>>> functions capability so that serial2 pads can always be called
> "rx_irxx"
>>> ?.
>>
>>Yes from OMAP2420 to OMAP4430 uart3 can used as irda.
>>
> Ok.
>>--
>>Thanks,
>>Govindraj.R
>
^ permalink raw reply
* [PATCH V5 6/6] ARM: imx53_loco: add esdhc device support
From: Richard Zhu @ 2011-03-02 10:04 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1299060283-6404-1-git-send-email-Hong-Xing.Zhu@freescale.com>
Signed-off-by: Richard Zhao <richard.zhao@freescale.com>
Acked-by: Wolfram Sang <w.sang@pengutronix.de>
---
arch/arm/mach-mx5/Kconfig | 1 +
arch/arm/mach-mx5/board-mx53_loco.c | 2 ++
2 files changed, 3 insertions(+), 0 deletions(-)
diff --git a/arch/arm/mach-mx5/Kconfig b/arch/arm/mach-mx5/Kconfig
index f065a0d..a72c833 100644
--- a/arch/arm/mach-mx5/Kconfig
+++ b/arch/arm/mach-mx5/Kconfig
@@ -162,6 +162,7 @@ config MACH_MX53_LOCO
select IMX_HAVE_PLATFORM_IMX2_WDT
select IMX_HAVE_PLATFORM_IMX_I2C
select IMX_HAVE_PLATFORM_IMX_UART
+ select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
help
Include support for MX53 LOCO platform. This includes specific
configurations for the board and its peripherals.
diff --git a/arch/arm/mach-mx5/board-mx53_loco.c b/arch/arm/mach-mx5/board-mx53_loco.c
index 160899e..0a18f8d 100644
--- a/arch/arm/mach-mx5/board-mx53_loco.c
+++ b/arch/arm/mach-mx5/board-mx53_loco.c
@@ -213,6 +213,8 @@ static void __init mx53_loco_board_init(void)
imx53_add_imx2_wdt(0, NULL);
imx53_add_imx_i2c(0, &mx53_loco_i2c_data);
imx53_add_imx_i2c(1, &mx53_loco_i2c_data);
+ imx53_add_sdhci_esdhc_imx(0, NULL);
+ imx53_add_sdhci_esdhc_imx(2, NULL);
}
static void __init mx53_loco_timer_init(void)
--
1.7.1
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox