From: Anton Vorontsov <avorontsov@ru.mvista.com>
To: Pierre Ossman <drzeus-mmc@drzeus.cx>
Cc: linuxppc-dev@ozlabs.org,
David Brownell <dbrownell@users.sourceforge.net>,
linux-kernel@vger.kernel.org
Subject: [PATCH v2] mmc: Add mmc_vddrange_to_ocrmask() helper function
Date: Wed, 26 Nov 2008 22:54:17 +0300 [thread overview]
Message-ID: <20081126195417.GA26264@oksana.dev.rtsoft.ru> (raw)
In-Reply-To: <20081108215537.12cdf5f6@mjolnir.drzeus.cx>
This function sets the OCR mask bits according to provided voltage
ranges. Will be used by the mmc_spi OpenFirmware bindings.
Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
---
Hi Pierre,
Sorry for the delay.
On Sat, Nov 08, 2008 at 09:55:37PM +0100, Pierre Ossman wrote:
> On Thu, 30 Oct 2008 22:56:32 +0300
> Anton Vorontsov <avorontsov@ru.mvista.com> wrote:
>
> > +/**
> > + * mmc_vddrange_to_ocrmask - Convert a voltage range to the OCR mask
> > + * @vdd_min: minimum voltage value (mV)
> > + * @vdd_max: maximum voltage value (mV)
> > + * @mask: pointer to the mask
> > + *
>
> Why the pointer? Why not let the caller handle the aggregation? That
> would be a lot safer.
Yeah, makes sense. Now the function returns OCR mask, or 0 on error.
> > + /* fill the mask, from max bit to min bit */
> > + while (vdd_max >= vdd_min)
> > + *mask |= 1 << vdd_max--;
> > + return 0;
>
> Many cards get a bit uppity with a single bit set. If possible, try to
> make this function set two bits when the voltage is right on the
> boundary (e.g. 3.3V).
Something like this patch (the boundary cases are documented now)?
p.s. If the patch is OK I'll respin the whole patchset.
drivers/mmc/core/core.c | 75 ++++++++++++++++++++++++++++++++++++++++++++++
include/linux/mmc/core.h | 2 +
2 files changed, 77 insertions(+), 0 deletions(-)
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 044d84e..1673765 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -20,6 +20,7 @@
#include <linux/err.h>
#include <linux/leds.h>
#include <linux/scatterlist.h>
+#include <linux/log2.h>
#include <linux/mmc/card.h>
#include <linux/mmc/host.h>
@@ -444,6 +445,80 @@ void mmc_set_bus_width(struct mmc_host *host, unsigned int width)
mmc_set_ios(host);
}
+/**
+ * mmc_vdd_to_ocrbitnum - Convert a voltage to the OCR bit number
+ * @vdd: voltage (mV)
+ * @low_bits: prefer low bits in boundary cases
+ *
+ * This function returns the OCR bit number according to the provided @vdd
+ * value. If conversion is not possible a negative errno value returned.
+ *
+ * Depending on the @low_bits flag the function prefers low or high OCR bits
+ * on boundary voltages. For example,
+ * with @low_bits = true, 3300 mV translates to ilog2(MMC_VDD_32_33);
+ * with @low_bits = false, 3300 mV translates to ilog2(MMC_VDD_33_34);
+ *
+ * Any value in the [1951:1999] range translates to the ilog2(MMC_VDD_20_21).
+ */
+static int mmc_vdd_to_ocrbitnum(int vdd, bool low_bits)
+{
+ const int max_bit = ilog2(MMC_VDD_35_36);
+ int bit;
+
+ if (vdd < 1650 || vdd > 3600)
+ return -EINVAL;
+
+ if (vdd >= 1650 && vdd <= 1950)
+ return ilog2(MMC_VDD_165_195);
+
+ if (low_bits)
+ vdd -= 1;
+
+ /* Base 2000 mV, step 100 mV, bit's base 8. */
+ bit = (vdd - 2000) / 100 + 8;
+ if (bit > max_bit)
+ return max_bit;
+ return bit;
+}
+
+/**
+ * mmc_vddrange_to_ocrmask - Convert a voltage range to the OCR mask
+ * @vdd_min: minimum voltage value (mV)
+ * @vdd_max: maximum voltage value (mV)
+ *
+ * This function returns the OCR mask bits according to the provided @vdd_min
+ * and @vdd_max values. If conversion is not possible the function returns 0.
+ *
+ * Notes wrt boundary cases:
+ * This function sets the OCR bits for all boundary voltages, for example
+ * [3300:3400] range is translated to MMC_VDD_32_33 | MMC_VDD_33_34 |
+ * MMC_VDD_34_35 mask.
+ */
+u32 mmc_vddrange_to_ocrmask(int vdd_min, int vdd_max)
+{
+ u32 mask = 0;
+
+ if (vdd_max < vdd_min)
+ return 0;
+
+ /* Prefer high bits for the boundary vdd_max values. */
+ vdd_max = mmc_vdd_to_ocrbitnum(vdd_max, false);
+ if (vdd_max < 0)
+ return 0;
+
+ /* Prefer low bits for the boundary vdd_min values. */
+ vdd_min = mmc_vdd_to_ocrbitnum(vdd_min, true);
+ if (vdd_min < 0)
+ return 0;
+
+ /* Fill the mask, from max bit to min bit. */
+ while (vdd_max >= vdd_min)
+ mask |= 1 << vdd_max--;
+
+ return mask;
+}
+EXPORT_SYMBOL(mmc_vddrange_to_ocrmask);
+
/*
* Mask off any voltages we don't support and select
* the lowest voltage
diff --git a/include/linux/mmc/core.h b/include/linux/mmc/core.h
index 143cebf..7ac8b50 100644
--- a/include/linux/mmc/core.h
+++ b/include/linux/mmc/core.h
@@ -151,4 +151,6 @@ static inline void mmc_claim_host(struct mmc_host *host)
__mmc_claim_host(host, NULL);
}
+extern u32 mmc_vddrange_to_ocrmask(int vdd_min, int vdd_max);
+
#endif
--
1.5.6.5
WARNING: multiple messages have this Message-ID (diff)
From: Anton Vorontsov <avorontsov@ru.mvista.com>
To: Pierre Ossman <drzeus-mmc@drzeus.cx>
Cc: linux-kernel@vger.kernel.org, linuxppc-dev@ozlabs.org,
David Brownell <dbrownell@users.sourceforge.net>,
Grant Likely <grant.likely@secretlab.ca>
Subject: [PATCH v2] mmc: Add mmc_vddrange_to_ocrmask() helper function
Date: Wed, 26 Nov 2008 22:54:17 +0300 [thread overview]
Message-ID: <20081126195417.GA26264@oksana.dev.rtsoft.ru> (raw)
In-Reply-To: <20081108215537.12cdf5f6@mjolnir.drzeus.cx>
This function sets the OCR mask bits according to provided voltage
ranges. Will be used by the mmc_spi OpenFirmware bindings.
Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
---
Hi Pierre,
Sorry for the delay.
On Sat, Nov 08, 2008 at 09:55:37PM +0100, Pierre Ossman wrote:
> On Thu, 30 Oct 2008 22:56:32 +0300
> Anton Vorontsov <avorontsov@ru.mvista.com> wrote:
>
> > +/**
> > + * mmc_vddrange_to_ocrmask - Convert a voltage range to the OCR mask
> > + * @vdd_min: minimum voltage value (mV)
> > + * @vdd_max: maximum voltage value (mV)
> > + * @mask: pointer to the mask
> > + *
>
> Why the pointer? Why not let the caller handle the aggregation? That
> would be a lot safer.
Yeah, makes sense. Now the function returns OCR mask, or 0 on error.
> > + /* fill the mask, from max bit to min bit */
> > + while (vdd_max >= vdd_min)
> > + *mask |= 1 << vdd_max--;
> > + return 0;
>
> Many cards get a bit uppity with a single bit set. If possible, try to
> make this function set two bits when the voltage is right on the
> boundary (e.g. 3.3V).
Something like this patch (the boundary cases are documented now)?
p.s. If the patch is OK I'll respin the whole patchset.
drivers/mmc/core/core.c | 75 ++++++++++++++++++++++++++++++++++++++++++++++
include/linux/mmc/core.h | 2 +
2 files changed, 77 insertions(+), 0 deletions(-)
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 044d84e..1673765 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -20,6 +20,7 @@
#include <linux/err.h>
#include <linux/leds.h>
#include <linux/scatterlist.h>
+#include <linux/log2.h>
#include <linux/mmc/card.h>
#include <linux/mmc/host.h>
@@ -444,6 +445,80 @@ void mmc_set_bus_width(struct mmc_host *host, unsigned int width)
mmc_set_ios(host);
}
+/**
+ * mmc_vdd_to_ocrbitnum - Convert a voltage to the OCR bit number
+ * @vdd: voltage (mV)
+ * @low_bits: prefer low bits in boundary cases
+ *
+ * This function returns the OCR bit number according to the provided @vdd
+ * value. If conversion is not possible a negative errno value returned.
+ *
+ * Depending on the @low_bits flag the function prefers low or high OCR bits
+ * on boundary voltages. For example,
+ * with @low_bits = true, 3300 mV translates to ilog2(MMC_VDD_32_33);
+ * with @low_bits = false, 3300 mV translates to ilog2(MMC_VDD_33_34);
+ *
+ * Any value in the [1951:1999] range translates to the ilog2(MMC_VDD_20_21).
+ */
+static int mmc_vdd_to_ocrbitnum(int vdd, bool low_bits)
+{
+ const int max_bit = ilog2(MMC_VDD_35_36);
+ int bit;
+
+ if (vdd < 1650 || vdd > 3600)
+ return -EINVAL;
+
+ if (vdd >= 1650 && vdd <= 1950)
+ return ilog2(MMC_VDD_165_195);
+
+ if (low_bits)
+ vdd -= 1;
+
+ /* Base 2000 mV, step 100 mV, bit's base 8. */
+ bit = (vdd - 2000) / 100 + 8;
+ if (bit > max_bit)
+ return max_bit;
+ return bit;
+}
+
+/**
+ * mmc_vddrange_to_ocrmask - Convert a voltage range to the OCR mask
+ * @vdd_min: minimum voltage value (mV)
+ * @vdd_max: maximum voltage value (mV)
+ *
+ * This function returns the OCR mask bits according to the provided @vdd_min
+ * and @vdd_max values. If conversion is not possible the function returns 0.
+ *
+ * Notes wrt boundary cases:
+ * This function sets the OCR bits for all boundary voltages, for example
+ * [3300:3400] range is translated to MMC_VDD_32_33 | MMC_VDD_33_34 |
+ * MMC_VDD_34_35 mask.
+ */
+u32 mmc_vddrange_to_ocrmask(int vdd_min, int vdd_max)
+{
+ u32 mask = 0;
+
+ if (vdd_max < vdd_min)
+ return 0;
+
+ /* Prefer high bits for the boundary vdd_max values. */
+ vdd_max = mmc_vdd_to_ocrbitnum(vdd_max, false);
+ if (vdd_max < 0)
+ return 0;
+
+ /* Prefer low bits for the boundary vdd_min values. */
+ vdd_min = mmc_vdd_to_ocrbitnum(vdd_min, true);
+ if (vdd_min < 0)
+ return 0;
+
+ /* Fill the mask, from max bit to min bit. */
+ while (vdd_max >= vdd_min)
+ mask |= 1 << vdd_max--;
+
+ return mask;
+}
+EXPORT_SYMBOL(mmc_vddrange_to_ocrmask);
+
/*
* Mask off any voltages we don't support and select
* the lowest voltage
diff --git a/include/linux/mmc/core.h b/include/linux/mmc/core.h
index 143cebf..7ac8b50 100644
--- a/include/linux/mmc/core.h
+++ b/include/linux/mmc/core.h
@@ -151,4 +151,6 @@ static inline void mmc_claim_host(struct mmc_host *host)
__mmc_claim_host(host, NULL);
}
+extern u32 mmc_vddrange_to_ocrmask(int vdd_min, int vdd_max);
+
#endif
--
1.5.6.5
next prev parent reply other threads:[~2008-11-26 19:54 UTC|newest]
Thread overview: 28+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-10-30 19:55 [PATCH 0/3 RFC] MMC SPI support for OpenFirmware platforms Anton Vorontsov
2008-10-30 19:55 ` Anton Vorontsov
2008-10-30 19:56 ` [PATCH 1/3] powerpc: Add mmc-spi-slot bindings Anton Vorontsov
2008-10-30 19:56 ` Anton Vorontsov
2008-10-30 20:37 ` Grant Likely
2008-10-30 20:37 ` Grant Likely
2008-10-30 23:02 ` Anton Vorontsov
2008-10-30 23:02 ` Anton Vorontsov
2008-10-30 23:24 ` David Gibson
2008-10-30 23:24 ` David Gibson
2008-10-30 23:28 ` Anton Vorontsov
2008-10-30 23:28 ` Anton Vorontsov
2008-10-30 19:56 ` [PATCH 2/3] mmc: Add mmc_vddrange_to_ocrmask() helper function Anton Vorontsov
2008-10-30 19:56 ` Anton Vorontsov
2008-11-08 20:55 ` Pierre Ossman
2008-11-08 20:55 ` Pierre Ossman
2008-11-26 19:54 ` Anton Vorontsov [this message]
2008-11-26 19:54 ` [PATCH v2] " Anton Vorontsov
2008-11-30 20:06 ` Pierre Ossman
2008-11-30 20:06 ` Pierre Ossman
2008-12-01 11:53 ` Anton Vorontsov
2008-12-01 11:53 ` Anton Vorontsov
2008-12-14 17:28 ` Pierre Ossman
2008-12-14 17:28 ` Pierre Ossman
2008-10-30 19:56 ` [PATCH 3/3] mmc_spi: Add support for OpenFirmware bindings Anton Vorontsov
2008-10-30 19:56 ` Anton Vorontsov
2008-11-08 20:50 ` [PATCH 0/3 RFC] MMC SPI support for OpenFirmware platforms Pierre Ossman
2008-11-08 20:50 ` Pierre Ossman
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20081126195417.GA26264@oksana.dev.rtsoft.ru \
--to=avorontsov@ru.mvista.com \
--cc=dbrownell@users.sourceforge.net \
--cc=drzeus-mmc@drzeus.cx \
--cc=linux-kernel@vger.kernel.org \
--cc=linuxppc-dev@ozlabs.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.