From: Marek Vasut <marex@denx.de>
To: u-boot@lists.denx.de
Subject: [U-Boot] [PATCH 1/2] arm: socfpga: mmc: Enable calibration for drvsel and smpsel
Date: Thu, 20 Aug 2015 07:32:34 +0200 [thread overview]
Message-ID: <201508200732.35071.marex@denx.de> (raw)
In-Reply-To: <1440048482.1982.3.camel@clsee-VirtualBox.altera.com>
On Thursday, August 20, 2015 at 07:28:02 AM, Chin Liang See wrote:
> Hi,
>
> On Wed, 2015-08-19 at 14:36 +0000, marex at denx.de wrote:
> > On Wednesday, August 19, 2015 at 10:21:17 AM, Chin Liang See wrote:
> > > Hi,
> >
> > Hi again,
> >
> > > On Wed, 2015-08-19 at 02:41 +0000, marex at denx.de wrote:
> > > > On Wednesday, August 19, 2015 at 07:54:50 AM, Chin Liang See wrote:
> > > > > Enable SDMMC calibration to determine the best setting for
> > > > > drvsel and smpsel. It will be triggered whenever there is
> > > > > a change of card frequency and bus width. This is to ensure
> > > > > reliable transmission between the controller and the card.
> > > > >
> > > > > Signed-off-by: Chin Liang See <clsee@altera.com>
> > > > > Cc: Dinh Nguyen <dinguyen@opensource.altera.com>
> > > > > Cc: Pavel Machek <pavel@denx.de>
> > > > > Cc: Marek Vasut <marex@denx.de>
> > > > > Cc: Wolfgang Denk <wd@denx.de>
> > > > > Cc: Stefan Roese <sr@denx.de>
> > > > > Cc: Tom Rini <trini@konsulko.com>
> > > > > ---
> > > > >
> > > > > drivers/mmc/socfpga_dw_mmc.c | 187
> > > > >
> > > > > ++++++++++++++++++++++++++++++++++++++++-- 1 files changed, 180
> > > > > insertions(+), 7 deletions(-)
> > > > >
> > > > > diff --git a/drivers/mmc/socfpga_dw_mmc.c
> > > > > b/drivers/mmc/socfpga_dw_mmc.c index eb69aed..15e537c 100644
> > > > > --- a/drivers/mmc/socfpga_dw_mmc.c
> > > > > +++ b/drivers/mmc/socfpga_dw_mmc.c
> > > > > @@ -11,25 +11,140 @@
> > > > >
> > > > > #include <asm/arch/dwmmc.h>
> > > > > #include <asm/arch/clock_manager.h>
> > > > > #include <asm/arch/system_manager.h>
> > > > >
> > > > > +#include "mmc_private.h"
> > > > >
> > > > > static const struct socfpga_clock_manager *clock_manager_base =
> > > > >
> > > > > (void *)SOCFPGA_CLKMGR_ADDRESS;
> > > > >
> > > > > static const struct socfpga_system_manager *system_manager_base =
> > > > >
> > > > > (void *)SOCFPGA_SYSMGR_ADDRESS;
> > > > >
> > > > > -static void socfpga_dwmci_clksel(struct dwmci_host *host)
> > > > > +#define CAL_ROWS 7
> > > > > +#define CAL_COLS 8
> > > > > +
> > > > > +/*
> > > > > + * This function determines the largest rectangle filled with 1's
> > > > > and returns + * the middle. This functon can be optimized, for
> > > > > example using the algorithm + * from
> > > > > http://www.drdobbs.com/database/the-maximal-rectangle-problem/18441
> > > > > 0529 + * It currently takes less than 1ms, while creating the input
> > > > > data takes ~5ms + * so there is not a real need to optimize it. +
> > > > > */
> > > > > +int find_calibration_point(unsigned char
> > > > > cal_results[CAL_ROWS][CAL_COLS], +unsigned int sum, unsigned int *
> > > > > cal_row, unsigned int * cal_col)
> > > > >
> > > > > {
> > > > >
> > > > > - unsigned int drvsel;
> > > > > - unsigned int smplsel;
> > > > > + /* Structure containing a rectangle candidate */
> > > > > + typedef struct
> > > > > + {
> > > > > + unsigned char height;
> > > > > + unsigned char width;
> > > > > + unsigned short area;
> > > > > + } rect_cand_t;
> > > > > +
> > > > > + /* Array with the rectangle candidates */
> > > > > + rect_cand_t rect_cands[CAL_ROWS * CAL_COLS];
> > > > > + unsigned char cr_rect_cand = 0;
> > > > > + unsigned char height, width, k;
> > > > > +
> > > > > + /* No solution if all combinations fail */
> > > > > + if(sum == 0)
> > > > > + return 1;
> > > > > +
> > > > > + /* Simple solution if all combinations pass */
> > > > > + if(sum == (CAL_ROWS * CAL_COLS)) {
> > > > > + *cal_row = (CAL_ROWS - 1) / 2;
> > > > > + *cal_col = (CAL_COLS - 1) / 2;
> > > > > + return 0;
> > > > > + }
> > > > > +
> > > > > + /*
> > > > > + * Create list of all possible sub-rectangles, in descending
area
> > > > > + * order
> > > > > + */
> > > > > + for(height = CAL_ROWS; height >= 1; height--) {
> > > > > + for(width = CAL_COLS; width >= 1 ; width--){
> > > > > + /* Add a new rectangle candidate */
> > > > > + rect_cands[cr_rect_cand].height = height;
> > > > > + rect_cands[cr_rect_cand].width = width;
> > > > > + rect_cands[cr_rect_cand].area = height * width;
> > > > > + cr_rect_cand++;
> > > > > +
> > > > > + /* First candidate it always in the right
position */
> > > > > + if(cr_rect_cand == 1)
> > > > > + continue;
> > > > > +
> > > > > + /*
> > > > > + * Put the candidate in right location to
maintain
> > > > > + * descending order
> > > > > + */
> > > > > + for(k = cr_rect_cand - 1; k > 1; k--){
> > > > > + if(rect_cands[k-1].area <
rect_cands[k].area){
> > > > > + rect_cand_t tmp =
rect_cands[k-1];
> > > > > + rect_cands[k-1] = rect_cands[k];
> > > > > + rect_cands[k] = tmp;
> > > > > + } else
> > > > > + break;
> > > > > + }
> > > > > + }
> > > > > + }
> > > > > +
> > > > > + /* Try to fit the rectangle candidates, in descending area order
> > > > > */ + for(k = 0; k < CAL_ROWS * CAL_COLS; k++) {
> > > > > + unsigned char start_row, start_col;
> > > > > + unsigned rect_width = rect_cands[k].width;
> > > > > + unsigned rect_height = rect_cands[k].height;
> > > > > +
> > > > > + /* Find the row and column where the candidate fits */
> > > > > + for (start_col = 0; start_col < (CAL_COLS - rect_width +
1);
> > > > > + start_col++) {
> > > > > + for (start_row = 0; start_row < (CAL_ROWS -
> > > > > + rect_height + 1); start_row++) {
> > > > > + unsigned ok = 1;
> > > > > + unsigned add_col, add_row;
> > > > > +
> > > > > + /* Determine if the rectangle fits here
*/
> > > > > + for (add_col = 0; (add_col < rect_width)
&& ok;
> > > > > + add_col++) {
> > > > > + for (add_row = 0; add_row <
rect_height;
> > > > > + add_row++) {
> > > > > + if (!cal_results
> > > > > + [start_row+add_row]
[start_col
> > > > > + + add_col]) {
> > > > > + ok = 0;
> > > > > + break;
> > > > > + }
> > > > > + }
> > > > > + }
> > > > > +
> > > > > + /*
> > > > > + * Return 'middle' of rectangle in case
of
> > > > > + * success
> > > > > + */
> > > > > + if (ok) {
> > > > > + if(rect_width > 1)
> > > > > + rect_width--;
> > > > > +
> > > > > + if(rect_height > 1)
> > > > > + rect_height--;
> > > > > +
> > > > > + *cal_row = start_row +
> > > > > + (rect_height / 2);
> > > > > + *cal_col = start_col +
(rect_width / 2);
> > > > > +
> > > > > + return 0;
> > > > > + }
> > > > > + }
> > > > > + }
> > > > > + }
> > > > > +
> > > > > + /* We could not fit any rectangle - return failure */
> > > > > + return 1;
> > > >
> > > > Oh btw. please make sure to use errno.h and standard return codes ;
> > > > -EINVAL in this case I believe.
> > >
> > > Good suggestion, will fix in v2.
> > > Thanks
> >
> > Thanks. I was curious, is this really socfpga specific or can this
> > calibration be used on dwmmc in general -- thus on exynos and rockchip
> > systems -- as well? If it's generic to dwmmc, this should be moved into
> > the dwmmc core code. Also, I am CCing Simon, he's been plumbing in the
> > DWMMC recently.
>
> I am not sure. But definitely we can make the calibration common enough
> if they required the calibration too. Let wait feedback from Simon.
Excellent, thanks!
next prev parent reply other threads:[~2015-08-20 5:32 UTC|newest]
Thread overview: 40+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-08-19 5:54 [U-Boot] [PATCH 1/2] arm: socfpga: mmc: Enable calibration for drvsel and smpsel Chin Liang See
2015-08-19 7:26 ` Pavel Machek
2015-08-19 7:34 ` Marek Vasut
2015-08-19 8:30 ` Chin Liang See
2015-08-19 23:23 ` Marek Vasut
2015-08-19 8:33 ` Chin Liang See
2015-08-19 7:40 ` Marek Vasut
2015-08-19 8:21 ` Chin Liang See
2015-08-19 19:36 ` Marek Vasut
2015-08-20 5:28 ` Chin Liang See
2015-08-20 5:32 ` Marek Vasut [this message]
2015-08-20 21:55 ` Dinh Nguyen
2015-08-20 21:59 ` Marek Vasut
2015-08-21 0:33 ` Dinh Nguyen
2015-08-21 0:42 ` Marek Vasut
2015-08-21 20:52 ` Simon Glass
2015-08-24 15:04 ` Chin Liang See
2015-08-25 2:36 ` Jaehoon Chung
2015-08-25 3:08 ` Chin Liang See
2015-08-26 5:29 ` Jaehoon Chung
2015-08-26 5:47 ` Chin Liang See
2015-08-26 6:14 ` Jaehoon Chung
2015-08-26 6:54 ` Chin Liang See
2015-09-01 8:54 ` Chin Liang See
2015-09-01 9:01 ` Marek Vasut
2015-09-01 9:10 ` Chin Liang See
2015-09-01 10:12 ` Jaehoon Chung
2015-09-01 14:53 ` Dinh Nguyen
2015-09-02 10:32 ` Marek Vasut
2015-09-03 0:27 ` Chin Liang See
2015-09-03 5:30 ` Jaehoon Chung
2015-09-03 9:37 ` Marek Vasut
2015-09-03 14:06 ` Chin Liang See
2015-09-03 14:25 ` Marek Vasut
2015-09-04 10:41 ` Pavel Machek
2015-09-07 8:33 ` Jaehoon Chung
2015-09-08 1:32 ` Chin Liang See
2015-09-08 10:56 ` Marek Vasut
[not found] ` <0016CF5815A1B142902817051AF62EB305FDF5BA@PG-ITEXCH01.altera.priv.altera.com>
2015-10-07 2:54 ` Chin Liang See
2015-10-12 14:44 ` Marek Vasut
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=201508200732.35071.marex@denx.de \
--to=marex@denx.de \
--cc=u-boot@lists.denx.de \
/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.