From: Adrian Hunter <adrian.hunter@nokia.com> To: Tony Lindgren <tony@atomide.com> Cc: Madhusudhan Chikkature <madhu.cr@ti.com>, linux-omap Mailing List <linux-omap@vger.kernel.org>, linux-mmc Mailing List <linux-mmc@vger.kernel.org>, linux-arm Mailing List <linux-arm-kernel@lists.infradead.org>, Andy Shevchenko <ext-andriy.shevchenko@nokia.com>, Adrian Hunter <adrian.hunter@nokia.com> Subject: [PATCH 20/22] mmc: omap_hsmmc: adjust host controller clock in regard to current OPP Date: Thu, 5 May 2011 14:51:20 +0300 [thread overview] Message-ID: <1304596282-4095-21-git-send-email-adrian.hunter@nokia.com> (raw) In-Reply-To: <1304596282-4095-1-git-send-email-adrian.hunter@nokia.com> From: Andy Shevchenko <ext-andriy.shevchenko@nokia.com> We should like to adjust MMC host controller clock whenever the OPP is changed. OPP affects to L3/L4 bus frequency. Due to this we update the maximum frequency limits before each upcoming request and when the divisor is calculated. Signed-off-by: Andy Shevchenko <ext-andriy.shevchenko@nokia.com> Signed-off-by: Adrian Hunter <adrian.hunter@nokia.com> --- drivers/mmc/host/omap_hsmmc.c | 65 +++++++++++++++++++++++++++++++++++++---- 1 files changed, 59 insertions(+), 6 deletions(-) diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index 2c8fa01..8c5e7d3 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -199,6 +199,9 @@ struct omap_hsmmc_host { int use_reg; int req_in_progress; + /* Actual output frequency of host controller */ + unsigned int freq; + struct omap_mmc_platform_data *pdata; }; @@ -604,13 +607,31 @@ static void omap_hsmmc_disable_irq(struct omap_hsmmc_host *host) OMAP_HSMMC_WRITE(host->base, STAT, STAT_CLEAR); } +/* + * Recalculate desired clock frequency with regard to maximum possible + * frequency at current OPP. + * + * Choose either target frequency (ios->clock) or maximum possible frequency at + * current OPP (get_max_freq() returns this limit) + */ +static void omap_hsmmc_recalc_freq(struct omap_hsmmc_host *host, + struct mmc_ios *ios) +{ + struct omap_mmc_platform_data *pdata = host->pdata; + + if (pdata->get_max_freq) + host->freq = min(ios->clock, pdata->get_max_freq(host->dev)); + else + host->freq = ios->clock; +} + /* Calculate divisor for the given clock frequency */ -static u16 calc_divisor(struct mmc_ios *ios) +static u16 calc_divisor(struct omap_hsmmc_host *host) { u16 dsor = 0; - if (ios->clock) { - dsor = DIV_ROUND_UP(OMAP_MMC_MASTER_CLOCK, ios->clock); + if (host->freq) { + dsor = DIV_ROUND_UP(OMAP_MMC_MASTER_CLOCK, host->freq); if (dsor > 250) dsor = 250; } @@ -620,17 +641,16 @@ static u16 calc_divisor(struct mmc_ios *ios) static void omap_hsmmc_set_clock(struct omap_hsmmc_host *host) { - struct mmc_ios *ios = &host->mmc->ios; unsigned long regval; unsigned long timeout; - dev_dbg(mmc_dev(host->mmc), "Set clock to %uHz\n", ios->clock); + dev_dbg(mmc_dev(host->mmc), "Set clock to %uHz\n", host->freq); omap_hsmmc_stop_clock(host); regval = OMAP_HSMMC_READ(host->base, SYSCTL); regval = regval & ~(CLKD_MASK | DTO_MASK); - regval = regval | (calc_divisor(ios) << 6) | (DTO << 16); + regval = regval | (calc_divisor(host) << 6) | (DTO << 16); OMAP_HSMMC_WRITE(host->base, SYSCTL, regval); OMAP_HSMMC_WRITE(host->base, SYSCTL, OMAP_HSMMC_READ(host->base, SYSCTL) | ICE); @@ -754,6 +774,7 @@ static int omap_hsmmc_context_restore(struct omap_hsmmc_host *host) omap_hsmmc_set_bus_width(host); + omap_hsmmc_recalc_freq(host, ios); omap_hsmmc_set_clock(host); omap_hsmmc_set_bus_mode(host); @@ -937,6 +958,8 @@ static void omap_hsmmc_request_done(struct omap_hsmmc_host *host, struct mmc_req if (mrq->data && host->dma_in_use && dma_ch != -1) return; host->mrq = NULL; + if (host->pdata->inactive) + host->pdata->inactive(host->dev); mmc_request_done(host->mmc, mrq); } @@ -996,6 +1019,9 @@ omap_hsmmc_cmd_done(struct omap_hsmmc_host *host, struct mmc_command *cmd) } if ((host->data == NULL && !host->response_busy) || cmd->error) omap_hsmmc_request_done(host, cmd->mrq); + else if (host->data == NULL && host->response_busy && + host->pdata->inactive) + host->pdata->inactive(host->dev); } /* @@ -1418,6 +1444,8 @@ static void omap_hsmmc_dma_cb(int lch, u16 ch_status, void *cb_data) struct mmc_request *mrq = host->mrq; host->mrq = NULL; + if (host->pdata->inactive) + host->pdata->inactive(host->dev); mmc_request_done(host->mmc, mrq); } } @@ -1615,6 +1643,26 @@ static void omap_hsmmc_request(struct mmc_host *mmc, struct mmc_request *req) BUG_ON(host->req_in_progress); BUG_ON(host->dma_ch != -1); + + if (host->pdata->active) { + unsigned int new_freq; + + /* + * active() returns minimum of two (target, maximum) + * frequencies. + */ + new_freq = host->pdata->active(host->dev, mmc->ios.clock); + + /* + * We need to update actual frequency if it is not equal to the + * minimum of two (target and maximum) frequencies + */ + if (host->freq != new_freq) { + host->freq = new_freq; + omap_hsmmc_set_clock(host); + } + } + if (host->protect_card) { if (host->reqs_blocked < 3) { /* @@ -1630,6 +1678,8 @@ static void omap_hsmmc_request(struct mmc_host *mmc, struct mmc_request *req) if (req->data) req->data->error = -EBADF; req->cmd->retries = 0; + if (host->pdata->inactive) + host->pdata->inactive(host->dev); mmc_request_done(mmc, req); return; } else if (host->reqs_blocked) @@ -1642,6 +1692,8 @@ static void omap_hsmmc_request(struct mmc_host *mmc, struct mmc_request *req) if (req->data) req->data->error = err; host->mrq = NULL; + if (host->pdata->inactive) + host->pdata->inactive(host->dev); mmc_request_done(mmc, req); return; } @@ -1698,6 +1750,7 @@ static void omap_hsmmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) } } + omap_hsmmc_recalc_freq(host, ios); omap_hsmmc_set_clock(host); if (do_send_init_stream) -- 1.7.0.4
WARNING: multiple messages have this Message-ID (diff)
From: adrian.hunter@nokia.com (Adrian Hunter) To: linux-arm-kernel@lists.infradead.org Subject: [PATCH 20/22] mmc: omap_hsmmc: adjust host controller clock in regard to current OPP Date: Thu, 5 May 2011 14:51:20 +0300 [thread overview] Message-ID: <1304596282-4095-21-git-send-email-adrian.hunter@nokia.com> (raw) In-Reply-To: <1304596282-4095-1-git-send-email-adrian.hunter@nokia.com> From: Andy Shevchenko <ext-andriy.shevchenko@nokia.com> We should like to adjust MMC host controller clock whenever the OPP is changed. OPP affects to L3/L4 bus frequency. Due to this we update the maximum frequency limits before each upcoming request and when the divisor is calculated. Signed-off-by: Andy Shevchenko <ext-andriy.shevchenko@nokia.com> Signed-off-by: Adrian Hunter <adrian.hunter@nokia.com> --- drivers/mmc/host/omap_hsmmc.c | 65 +++++++++++++++++++++++++++++++++++++---- 1 files changed, 59 insertions(+), 6 deletions(-) diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index 2c8fa01..8c5e7d3 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -199,6 +199,9 @@ struct omap_hsmmc_host { int use_reg; int req_in_progress; + /* Actual output frequency of host controller */ + unsigned int freq; + struct omap_mmc_platform_data *pdata; }; @@ -604,13 +607,31 @@ static void omap_hsmmc_disable_irq(struct omap_hsmmc_host *host) OMAP_HSMMC_WRITE(host->base, STAT, STAT_CLEAR); } +/* + * Recalculate desired clock frequency with regard to maximum possible + * frequency at current OPP. + * + * Choose either target frequency (ios->clock) or maximum possible frequency at + * current OPP (get_max_freq() returns this limit) + */ +static void omap_hsmmc_recalc_freq(struct omap_hsmmc_host *host, + struct mmc_ios *ios) +{ + struct omap_mmc_platform_data *pdata = host->pdata; + + if (pdata->get_max_freq) + host->freq = min(ios->clock, pdata->get_max_freq(host->dev)); + else + host->freq = ios->clock; +} + /* Calculate divisor for the given clock frequency */ -static u16 calc_divisor(struct mmc_ios *ios) +static u16 calc_divisor(struct omap_hsmmc_host *host) { u16 dsor = 0; - if (ios->clock) { - dsor = DIV_ROUND_UP(OMAP_MMC_MASTER_CLOCK, ios->clock); + if (host->freq) { + dsor = DIV_ROUND_UP(OMAP_MMC_MASTER_CLOCK, host->freq); if (dsor > 250) dsor = 250; } @@ -620,17 +641,16 @@ static u16 calc_divisor(struct mmc_ios *ios) static void omap_hsmmc_set_clock(struct omap_hsmmc_host *host) { - struct mmc_ios *ios = &host->mmc->ios; unsigned long regval; unsigned long timeout; - dev_dbg(mmc_dev(host->mmc), "Set clock to %uHz\n", ios->clock); + dev_dbg(mmc_dev(host->mmc), "Set clock to %uHz\n", host->freq); omap_hsmmc_stop_clock(host); regval = OMAP_HSMMC_READ(host->base, SYSCTL); regval = regval & ~(CLKD_MASK | DTO_MASK); - regval = regval | (calc_divisor(ios) << 6) | (DTO << 16); + regval = regval | (calc_divisor(host) << 6) | (DTO << 16); OMAP_HSMMC_WRITE(host->base, SYSCTL, regval); OMAP_HSMMC_WRITE(host->base, SYSCTL, OMAP_HSMMC_READ(host->base, SYSCTL) | ICE); @@ -754,6 +774,7 @@ static int omap_hsmmc_context_restore(struct omap_hsmmc_host *host) omap_hsmmc_set_bus_width(host); + omap_hsmmc_recalc_freq(host, ios); omap_hsmmc_set_clock(host); omap_hsmmc_set_bus_mode(host); @@ -937,6 +958,8 @@ static void omap_hsmmc_request_done(struct omap_hsmmc_host *host, struct mmc_req if (mrq->data && host->dma_in_use && dma_ch != -1) return; host->mrq = NULL; + if (host->pdata->inactive) + host->pdata->inactive(host->dev); mmc_request_done(host->mmc, mrq); } @@ -996,6 +1019,9 @@ omap_hsmmc_cmd_done(struct omap_hsmmc_host *host, struct mmc_command *cmd) } if ((host->data == NULL && !host->response_busy) || cmd->error) omap_hsmmc_request_done(host, cmd->mrq); + else if (host->data == NULL && host->response_busy && + host->pdata->inactive) + host->pdata->inactive(host->dev); } /* @@ -1418,6 +1444,8 @@ static void omap_hsmmc_dma_cb(int lch, u16 ch_status, void *cb_data) struct mmc_request *mrq = host->mrq; host->mrq = NULL; + if (host->pdata->inactive) + host->pdata->inactive(host->dev); mmc_request_done(host->mmc, mrq); } } @@ -1615,6 +1643,26 @@ static void omap_hsmmc_request(struct mmc_host *mmc, struct mmc_request *req) BUG_ON(host->req_in_progress); BUG_ON(host->dma_ch != -1); + + if (host->pdata->active) { + unsigned int new_freq; + + /* + * active() returns minimum of two (target, maximum) + * frequencies. + */ + new_freq = host->pdata->active(host->dev, mmc->ios.clock); + + /* + * We need to update actual frequency if it is not equal to the + * minimum of two (target and maximum) frequencies + */ + if (host->freq != new_freq) { + host->freq = new_freq; + omap_hsmmc_set_clock(host); + } + } + if (host->protect_card) { if (host->reqs_blocked < 3) { /* @@ -1630,6 +1678,8 @@ static void omap_hsmmc_request(struct mmc_host *mmc, struct mmc_request *req) if (req->data) req->data->error = -EBADF; req->cmd->retries = 0; + if (host->pdata->inactive) + host->pdata->inactive(host->dev); mmc_request_done(mmc, req); return; } else if (host->reqs_blocked) @@ -1642,6 +1692,8 @@ static void omap_hsmmc_request(struct mmc_host *mmc, struct mmc_request *req) if (req->data) req->data->error = err; host->mrq = NULL; + if (host->pdata->inactive) + host->pdata->inactive(host->dev); mmc_request_done(mmc, req); return; } @@ -1698,6 +1750,7 @@ static void omap_hsmmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) } } + omap_hsmmc_recalc_freq(host, ios); omap_hsmmc_set_clock(host); if (do_send_init_stream) -- 1.7.0.4
next prev parent reply other threads:[~2011-05-05 11:52 UTC|newest] Thread overview: 56+ messages / expand[flat|nested] mbox.gz Atom feed top 2011-05-05 11:51 [PATCH 00/22] omap_hsmmc patches Adrian Hunter 2011-05-05 11:51 ` Adrian Hunter 2011-05-05 11:51 ` [PATCH 01/22] OMAP: sDMA: descriptor autoloading feature Adrian Hunter 2011-05-05 11:51 ` Adrian Hunter 2011-05-06 6:22 ` Tony Lindgren 2011-05-06 6:22 ` Tony Lindgren 2011-05-05 11:51 ` [PATCH 02/22] OMAP: DMA: add omap_dma_has_sglist() Adrian Hunter 2011-05-05 11:51 ` Adrian Hunter 2011-05-05 11:51 ` [PATCH 03/22] OMAP: DMA: Ensure the sglist registers are cleared Adrian Hunter 2011-05-05 11:51 ` Adrian Hunter 2011-05-05 11:51 ` [PATCH 04/22] mmc: omap hsmmc: adaptation of sdma descriptor Adrian Hunter 2011-05-05 11:51 ` Adrian Hunter 2011-05-05 11:51 ` [PATCH 05/22] mmc: omap_hsmmc: fix dma sglist use Adrian Hunter 2011-05-05 11:51 ` Adrian Hunter 2011-05-05 11:51 ` [PATCH 06/22] mmc: omap_hsmmc: limit scatterlist size for sDMA autoloading Adrian Hunter 2011-05-05 11:51 ` Adrian Hunter 2011-05-05 11:51 ` [PATCH 07/22] mmc: omap_hsmmc: fix missing mmc_release_host() in no_off case Adrian Hunter 2011-05-05 11:51 ` Adrian Hunter 2011-05-05 13:08 ` Sergei Shtylyov 2011-05-05 13:08 ` Sergei Shtylyov 2011-05-05 11:51 ` [PATCH 08/22] mmc: omap_hsmmc: correct debug report error status mnemonics Adrian Hunter 2011-05-05 11:51 ` Adrian Hunter 2011-05-06 8:35 ` S, Venkatraman 2011-05-06 8:35 ` S, Venkatraman 2011-05-05 11:51 ` [PATCH 09/22] mmc: omap_hsmmc: move hardcoded frequency constants to definition block Adrian Hunter 2011-05-05 11:51 ` Adrian Hunter 2011-05-05 11:51 ` [PATCH 10/22] mmc: omap_hsmmc: reduce a bit the error handlers in probe() Adrian Hunter 2011-05-05 11:51 ` Adrian Hunter 2011-05-05 11:51 ` [PATCH 11/22] mmc: omap_hsmmc: split duplicate code to calc_divisor() function Adrian Hunter 2011-05-05 11:51 ` Adrian Hunter 2011-05-05 11:51 ` [PATCH 12/22] mmc: omap_hsmmc: introduce start_clock and re-use stop_clock Adrian Hunter 2011-05-05 11:51 ` Adrian Hunter 2011-05-05 11:51 ` [PATCH 13/22] mmc: omap_hsmmc: fix few bugs when set the clock divisor Adrian Hunter 2011-05-05 11:51 ` Adrian Hunter 2011-05-05 12:53 ` Grazvydas Ignotas 2011-05-05 12:53 ` Grazvydas Ignotas 2011-05-05 11:51 ` [PATCH 14/22] mmc: omap_hsmmc: split same pieces of code to separate functions Adrian Hunter 2011-05-05 11:51 ` Adrian Hunter 2011-05-05 11:51 ` [PATCH 15/22] OMAP: hsmmc: Do not mux the slot if non default muxing is already done Adrian Hunter 2011-05-05 11:51 ` Adrian Hunter 2011-05-05 11:51 ` [PATCH 16/22] OMAP: board-rm680: set MMC nomux flag Adrian Hunter 2011-05-05 11:51 ` Adrian Hunter 2011-05-05 11:51 ` [PATCH 17/22] mmc: omap_hsmmc: ensure pbias configuration is always done Adrian Hunter 2011-05-05 11:51 ` Adrian Hunter 2011-05-05 11:51 ` [PATCH 18/22] mmc: omap_hsmmc: fix oops in omap_hsmmc_dma_cb Adrian Hunter 2011-05-05 11:51 ` Adrian Hunter 2011-05-05 11:51 ` [PATCH 19/22] OMAP: hsmmc: implement clock switcher Adrian Hunter 2011-05-05 11:51 ` Adrian Hunter 2011-05-05 13:34 ` Grazvydas Ignotas 2011-05-05 13:34 ` Grazvydas Ignotas 2011-05-05 11:51 ` Adrian Hunter [this message] 2011-05-05 11:51 ` [PATCH 20/22] mmc: omap_hsmmc: adjust host controller clock in regard to current OPP Adrian Hunter 2011-05-05 11:51 ` [PATCH 21/22] OMAP: hsmmc: add platform data for eMMC hardware reset gpio Adrian Hunter 2011-05-05 11:51 ` Adrian Hunter 2011-05-05 11:51 ` [PATCH 22/22] mmc: omap_hsmmc: add a hardware reset before initialization Adrian Hunter 2011-05-05 11:51 ` Adrian Hunter
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=1304596282-4095-21-git-send-email-adrian.hunter@nokia.com \ --to=adrian.hunter@nokia.com \ --cc=ext-andriy.shevchenko@nokia.com \ --cc=linux-arm-kernel@lists.infradead.org \ --cc=linux-mmc@vger.kernel.org \ --cc=linux-omap@vger.kernel.org \ --cc=madhu.cr@ti.com \ --cc=tony@atomide.com \ /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: linkBe 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.