From: Georgi Djakov <gdjakov@mm-sol.com>
To: Stephen Boyd <sboyd@codeaurora.org>
Cc: linux-mmc@vger.kernel.org, cjb@laptop.org,
devicetree@vger.kernel.org, grant.likely@linaro.org,
rob.herring@calxeda.com, pawel.moll@arm.com,
mark.rutland@arm.com, swarren@wwwdotorg.org,
ijc+devicetree@hellion.org.uk, galak@codeaurora.org,
rob@landley.net, linux-doc@vger.kernel.org,
linux-kernel@vger.kernel.org, linux-arm-msm@vger.kernel.org
Subject: Re: [PATCH v8 3/3] mmc: sdhci-msm: Add platform_execute_tunning implementation
Date: Thu, 13 Feb 2014 18:42:03 +0200 [thread overview]
Message-ID: <52FCF5DB.4030804@mm-sol.com> (raw)
In-Reply-To: <20140208032315.GB10784@codeaurora.org>
Hi Stephen,
On 02/08/2014 05:23 AM, Stephen Boyd wrote:
> On 01/30, Georgi Djakov wrote:
>> @@ -75,17 +110,389 @@ struct sdhci_msm_host {
>> };
>>
>> /* MSM platform specific tuning */
>> -int sdhci_msm_execute_tuning(struct sdhci_host *host, u32 opcode)
>> +static inline int msm_dll_poll_ck_out_en(struct sdhci_host *host, u8 poll)
>> +{
>> + u32 wait_cnt = 50;
>> + u8 ck_out_en = 0;
>
> Looks like a useless assignment.
Yes, thanks!
>
>> + struct mmc_host *mmc = host->mmc;
>> +
>> + /* poll for CK_OUT_EN bit. max. poll time = 50us */
>> + ck_out_en = !!(readl_relaxed(host->ioaddr + CORE_DLL_CONFIG) &
>> + CORE_CK_OUT_EN);
>> +
>> + while (ck_out_en != poll) {
>> + if (--wait_cnt == 0) {
>> + dev_err(mmc_dev(mmc), "%s: CK_OUT_EN bit is not %d\n",
>> + mmc_hostname(mmc), poll);
>> + return -ETIMEDOUT;
>> + }
>> + udelay(1);
>> +
>> + ck_out_en = !!(readl_relaxed(host->ioaddr + CORE_DLL_CONFIG) &
>> + CORE_CK_OUT_EN);
>> + }
>> +
>> + return 0;
>> +}
>> +
>> +static int msm_config_cm_dll_phase(struct sdhci_host *host, u8 phase)
>> +{
>> + int rc = 0;
>
> Looks like a useless assignment.
Ok.
>
>> + u8 grey_coded_phase_table[] = {
>> + 0x0, 0x1, 0x3, 0x2, 0x6, 0x7, 0x5, 0x4,
>> + 0xc, 0xd, 0xf, 0xe, 0xa, 0xb, 0x9, 0x8
>> + };
>
> This could be static const?
Yes, indeed!
>
>> + unsigned long flags;
>> + u32 config;
>> + struct mmc_host *mmc = host->mmc;
>> +
>> + spin_lock_irqsave(&host->lock, flags);
>> +
>> + config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG);
>> + config &= ~(CORE_CDR_EN | CORE_CK_OUT_EN);
>> + config |= (CORE_CDR_EXT_EN | CORE_DLL_EN);
>> + writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG);
>> +
>> + /* Wait until CK_OUT_EN bit of DLL_CONFIG register becomes '0' */
>> + rc = msm_dll_poll_ck_out_en(host, 0);
>> + if (rc)
>> + goto err_out;
>> +
>> + /*
>> + * Write the selected DLL clock output phase (0 ... 15)
>> + * to CDR_SELEXT bit field of DLL_CONFIG register.
>> + */
>> + writel_relaxed(((readl_relaxed(host->ioaddr + CORE_DLL_CONFIG)
>> + & ~(0xF << 20))
>> + | (grey_coded_phase_table[phase] << 20)),
>> + host->ioaddr + CORE_DLL_CONFIG);
>
> Wow this is complicated. Can we please break this up into
> multiple lines? What does 0xf << 20 mean?
Yes, sure! I will simplify it! Only bits 23:20 are used.
>
>> +
>> + /* Set CK_OUT_EN bit of DLL_CONFIG register to 1. */
>> + writel_relaxed((readl_relaxed(host->ioaddr + CORE_DLL_CONFIG)
>> + | CORE_CK_OUT_EN), host->ioaddr + CORE_DLL_CONFIG);
>> +
> [...]
>> +}
>> +
>> +static int msm_find_most_appropriate_phase(struct sdhci_host *host,
>> + u8 *phase_table, u8 total_phases)
>> +{
> [...]
>> +
>> + for (cnt = 0; cnt <= row_index; cnt++) {
>> + if (phases_per_row[cnt] > curr_max) {
>> + curr_max = phases_per_row[cnt];
>> + selected_row_index = cnt;
>> + }
>> + }
>> +
>> + i = ((curr_max * 3) / 4);
>
> Unnecessary extra parentheses here.
Thanks!
>
>> + if (i)
>> + i--;
>> +
>> + ret = (int)ranges[selected_row_index][i];
>
> Is this cast necessary?
Not necessary. Will fix it!
>
>> +
>> + if (ret >= MAX_PHASES) {
>> + ret = -EINVAL;
>> + dev_err(mmc_dev(mmc), "%s: invalid phase selected=%d\n",
>> + mmc_hostname(mmc), ret);
>> + }
>> +
>> + return ret;
>> +}
>> +
>> +static inline void msm_cm_dll_set_freq(struct sdhci_host *host)
>> +{
>> + u32 mclk_freq = 0;
>> +
>> + /* Program the MCLK value to MCLK_FREQ bit field */
>> + if (host->clock <= 112000000)
>> + mclk_freq = 0;
>> + else if (host->clock <= 125000000)
>> + mclk_freq = 1;
>> + else if (host->clock <= 137000000)
>> + mclk_freq = 2;
>> + else if (host->clock <= 150000000)
>> + mclk_freq = 3;
>> + else if (host->clock <= 162000000)
>> + mclk_freq = 4;
>> + else if (host->clock <= 175000000)
>> + mclk_freq = 5;
>> + else if (host->clock <= 187000000)
>> + mclk_freq = 6;
>> + else if (host->clock <= 200000000)
>> + mclk_freq = 7;
>
> This could be a case statement but I'm not sure it's any clearer.
> At least the range is specified.
>
> switch (host->clock) {
> case 0 ... 112000000:
> mclk_freq = 0;
> break;
> case 112000001 ... 125000000:
> mclk_freq = 1;
> break;
> ...
It seems to be shorter with the ifs, so i prefer to keep it this way.
>
>> +
>> + writel_relaxed(((readl_relaxed(host->ioaddr + CORE_DLL_CONFIG)
>> + & ~(7 << 24)) | (mclk_freq << 24)),
>> + host->ioaddr + CORE_DLL_CONFIG);
>
> This is also complicated. Can you split this up into multiple lines?
Yes, sure!
>
>> +int sdhci_msm_execute_tuning(struct sdhci_host *host, u32 opcode)
>> +{
> [...]
>> + do {
>> + struct mmc_command cmd = { 0 };
>> + struct mmc_data data = { 0 };
>> + struct mmc_request mrq = {
>> + .cmd = &cmd,
>> + .data = &data
>> + };
>> + struct scatterlist sg;
>> +
>> + /* set the phase in delay line hw block */
>> + rc = msm_config_cm_dll_phase(host, phase);
>> + if (rc)
>> + goto out;
>> +
>> + cmd.opcode = opcode;
>> + cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
>> +
>> + data.blksz = size;
>> + data.blocks = 1;
>> + data.flags = MMC_DATA_READ;
>> + data.timeout_ns = 1000 * 1000 * 1000; /* 1 sec */
>
> NSEC_PER_SEC?
Thanks!
>
>> +
>> + data.sg = &sg;
>> + data.sg_len = 1;
>> + sg_init_one(&sg, data_buf, sizeof(data_buf));
>> + memset(data_buf, 0, sizeof(data_buf));
>> + mmc_wait_for_req(mmc, &mrq);
>> +
>> + if (!cmd.error && !data.error &&
>> + !memcmp(data_buf, tuning_block_pattern, sizeof(data_buf))) {
>> + /* tuning is successful at this tuning point */
>> + tuned_phases[tuned_phase_cnt++] = phase;
>> + dev_dbg(mmc_dev(mmc), "%s: found good phase = %d\n",
>> + mmc_hostname(mmc), phase);
>> + }
>> + } while (++phase < 16);
>
> ++phase < ARRAY_SIZE(tuned_phases) ?
Thanks!
>
>> +
>> + if (tuned_phase_cnt) {
>> + rc = msm_find_most_appropriate_phase(host, tuned_phases,
>> + tuned_phase_cnt);
>> + if (rc < 0)
>> + goto out;
>> + else
>> + phase = (u8) rc;
>
> Unnecessary cast?
Yes, thank you for the review!
BR,
Georgi
next prev parent reply other threads:[~2014-02-13 16:42 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-01-30 18:45 [PATCH v8 0/3] mmc: sdhci-msm: Add support for Qualcomm chipsets Georgi Djakov
2014-01-30 18:45 ` [PATCH v8 1/3] mmc: sdhci-msm: Qualcomm SDHCI binding documentation Georgi Djakov
2014-01-30 18:45 ` [PATCH v8 2/3] mmc: sdhci-msm: Initial support for Qualcomm chipsets Georgi Djakov
2014-01-30 18:45 ` [PATCH v8 3/3] mmc: sdhci-msm: Add platform_execute_tunning implementation Georgi Djakov
2014-02-08 3:23 ` Stephen Boyd
2014-02-13 16:42 ` Georgi Djakov [this message]
2014-02-04 13:19 ` [PATCH v8 0/3] mmc: sdhci-msm: Add support for Qualcomm chipsets Christopher Covington
2014-02-04 16:58 ` Georgi Djakov
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=52FCF5DB.4030804@mm-sol.com \
--to=gdjakov@mm-sol.com \
--cc=cjb@laptop.org \
--cc=devicetree@vger.kernel.org \
--cc=galak@codeaurora.org \
--cc=grant.likely@linaro.org \
--cc=ijc+devicetree@hellion.org.uk \
--cc=linux-arm-msm@vger.kernel.org \
--cc=linux-doc@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mmc@vger.kernel.org \
--cc=mark.rutland@arm.com \
--cc=pawel.moll@arm.com \
--cc=rob.herring@calxeda.com \
--cc=rob@landley.net \
--cc=sboyd@codeaurora.org \
--cc=swarren@wwwdotorg.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).