RE: [PATCH v2] mmc: dw_mmc: Make sure we don't get stuck when we get an error
Hi Chris Ulf, I hope you find this patch for next. Thanks, Seungwon Jeon On Wed, May 21, 2014, Seungwon Jeon wrote: On Wed, May 21, 2014, Doug Anderson wrote: If we happened to get a data error at just the wrong time the dw_mmc driver could get into a state where it would never complete its request. That would leave the caller just hanging there. We fix this two ways and both of the two fixes on their own appear to fix the problems we've seen: 1. Fix a race in the tasklet where the interrupt setting the data error happens _just after_ we check for it, then we get a EVENT_XFER_COMPLETE. We fix this by repeating a bit of code. 2. Fix it so that if we detect that we've got an error in the data busy state and we're not going to do anything else we end the request and unblock anyone waiting. Signed-off-by: Doug Anderson diand...@chromium.org Signed-off-by: Yuvaraj Kumar C D yuvaraj...@gmail.com It will be applied after mmc: dw_mmc: change to use recommended reset procedure Acked-by: Seungwon Jeon tgih@samsung.com Thanks, Seungwon Jeon --- Changes in v2: - Removed TODO - Set cmd to NULL before calling dw_mci_request_end() drivers/mmc/host/dw_mmc.c | 46 ++ 1 file changed, 46 insertions(+) diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index cced599..54ec8b0 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c @@ -1318,6 +1318,14 @@ static void dw_mci_tasklet_func(unsigned long priv) /* fall through */ case STATE_SENDING_DATA: + /* +* We could get a data error and never a transfer +* complete so we'd better check for it here. +* +* Note that we don't really care if we also got a +* transfer complete; stopping the DMA and sending an +* abort won't hurt. +*/ if (test_and_clear_bit(EVENT_DATA_ERROR, host-pending_events)) { dw_mci_stop_dma(host); @@ -1331,7 +1339,29 @@ static void dw_mci_tasklet_func(unsigned long priv) break; set_bit(EVENT_XFER_COMPLETE, host-completed_events); + + /* +* Handle an EVENT_DATA_ERROR that might have shown up +* before the transfer completed. This might not have +* been caught by the check above because the interrupt +* could have gone off between the previous check and +* the check for transfer complete. +* +* Technically this ought not be needed assuming we +* get a DATA_COMPLETE eventually (we'll notice the +* error and end the request), but it shouldn't hurt. +* +* This has the advantage of sending the stop command. +*/ + if (test_and_clear_bit(EVENT_DATA_ERROR, + host-pending_events)) { + dw_mci_stop_dma(host); + send_stop_abort(host, data); + state = STATE_DATA_ERROR; + break; + } prev_state = state = STATE_DATA_BUSY; + /* fall through */ case STATE_DATA_BUSY: @@ -1354,6 +1384,22 @@ static void dw_mci_tasklet_func(unsigned long priv) /* stop command for open-ended transfer*/ if (data-stop) send_stop_abort(host, data); + } else { + /* +* If we don't have a command complete now we'll +* never get one since we just reset everything; +* better end the request. +* +* If we do have a command complete we'll fall +* through to the SENDING_STOP command and +* everything will be peachy keen. +*/ + if (!test_bit(EVENT_CMD_COMPLETE, + host-pending_events)) { + host-cmd = NULL; + dw_mci_request_end(host, mrq); + goto unlock; + } } /* -- 1.9.1.423.g4596e3a -- To unsubscribe from
RE: [PATCHv6] mmc: dw_mmc: change to use recommended reset procedure
On Tue, July 15, 2014, Sonny Rao wrote: This patch changes the fifo reset code to follow the reset procedure outlined in the documentation of Synopsys Mobile storage host databook. Signed-off-by: Sonny Rao sonny...@chromium.org Signed-off-by: Yuvaraj Kumar C D yuvaraj...@samsung.com Acked-by: Seungwon Jeon tgih@samsung.com Thanks, Seungwon Jeon --- v2: Add Generic DMA support per the documentation, move interrupt clear before wait make the test for DMA host-use_dma rather than host-using_dma add proper return values (although it appears no caller checks) v3: rename fifo reset function, and change callers use this combined reset function in dw_mci_resume() just one caller left (probe), so get rid of dw_mci_ctrl_all_reset() use DMA reset bit for all systems which use DMA remove extra IDMAC reset in dw_mci_work_routine_card() do CIU clock update in error path, if CIU reset cleared v4: remove comment about FIFO reset in dw_mci_work_routine_card() move down error message when control reset clears but others don't and clarify the error stating that we will still update clocks make flags for all reset bits a macro v5: don't use dw_mci_reset() in dw_mci_resume() and instead match what is done in dw_mci_probe() and don't force inline dw_mci_resume() v6: add newlines to dev_err() messages --- drivers/mmc/host/dw_mmc.c | 86 ++- drivers/mmc/host/dw_mmc.h | 5 +++ 2 files changed, 68 insertions(+), 23 deletions(-) diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index 55cd110..0c0aecb 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c @@ -111,8 +111,7 @@ static const u8 tuning_blk_pattern_8bit[] = { 0xff, 0x77, 0x77, 0xff, 0x77, 0xbb, 0xdd, 0xee, }; -static inline bool dw_mci_fifo_reset(struct dw_mci *host); -static inline bool dw_mci_ctrl_all_reset(struct dw_mci *host); +static bool dw_mci_reset(struct dw_mci *host); #if defined(CONFIG_DEBUG_FS) static int dw_mci_req_show(struct seq_file *s, void *v) @@ -1254,7 +1253,7 @@ static int dw_mci_data_complete(struct dw_mci *host, struct mmc_data *data) * After an error, there may be data lingering * in the FIFO */ - dw_mci_fifo_reset(host); + dw_mci_reset(host); } else { data-bytes_xfered = data-blocks * data-blksz; data-error = 0; @@ -1371,7 +1370,7 @@ static void dw_mci_tasklet_func(unsigned long priv) /* CMD error in data command */ if (mrq-cmd-error mrq-data) - dw_mci_fifo_reset(host); + dw_mci_reset(host); host-cmd = NULL; host-data = NULL; @@ -1982,14 +1981,8 @@ static void dw_mci_work_routine_card(struct work_struct *work) } /* Power down slot */ - if (present == 0) { - /* Clear down the FIFO */ - dw_mci_fifo_reset(host); -#ifdef CONFIG_MMC_DW_IDMAC - dw_mci_idmac_reset(host); -#endif - - } + if (present == 0) + dw_mci_reset(host); spin_unlock_bh(host-lock); @@ -2323,8 +2316,11 @@ static bool dw_mci_ctrl_reset(struct dw_mci *host, u32 reset) return false; } -static inline bool dw_mci_fifo_reset(struct dw_mci *host) +static bool dw_mci_reset(struct dw_mci *host) { + u32 flags = SDMMC_CTRL_RESET | SDMMC_CTRL_FIFO_RESET; + bool ret = false; + /* * Reseting generates a block interrupt, hence setting * the scatter-gather pointer to NULL. @@ -2334,15 +2330,59 @@ static inline bool dw_mci_fifo_reset(struct dw_mci *host) host-sg = NULL; } - return dw_mci_ctrl_reset(host, SDMMC_CTRL_FIFO_RESET); -} + if (host-use_dma) + flags |= SDMMC_CTRL_DMA_RESET; -static inline bool dw_mci_ctrl_all_reset(struct dw_mci *host) -{ - return dw_mci_ctrl_reset(host, - SDMMC_CTRL_FIFO_RESET | - SDMMC_CTRL_RESET | - SDMMC_CTRL_DMA_RESET); + if (dw_mci_ctrl_reset(host, flags)) { + /* + * In all cases we clear the RAWINTS register to clear any + * interrupts. + */ + mci_writel(host, RINTSTS, 0x); + + /* if using dma we wait for dma_req to clear */ + if (host-use_dma) { + unsigned long timeout = jiffies + msecs_to_jiffies(500); + u32 status; + do { + status = mci_readl(host, STATUS
RE: [PATCH] mmc: dw_mmc: change to use recommended reset procedure
On Fri, July 11, 2014, Sonny Rao wrote: On Thu, Jul 10, 2014 at 5:28 AM, Seungwon Jeon tgih@samsung.com wrote: Hi Sonny, I have missed this patch. You finally choose to take extra interrupt handling. If it is not harm, it's fine. Hi, thanks for coming back to it. Based on my tracing, the interrupt seems to be okay and is just ignored. -static inline bool dw_mci_fifo_reset(struct dw_mci *host) +static inline bool dw_mci_reset(struct dw_mci *host) inline is no needed anymore. { + u32 flags = SDMMC_CTRL_RESET | SDMMC_CTRL_FIFO_RESET; + bool ret = false; + /* * Reseting generates a block interrupt, hence setting * the scatter-gather pointer to NULL. @@ -2334,15 +2330,59 @@ static inline bool dw_mci_fifo_reset(struct dw_mci *host) host-sg = NULL; } - return dw_mci_ctrl_reset(host, SDMMC_CTRL_FIFO_RESET); -} + if (host-use_dma) + flags |= SDMMC_CTRL_DMA_RESET; -static inline bool dw_mci_ctrl_all_reset(struct dw_mci *host) -{ - return dw_mci_ctrl_reset(host, - SDMMC_CTRL_FIFO_RESET | - SDMMC_CTRL_RESET | - SDMMC_CTRL_DMA_RESET); + if (dw_mci_ctrl_reset(host, flags)) { + /* + * In all cases we clear the RAWINTS register to clear any + * interrupts. + */ + mci_writel(host, RINTSTS, 0x); + + /* if using dma we wait for dma_req to clear */ + if (host-use_dma) { + unsigned long timeout = jiffies + msecs_to_jiffies(500); + u32 status; + do { + status = mci_readl(host, STATUS); + if (!(status SDMMC_STATUS_DMA_REQ)) + break; + cpu_relax(); + } while (time_before(jiffies, timeout)); + + if (status SDMMC_STATUS_DMA_REQ) { + dev_err(host-dev, + %s: Timeout waiting for dma_req to + clear during reset, __func__); + goto ciu_out; + } + + /* when using DMA next we reset the fifo again */ + if (!dw_mci_ctrl_reset(host, SDMMC_CTRL_FIFO_RESET)) + goto ciu_out; + } + } else { + /* if the controller reset bit did clear, then set clock regs */ + if (!(mci_readl(host, CTRL) SDMMC_CTRL_RESET)) { + dev_err(host-dev, %s: fifo/dma reset bits didn't + clear but ciu was reset, doing clock update., + __func__); + goto ciu_out; + } + } + + if (IS_ENABLED(CONFIG_MMC_DW_IDMAC)) + /* It is also recommended that we reset and reprogram idmac */ + dw_mci_idmac_reset(host); + + ret = true; + +ciu_out: + /* After a CTRL reset we need to have CIU set clock registers */ + mci_send_cmd(host-cur_slot, SDMMC_CMD_UPD_CLK, 0); + + return ret; } #ifdef CONFIG_OF @@ -2555,7 +2595,7 @@ int dw_mci_probe(struct dw_mci *host) } /* Reset all blocks */ - if (!dw_mci_ctrl_all_reset(host)) + if (!dw_mci_ctrl_reset(host, SDMMC_CTRL_ALL_RESET_FLAGS)) return -ENODEV; host-dma_ops = host-pdata-dma_ops; @@ -2744,7 +2784,7 @@ int dw_mci_resume(struct dw_mci *host) } } - if (!dw_mci_ctrl_all_reset(host)) { + if (!dw_mci_reset(host)) { Do you have any reason to use dw_mci_reset() unlike doing on probing? I really wanted to use dw_mci_reset() everwhere, including probe, because that would be simplest, where there is just one reset function always, but the host structure is not completely set up at probe time, so the code in dw_mci_reset() where we try to send a command to update clock fails, so that's why I had to just do a reset. Yes, if we can keep one interface, it would be good. But can you check below? Did you see the kernel panic on probing with host-cur_slot is NULL? If right, resume seems not different from probe in case of removable type. And dw_mci_idmac_reset() is redundant when dw_mci_reset() is used at resume. I think dw_mci_ctrl_reset() can be also used at resume like at probe for simple way. For safety's sake, host-cur_slot should be guaranteed it's not NULL. Thanks, Seungwon Jeon -- To unsubscribe from this list: send the line unsubscribe linux-samsung-soc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
RE: [PATCHv4 0/5] ARM: remove the sub-node and deprecated supports-highspeed property for dwmmc.
On Thu, July 10, 2014, Jaehoon Chung wrote: Since used the mmc_of_parse(), didn't parse the sub-node. So we can remove the sub-node, because almost SoC used the only one card per a host. And supports-highspeed can be replaced to cap-mmc/sd-highspeed property. Changelog V4: - Fix the checkpatch error. Changelog V3: - Fix the wrong bus-width value. - Use the slot-host-quirks instead of brq-quirks. - Add tested-by and reviewd-by. Changelog V2: - Add the mmc: dw_mmc: replace disable-wp from slot's quirks to host's quirk Jaehoon Chung (5): mmc: dw_mmc: modify the dt-binding for removing slot-node and supports-highspeed ARM: dts: exynos: unuse the slot-node and deprecated the supports-highspeed for dw-mmc ARM: dts: socfpga: unuse the slot-node and deprecated the supports-highspeed for dw-mmc ARM: dts: rockchip: unuse the slot-node and deprecated the supports-highspeed for dw-mmc mmc: dw_mmc: replace disable-wp from slot's quirk to host's quirk .../devicetree/bindings/mmc/exynos-dw-mshc.txt | 17 - .../devicetree/bindings/mmc/k3-dw-mshc.txt | 12 - .../devicetree/bindings/mmc/synopsys-dw-mshc.txt | 12 - arch/arm/boot/dts/exynos4412-odroidx.dts |8 ++ arch/arm/boot/dts/exynos4412-origen.dts|8 ++ arch/arm/boot/dts/exynos4412-trats2.dts|8 ++ arch/arm/boot/dts/exynos5250-arndale.dts | 18 -- arch/arm/boot/dts/exynos5250-cros-common.dtsi | 26 ++-- arch/arm/boot/dts/exynos5250-smdk5250.dts | 18 -- arch/arm/boot/dts/exynos5250-snow.dts |6 ++--- arch/arm/boot/dts/exynos5260-xyref5260.dts | 18 -- arch/arm/boot/dts/exynos5410-smdk5410.dts | 18 -- arch/arm/boot/dts/exynos5420-arndale-octa.dts | 16 +++- arch/arm/boot/dts/exynos5420-peach-pit.dts | 16 +++- arch/arm/boot/dts/exynos5420-smdk5420.dts | 16 +++- arch/arm/boot/dts/exynos5800-peach-pi.dts | 16 +++- arch/arm/boot/dts/rk3066a-bqcurie2.dts | 16 +++- arch/arm/boot/dts/socfpga_arria5.dtsi |9 +++ arch/arm/boot/dts/socfpga_cyclone5.dtsi|9 +++ arch/arm/boot/dts/socfpga_vt.dts |9 +++ drivers/mmc/host/dw_mmc.c | 12 - 21 files changed, 84 insertions(+), 204 deletions(-) Acked-by: Seungwon Jeon tgih@samsung.com Thanks, Seungwon Jeon -- To unsubscribe from this list: send the line unsubscribe linux-samsung-soc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
RE: [PATCHv3 5/5] mmc: dw_mmc: replace disable-wp from slot's quirk to host's quirk
On Thu, July 10, 2014, Ulf Hansson wrote: On 10 July 2014 11:40, Jaehoon Chung jh80.ch...@samsung.com wrote: Hi, Ulf. On 07/10/2014 06:15 PM, Ulf Hansson wrote: On 10 July 2014 09:08, Jaehoon Chung jh80.ch...@samsung.com wrote: Replaced the disable-wp into host's quirks. (Because the slot-node is removed at dt-file.) Signed-off-by: Jaehoon Chung jh80.ch...@samsung.com Hi Jaehoon, I plan to carry these patches through my mmc tree and I will share them through a PR from an immutable branch with the ARM SoC guys. Please tell me if you have any concern with this set up. Hmm, I having a second thought around this. Could I just apply the mmc patches for my next branch instead of involving ARM SoC? In other words, are there any decencies? If not, I might just apply patch 1 and 5. [PATCHv4 2/5] ARM: dts: exynos: unuse the slot-node and deprecated the supports-highspeed for dw-mmc [PATCHv4 4/5] ARM: dts: rockchip: unuse the slot-node and deprecated the supports-highspeed for dw-mmc [PATCHv4 5/5] mmc: dw_mmc: replace disable-wp from slot's quirk to host's quirk 2nd and 4th are closely related 5th. I think it shall be picked together. How about taking whole patch? And I hope that it is applied for 3.16-rcX fix. (Also, 3rd patch is close to fix patch.) Kukjin, Is it fine to be taken in Ulf's? Thanks, Seungwon Jeon -- To unsubscribe from this list: send the line unsubscribe linux-samsung-soc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
RE: [PATCH] mmc: dw_mmc: change to use recommended reset procedure
)) + break; + cpu_relax(); + } while (time_before(jiffies, timeout)); + + if (status SDMMC_STATUS_DMA_REQ) { + dev_err(host-dev, + %s: Timeout waiting for dma_req to + clear during reset, __func__); + goto ciu_out; + } + + /* when using DMA next we reset the fifo again */ + if (!dw_mci_ctrl_reset(host, SDMMC_CTRL_FIFO_RESET)) + goto ciu_out; + } + } else { + /* if the controller reset bit did clear, then set clock regs */ + if (!(mci_readl(host, CTRL) SDMMC_CTRL_RESET)) { + dev_err(host-dev, %s: fifo/dma reset bits didn't + clear but ciu was reset, doing clock update., + __func__); + goto ciu_out; + } + } + + if (IS_ENABLED(CONFIG_MMC_DW_IDMAC)) + /* It is also recommended that we reset and reprogram idmac */ + dw_mci_idmac_reset(host); + + ret = true; + +ciu_out: + /* After a CTRL reset we need to have CIU set clock registers */ + mci_send_cmd(host-cur_slot, SDMMC_CMD_UPD_CLK, 0); + + return ret; } #ifdef CONFIG_OF @@ -2555,7 +2595,7 @@ int dw_mci_probe(struct dw_mci *host) } /* Reset all blocks */ - if (!dw_mci_ctrl_all_reset(host)) + if (!dw_mci_ctrl_reset(host, SDMMC_CTRL_ALL_RESET_FLAGS)) return -ENODEV; host-dma_ops = host-pdata-dma_ops; @@ -2744,7 +2784,7 @@ int dw_mci_resume(struct dw_mci *host) } } - if (!dw_mci_ctrl_all_reset(host)) { + if (!dw_mci_reset(host)) { Do you have any reason to use dw_mci_reset() unlike doing on probing? Thanks, Seungwon Jeon -- To unsubscribe from this list: send the line unsubscribe linux-samsung-soc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
RE: [PATCHv3 5/5] mmc: dw_mmc: replace disable-wp from slot's quirk to host's quirk
On Thu, July 10, 2014, Ulf Hansson wrote: On 10 July 2014 13:53, Seungwon Jeon tgih@samsung.com wrote: On Thu, July 10, 2014, Ulf Hansson wrote: On 10 July 2014 11:40, Jaehoon Chung jh80.ch...@samsung.com wrote: Hi, Ulf. On 07/10/2014 06:15 PM, Ulf Hansson wrote: On 10 July 2014 09:08, Jaehoon Chung jh80.ch...@samsung.com wrote: Replaced the disable-wp into host's quirks. (Because the slot-node is removed at dt-file.) Signed-off-by: Jaehoon Chung jh80.ch...@samsung.com Hi Jaehoon, I plan to carry these patches through my mmc tree and I will share them through a PR from an immutable branch with the ARM SoC guys. Please tell me if you have any concern with this set up. Hmm, I having a second thought around this. Could I just apply the mmc patches for my next branch instead of involving ARM SoC? In other words, are there any decencies? If not, I might just apply patch 1 and 5. [PATCHv4 2/5] ARM: dts: exynos: unuse the slot-node and deprecated the supports-highspeed for dw-mmc [PATCHv4 4/5] ARM: dts: rockchip: unuse the slot-node and deprecated the supports-highspeed for dw- mmc [PATCHv4 5/5] mmc: dw_mmc: replace disable-wp from slot's quirk to host's quirk 2nd and 4th are closely related 5th. I think it shall be picked together. How about taking whole patch? And I hope that it is applied for 3.16-rcX fix. (Also, 3rd patch is close to fix patch.) Kukjin, Is it fine to be taken in Ulf's? I tried applied the complete patchset for 3.16 rc4, but some of the DTS patches fails. What are these patches based upon? I guess it's based on Ulf or Chris? It may need to be rebased for 3.16 rc4. I wonder if it's not best to leave all these for Kukjin to handle instead. You have my ack for all of the mmc patches! Thanks, Seungwon Jeon -- To unsubscribe from this list: send the line unsubscribe linux-samsung-soc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
RE: [PATCH 3/3] mmc: dw_mmc: Support voltage changes
On Tue, July 08, 2014,Yuvaraj Kumar wrote: On Mon, Jul 7, 2014 at 10:53 AM, Seungwon Jeon tgih@samsung.com wrote: On Fri, July 04, 2014, Seungwon Jeon wrote: On Tue, July 01, 2014. Yuvaraj Kumar wrote: On Fri, Jun 27, 2014 at 4:48 PM, Seungwon Jeon tgih@samsung.com wrote: Hi Yuvaraj, On Fri, June 27, 2014, Yuvaraj Kumar wrote: On Thu, Jun 26, 2014 at 10:20 PM, Doug Anderson diand...@chromium.org wrote: Seungwon, On Thu, Jun 26, 2014 at 3:41 AM, Seungwon Jeon tgih@samsung.com wrote: On Thu, June 26, 2014, Doug Anderson wrote: Seungwon, On Wed, Jun 25, 2014 at 6:08 AM, Seungwon Jeon tgih@samsung.com wrote: On Mon, June 23, 2014, Yuvaraj Kumar C D wrote: Subject: [PATCH 3/3] mmc: dw_mmc: Support voltage changes From: Doug Anderson diand...@chromium.org For UHS cards we need the ability to switch voltages from 3.3V to 1.8V. Add support to the dw_mmc driver to handle this. Note that dw_mmc needs a little bit of extra code since the interface needs a special bit programmed to the CMD register while CMD11 is progressing. This means adding a few extra states to the state machine to track. Overall new additional states makes it complicated. Can we do that in other way? That was the best I was able to figure out when I thought this through. If you have ideas for doing it another way I'd imagine that Yuvaraj would be happy to take your feedback. Let's clean up SDMMC_CMD_VOLT_SWITCH. In turn, we may remove state-handling simply. Signed-off-by: Doug Anderson diand...@chromium.org Signed-off-by: Yuvaraj Kumar C D yuvaraj...@samsung.com --- drivers/mmc/host/dw_mmc.c | 145 +--- drivers/mmc/host/dw_mmc.h |5 +- include/linux/mmc/dw_mmc.h |2 + 3 files changed, 142 insertions(+), 10 deletions(-) diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index e034bce..38eb548 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c @@ -29,6 +29,7 @@ #include linux/irq.h #include linux/mmc/host.h #include linux/mmc/mmc.h +#include linux/mmc/sd.h #include linux/mmc/sdio.h #include linux/mmc/dw_mmc.h #include linux/bitops.h @@ -235,10 +236,13 @@ err: } #endif /* defined(CONFIG_DEBUG_FS) */ +static void mci_send_cmd(struct dw_mci_slot *slot, u32 cmd, u32 arg); + static u32 dw_mci_prepare_command(struct mmc_host *mmc, struct mmc_command *cmd) { struct mmc_data *data; struct dw_mci_slot *slot = mmc_priv(mmc); + struct dw_mci *host = slot-host; const struct dw_mci_drv_data *drv_data = slot-host-drv_data; u32 cmdr; cmd-error = -EINPROGRESS; @@ -254,6 +258,32 @@ static u32 dw_mci_prepare_command(struct mmc_host *mmc, struct mmc_command *cmd) else if (cmd-opcode != MMC_SEND_STATUS cmd-data) cmdr |= SDMMC_CMD_PRV_DAT_WAIT; + if (cmd-opcode == SD_SWITCH_VOLTAGE) { + u32 clk_en_a; + + /* Special bit makes CMD11 not die */ + cmdr |= SDMMC_CMD_VOLT_SWITCH; + + /* Change state to continue to handle CMD11 weirdness */ + WARN_ON(slot-host-state != STATE_SENDING_CMD); + slot-host-state = STATE_SENDING_CMD11; + + /* + * We need to disable clock stop while doing voltage switch + * according to 7.4.1.2 Voltage Switch Normal Scenario. + * + * It's assumed that by the next time the CLKENA is updated + * (when we set the clock next) that the voltage change will + * be over, so we don't bother setting any bits to synchronize + * with dw_mci_setup_bus(). + */ + clk_en_a = mci_readl(host, CLKENA); + clk_en_a = ~(SDMMC_CLKEN_LOW_PWR slot-id); + mci_writel(host, CLKENA, clk_en_a); + mci_send_cmd(slot, SDMMC_CMD_UPD_CLK | + SDMMC_CMD_PRV_DAT_WAIT, 0); dw_mci_disable_low_power() can be used here. Ah. I guess we don't have that locally anymore. Locally we have variants on: I'm checking on cjb/mmc branch. * https://patchwork.kernel.org/patch/3070311/ * https://patchwork.kernel.org/patch/3070251/ * https://patchwork.kernel.org/patch/3070221/ ...which removed that function. ...but I
RE: [PATCHv2 2/5] ARM: dts: exynos: unuse the slot-node and deprecated the supports-highspeed for dw-mmc
Hi Jaehoon, Please check one thing below. On Mon, June 30, 2014, Jaehoon Chung wrote: dw-mmc controller can support multiple slots. But, there are no use-cases anywhere. So we don't need to support the slot-node for dw-mmc controller. And supports-highspeed property in dw-mmc is deprecated. supports-highspeed property can be replaced to cap-sd/mmc-highspeed. Signed-off-by: Jaehoon Chung jh80.ch...@samsung.com Reviewed-by: Tushar Behera trbli...@gmail.com Reviewed-by: Ulf Hansson ulf.hans...@linaro.org --- diff --git a/arch/arm/boot/dts/exynos5420-arndale-octa.dts b/arch/arm/boot/dts/exynos5420-arndale- octa.dts index 434fd9d..5f37b81 100644 --- a/arch/arm/boot/dts/exynos5420-arndale-octa.dts +++ b/arch/arm/boot/dts/exynos5420-arndale-octa.dts @@ -50,7 +50,6 @@ mmc@1220 { status = okay; broken-cd; - supports-highspeed; card-detect-delay = 200; samsung,dw-mshc-ciu-div = 3; samsung,dw-mshc-sdr-timing = 0 4; @@ -58,16 +57,12 @@ pinctrl-names = default; pinctrl-0 = sd0_clk sd0_cmd sd0_bus4 sd0_bus8; vmmc-supply = ldo10_reg; - - slot@0 { - reg = 0; - bus-width = 8; - }; + bus-width = 8; + cap-mmc-highspeed; }; mmc@1222 { status = okay; - supports-highspeed; card-detect-delay = 200; samsung,dw-mshc-ciu-div = 3; samsung,dw-mshc-sdr-timing = 2 3; @@ -75,11 +70,8 @@ pinctrl-names = default; pinctrl-0 = sd2_clk sd2_cmd sd2_cd sd2_bus4; vmmc-supply = ldo10_reg; - - slot@0 { - reg = 0; - bus-width = 4; - }; + bus-width = 8; 4 is correct? + cap-mmc-highspeed; Thanks, Seungwon Jeon -- To unsubscribe from this list: send the line unsubscribe linux-samsung-soc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
RE: [PATCHv2 5/5] mmc: dw_mmc: replace disable-wp from slot's quirk to host's quirk
Sorry for late review. If you're in progress for next, please consider it. On Mon, June 30, 2014, Jaehoon Chung wrote: Replaced the disable-wp into host's quirks. (Because the slot-node is removed at dt-file.) Signed-off-by: Jaehoon Chung jh80.ch...@samsung.com --- drivers/mmc/host/dw_mmc.c | 13 ++--- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index 1ac227c..6c5d696 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c @@ -994,10 +994,11 @@ static int dw_mci_get_ro(struct mmc_host *mmc) { int read_only; struct dw_mci_slot *slot = mmc_priv(mmc); + struct dw_mci_board *brd = slot-host-pdata; int gpio_ro = mmc_gpio_get_ro(mmc); /* Use platform get_ro function, else try on board write protect */ - if (slot-quirks DW_MCI_SLOT_QUIRK_NO_WRITE_PROTECT) It would be better to use host-quirks instead of brd-quirks It's finally updated with host-pdata-quirks on probing. Thanks, Seungwon Jeon -- To unsubscribe from this list: send the line unsubscribe linux-samsung-soc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
RE: [PATCH 3/3] mmc: dw_mmc: Support voltage changes
On Fri, July 04, 2014, Seungwon Jeon wrote: On Tue, July 01, 2014. Yuvaraj Kumar wrote: On Fri, Jun 27, 2014 at 4:48 PM, Seungwon Jeon tgih@samsung.com wrote: Hi Yuvaraj, On Fri, June 27, 2014, Yuvaraj Kumar wrote: On Thu, Jun 26, 2014 at 10:20 PM, Doug Anderson diand...@chromium.org wrote: Seungwon, On Thu, Jun 26, 2014 at 3:41 AM, Seungwon Jeon tgih@samsung.com wrote: On Thu, June 26, 2014, Doug Anderson wrote: Seungwon, On Wed, Jun 25, 2014 at 6:08 AM, Seungwon Jeon tgih@samsung.com wrote: On Mon, June 23, 2014, Yuvaraj Kumar C D wrote: Subject: [PATCH 3/3] mmc: dw_mmc: Support voltage changes From: Doug Anderson diand...@chromium.org For UHS cards we need the ability to switch voltages from 3.3V to 1.8V. Add support to the dw_mmc driver to handle this. Note that dw_mmc needs a little bit of extra code since the interface needs a special bit programmed to the CMD register while CMD11 is progressing. This means adding a few extra states to the state machine to track. Overall new additional states makes it complicated. Can we do that in other way? That was the best I was able to figure out when I thought this through. If you have ideas for doing it another way I'd imagine that Yuvaraj would be happy to take your feedback. Let's clean up SDMMC_CMD_VOLT_SWITCH. In turn, we may remove state-handling simply. Signed-off-by: Doug Anderson diand...@chromium.org Signed-off-by: Yuvaraj Kumar C D yuvaraj...@samsung.com --- drivers/mmc/host/dw_mmc.c | 145 +--- drivers/mmc/host/dw_mmc.h |5 +- include/linux/mmc/dw_mmc.h |2 + 3 files changed, 142 insertions(+), 10 deletions(-) diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index e034bce..38eb548 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c @@ -29,6 +29,7 @@ #include linux/irq.h #include linux/mmc/host.h #include linux/mmc/mmc.h +#include linux/mmc/sd.h #include linux/mmc/sdio.h #include linux/mmc/dw_mmc.h #include linux/bitops.h @@ -235,10 +236,13 @@ err: } #endif /* defined(CONFIG_DEBUG_FS) */ +static void mci_send_cmd(struct dw_mci_slot *slot, u32 cmd, u32 arg); + static u32 dw_mci_prepare_command(struct mmc_host *mmc, struct mmc_command *cmd) { struct mmc_data *data; struct dw_mci_slot *slot = mmc_priv(mmc); + struct dw_mci *host = slot-host; const struct dw_mci_drv_data *drv_data = slot-host-drv_data; u32 cmdr; cmd-error = -EINPROGRESS; @@ -254,6 +258,32 @@ static u32 dw_mci_prepare_command(struct mmc_host *mmc, struct mmc_command *cmd) else if (cmd-opcode != MMC_SEND_STATUS cmd-data) cmdr |= SDMMC_CMD_PRV_DAT_WAIT; + if (cmd-opcode == SD_SWITCH_VOLTAGE) { + u32 clk_en_a; + + /* Special bit makes CMD11 not die */ + cmdr |= SDMMC_CMD_VOLT_SWITCH; + + /* Change state to continue to handle CMD11 weirdness */ + WARN_ON(slot-host-state != STATE_SENDING_CMD); + slot-host-state = STATE_SENDING_CMD11; + + /* + * We need to disable clock stop while doing voltage switch + * according to 7.4.1.2 Voltage Switch Normal Scenario. + * + * It's assumed that by the next time the CLKENA is updated + * (when we set the clock next) that the voltage change will + * be over, so we don't bother setting any bits to synchronize + * with dw_mci_setup_bus(). + */ + clk_en_a = mci_readl(host, CLKENA); + clk_en_a = ~(SDMMC_CLKEN_LOW_PWR slot-id); + mci_writel(host, CLKENA, clk_en_a); + mci_send_cmd(slot, SDMMC_CMD_UPD_CLK | + SDMMC_CMD_PRV_DAT_WAIT, 0); dw_mci_disable_low_power() can be used here. Ah. I guess we don't have that locally anymore. Locally we have variants on: I'm checking on cjb/mmc branch. * https://patchwork.kernel.org/patch/3070311/ * https://patchwork.kernel.org/patch/3070251/ * https://patchwork.kernel.org/patch/3070221/ ...which removed that function. ...but I guess upstream never picked up those patches, huh? Looking back it looks like you had some feedback and it needed another spin but somehow fell off my plate. :( Maybe this is something Yuvaraj would like to pick up? It's long ago. I remember
RE: [PATCH 3/3] mmc: dw_mmc: Support voltage changes
On Tue, July 01, 2014. Yuvaraj Kumar wrote: On Fri, Jun 27, 2014 at 4:48 PM, Seungwon Jeon tgih@samsung.com wrote: Hi Yuvaraj, On Fri, June 27, 2014, Yuvaraj Kumar wrote: On Thu, Jun 26, 2014 at 10:20 PM, Doug Anderson diand...@chromium.org wrote: Seungwon, On Thu, Jun 26, 2014 at 3:41 AM, Seungwon Jeon tgih@samsung.com wrote: On Thu, June 26, 2014, Doug Anderson wrote: Seungwon, On Wed, Jun 25, 2014 at 6:08 AM, Seungwon Jeon tgih@samsung.com wrote: On Mon, June 23, 2014, Yuvaraj Kumar C D wrote: Subject: [PATCH 3/3] mmc: dw_mmc: Support voltage changes From: Doug Anderson diand...@chromium.org For UHS cards we need the ability to switch voltages from 3.3V to 1.8V. Add support to the dw_mmc driver to handle this. Note that dw_mmc needs a little bit of extra code since the interface needs a special bit programmed to the CMD register while CMD11 is progressing. This means adding a few extra states to the state machine to track. Overall new additional states makes it complicated. Can we do that in other way? That was the best I was able to figure out when I thought this through. If you have ideas for doing it another way I'd imagine that Yuvaraj would be happy to take your feedback. Let's clean up SDMMC_CMD_VOLT_SWITCH. In turn, we may remove state-handling simply. Signed-off-by: Doug Anderson diand...@chromium.org Signed-off-by: Yuvaraj Kumar C D yuvaraj...@samsung.com --- drivers/mmc/host/dw_mmc.c | 145 +--- drivers/mmc/host/dw_mmc.h |5 +- include/linux/mmc/dw_mmc.h |2 + 3 files changed, 142 insertions(+), 10 deletions(-) diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index e034bce..38eb548 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c @@ -29,6 +29,7 @@ #include linux/irq.h #include linux/mmc/host.h #include linux/mmc/mmc.h +#include linux/mmc/sd.h #include linux/mmc/sdio.h #include linux/mmc/dw_mmc.h #include linux/bitops.h @@ -235,10 +236,13 @@ err: } #endif /* defined(CONFIG_DEBUG_FS) */ +static void mci_send_cmd(struct dw_mci_slot *slot, u32 cmd, u32 arg); + static u32 dw_mci_prepare_command(struct mmc_host *mmc, struct mmc_command *cmd) { struct mmc_data *data; struct dw_mci_slot *slot = mmc_priv(mmc); + struct dw_mci *host = slot-host; const struct dw_mci_drv_data *drv_data = slot-host-drv_data; u32 cmdr; cmd-error = -EINPROGRESS; @@ -254,6 +258,32 @@ static u32 dw_mci_prepare_command(struct mmc_host *mmc, struct mmc_command *cmd) else if (cmd-opcode != MMC_SEND_STATUS cmd-data) cmdr |= SDMMC_CMD_PRV_DAT_WAIT; + if (cmd-opcode == SD_SWITCH_VOLTAGE) { + u32 clk_en_a; + + /* Special bit makes CMD11 not die */ + cmdr |= SDMMC_CMD_VOLT_SWITCH; + + /* Change state to continue to handle CMD11 weirdness */ + WARN_ON(slot-host-state != STATE_SENDING_CMD); + slot-host-state = STATE_SENDING_CMD11; + + /* + * We need to disable clock stop while doing voltage switch + * according to 7.4.1.2 Voltage Switch Normal Scenario. + * + * It's assumed that by the next time the CLKENA is updated + * (when we set the clock next) that the voltage change will + * be over, so we don't bother setting any bits to synchronize + * with dw_mci_setup_bus(). + */ + clk_en_a = mci_readl(host, CLKENA); + clk_en_a = ~(SDMMC_CLKEN_LOW_PWR slot-id); + mci_writel(host, CLKENA, clk_en_a); + mci_send_cmd(slot, SDMMC_CMD_UPD_CLK | + SDMMC_CMD_PRV_DAT_WAIT, 0); dw_mci_disable_low_power() can be used here. Ah. I guess we don't have that locally anymore. Locally we have variants on: I'm checking on cjb/mmc branch. * https://patchwork.kernel.org/patch/3070311/ * https://patchwork.kernel.org/patch/3070251/ * https://patchwork.kernel.org/patch/3070221/ ...which removed that function. ...but I guess upstream never picked up those patches, huh? Looking back it looks like you had some feedback and it needed another spin but somehow fell off my plate. :( Maybe this is something Yuvaraj would like to pick up? It's long ago. I remember that there is no progress since my last comment. In case of patch 3070221, I want to pick up for next Kernel. Sounds like Yuvaraj has agreed to look at addressing your comments. Thanks
RE: [PATCH 3/3] mmc: dw_mmc: Support voltage changes
Hi Yuvaraj, On Fri, June 27, 2014, Yuvaraj Kumar wrote: On Thu, Jun 26, 2014 at 10:20 PM, Doug Anderson diand...@chromium.org wrote: Seungwon, On Thu, Jun 26, 2014 at 3:41 AM, Seungwon Jeon tgih@samsung.com wrote: On Thu, June 26, 2014, Doug Anderson wrote: Seungwon, On Wed, Jun 25, 2014 at 6:08 AM, Seungwon Jeon tgih@samsung.com wrote: On Mon, June 23, 2014, Yuvaraj Kumar C D wrote: Subject: [PATCH 3/3] mmc: dw_mmc: Support voltage changes From: Doug Anderson diand...@chromium.org For UHS cards we need the ability to switch voltages from 3.3V to 1.8V. Add support to the dw_mmc driver to handle this. Note that dw_mmc needs a little bit of extra code since the interface needs a special bit programmed to the CMD register while CMD11 is progressing. This means adding a few extra states to the state machine to track. Overall new additional states makes it complicated. Can we do that in other way? That was the best I was able to figure out when I thought this through. If you have ideas for doing it another way I'd imagine that Yuvaraj would be happy to take your feedback. Let's clean up SDMMC_CMD_VOLT_SWITCH. In turn, we may remove state-handling simply. Signed-off-by: Doug Anderson diand...@chromium.org Signed-off-by: Yuvaraj Kumar C D yuvaraj...@samsung.com --- drivers/mmc/host/dw_mmc.c | 145 +--- drivers/mmc/host/dw_mmc.h |5 +- include/linux/mmc/dw_mmc.h |2 + 3 files changed, 142 insertions(+), 10 deletions(-) diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index e034bce..38eb548 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c @@ -29,6 +29,7 @@ #include linux/irq.h #include linux/mmc/host.h #include linux/mmc/mmc.h +#include linux/mmc/sd.h #include linux/mmc/sdio.h #include linux/mmc/dw_mmc.h #include linux/bitops.h @@ -235,10 +236,13 @@ err: } #endif /* defined(CONFIG_DEBUG_FS) */ +static void mci_send_cmd(struct dw_mci_slot *slot, u32 cmd, u32 arg); + static u32 dw_mci_prepare_command(struct mmc_host *mmc, struct mmc_command *cmd) { struct mmc_data *data; struct dw_mci_slot *slot = mmc_priv(mmc); + struct dw_mci *host = slot-host; const struct dw_mci_drv_data *drv_data = slot-host-drv_data; u32 cmdr; cmd-error = -EINPROGRESS; @@ -254,6 +258,32 @@ static u32 dw_mci_prepare_command(struct mmc_host *mmc, struct mmc_command *cmd) else if (cmd-opcode != MMC_SEND_STATUS cmd-data) cmdr |= SDMMC_CMD_PRV_DAT_WAIT; + if (cmd-opcode == SD_SWITCH_VOLTAGE) { + u32 clk_en_a; + + /* Special bit makes CMD11 not die */ + cmdr |= SDMMC_CMD_VOLT_SWITCH; + + /* Change state to continue to handle CMD11 weirdness */ + WARN_ON(slot-host-state != STATE_SENDING_CMD); + slot-host-state = STATE_SENDING_CMD11; + + /* + * We need to disable clock stop while doing voltage switch + * according to 7.4.1.2 Voltage Switch Normal Scenario. + * + * It's assumed that by the next time the CLKENA is updated + * (when we set the clock next) that the voltage change will + * be over, so we don't bother setting any bits to synchronize + * with dw_mci_setup_bus(). + */ + clk_en_a = mci_readl(host, CLKENA); + clk_en_a = ~(SDMMC_CLKEN_LOW_PWR slot-id); + mci_writel(host, CLKENA, clk_en_a); + mci_send_cmd(slot, SDMMC_CMD_UPD_CLK | + SDMMC_CMD_PRV_DAT_WAIT, 0); dw_mci_disable_low_power() can be used here. Ah. I guess we don't have that locally anymore. Locally we have variants on: I'm checking on cjb/mmc branch. * https://patchwork.kernel.org/patch/3070311/ * https://patchwork.kernel.org/patch/3070251/ * https://patchwork.kernel.org/patch/3070221/ ...which removed that function. ...but I guess upstream never picked up those patches, huh? Looking back it looks like you had some feedback and it needed another spin but somehow fell off my plate. :( Maybe this is something Yuvaraj would like to pick up? It's long ago. I remember that there is no progress since my last comment. In case of patch 3070221, I want to pick up for next Kernel. Sounds like Yuvaraj has agreed to look at addressing your comments. Thanks! + } + if (cmd-flags MMC_RSP_PRESENT) { /* We expect a response, so set this bit */ cmdr |= SDMMC_CMD_RESP_EXP; @@ -776,11 +806,15 @@ static void dw_mci_setup_bus(struct dw_mci_slot *slot, bool force_clkinit
RE: [PATCH 1/3] mmc: dw_mmc: use mmc_regulator_get_supply to handle regulators
On Fri, June 27, 2014, Doug Anderson wrote: Seungwon, On Thu, Jun 26, 2014 at 3:30 AM, Seungwon Jeon tgih@samsung.com wrote: Hi Doug, On Thu, June 26, 2014, Doug Anderson wrote: Seungwon, On Wed, Jun 25, 2014 at 4:18 AM, Seungwon Jeon tgih@samsung.com wrote: + case MMC_POWER_ON: + if (!IS_ERR(mmc-supply.vqmmc) + !test_bit(DW_MMC_IO_POWERED, slot-flags)) { You can use regulator_is_enabled() instead of flag bit, DW_MMC_IO_POWERED. I'd be a little worried about regulator_is_enabled() since regulators are reference counted. What if someone else is sharing this regulator? The regulator might happen to be enabled when you check it but unless you add your own dw_mmc reference count they might turn it off. Cool, that's a possibility. Some assumption may need. If mmc's core can guarantee its balance, I think we don't need to consider some flag. I notice that the mmc core seems to keep a flag itself for vdd (the mmc-regulator_enabled flag). That would imply that the core thought it was important to have the extra flag and that we should keep our own flag for vqmmc. Ok, Good. Thanks, Seungwon Jeon -Doug -- To unsubscribe from this list: send the line unsubscribe linux-mmc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html -- To unsubscribe from this list: send the line unsubscribe linux-samsung-soc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
RE: [PATCH 1/3] mmc: dw_mmc: use mmc_regulator_get_supply to handle regulators
Hi Doug, On Thu, June 26, 2014, Doug Anderson wrote: Seungwon, On Wed, Jun 25, 2014 at 4:18 AM, Seungwon Jeon tgih@samsung.com wrote: + case MMC_POWER_ON: + if (!IS_ERR(mmc-supply.vqmmc) + !test_bit(DW_MMC_IO_POWERED, slot-flags)) { You can use regulator_is_enabled() instead of flag bit, DW_MMC_IO_POWERED. I'd be a little worried about regulator_is_enabled() since regulators are reference counted. What if someone else is sharing this regulator? The regulator might happen to be enabled when you check it but unless you add your own dw_mmc reference count they might turn it off. Cool, that's a possibility. Some assumption may need. If mmc's core can guarantee its balance, I think we don't need to consider some flag. Thanks, Seungwon Jeon Important thing is that if powering vmmc failed at MMC_POWER_UP, vqmmc should not be powered. Good point. -- To unsubscribe from this list: send the line unsubscribe linux-mmc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html -- To unsubscribe from this list: send the line unsubscribe linux-samsung-soc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
RE: [PATCH 3/3] mmc: dw_mmc: Support voltage changes
On Thu, June 26, 2014, Doug Anderson wrote: Seungwon, On Wed, Jun 25, 2014 at 6:08 AM, Seungwon Jeon tgih@samsung.com wrote: On Mon, June 23, 2014, Yuvaraj Kumar C D wrote: Subject: [PATCH 3/3] mmc: dw_mmc: Support voltage changes From: Doug Anderson diand...@chromium.org For UHS cards we need the ability to switch voltages from 3.3V to 1.8V. Add support to the dw_mmc driver to handle this. Note that dw_mmc needs a little bit of extra code since the interface needs a special bit programmed to the CMD register while CMD11 is progressing. This means adding a few extra states to the state machine to track. Overall new additional states makes it complicated. Can we do that in other way? That was the best I was able to figure out when I thought this through. If you have ideas for doing it another way I'd imagine that Yuvaraj would be happy to take your feedback. Let's clean up SDMMC_CMD_VOLT_SWITCH. In turn, we may remove state-handling simply. Signed-off-by: Doug Anderson diand...@chromium.org Signed-off-by: Yuvaraj Kumar C D yuvaraj...@samsung.com --- drivers/mmc/host/dw_mmc.c | 145 +--- drivers/mmc/host/dw_mmc.h |5 +- include/linux/mmc/dw_mmc.h |2 + 3 files changed, 142 insertions(+), 10 deletions(-) diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index e034bce..38eb548 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c @@ -29,6 +29,7 @@ #include linux/irq.h #include linux/mmc/host.h #include linux/mmc/mmc.h +#include linux/mmc/sd.h #include linux/mmc/sdio.h #include linux/mmc/dw_mmc.h #include linux/bitops.h @@ -235,10 +236,13 @@ err: } #endif /* defined(CONFIG_DEBUG_FS) */ +static void mci_send_cmd(struct dw_mci_slot *slot, u32 cmd, u32 arg); + static u32 dw_mci_prepare_command(struct mmc_host *mmc, struct mmc_command *cmd) { struct mmc_data *data; struct dw_mci_slot *slot = mmc_priv(mmc); + struct dw_mci *host = slot-host; const struct dw_mci_drv_data *drv_data = slot-host-drv_data; u32 cmdr; cmd-error = -EINPROGRESS; @@ -254,6 +258,32 @@ static u32 dw_mci_prepare_command(struct mmc_host *mmc, struct mmc_command *cmd) else if (cmd-opcode != MMC_SEND_STATUS cmd-data) cmdr |= SDMMC_CMD_PRV_DAT_WAIT; + if (cmd-opcode == SD_SWITCH_VOLTAGE) { + u32 clk_en_a; + + /* Special bit makes CMD11 not die */ + cmdr |= SDMMC_CMD_VOLT_SWITCH; + + /* Change state to continue to handle CMD11 weirdness */ + WARN_ON(slot-host-state != STATE_SENDING_CMD); + slot-host-state = STATE_SENDING_CMD11; + + /* + * We need to disable clock stop while doing voltage switch + * according to 7.4.1.2 Voltage Switch Normal Scenario. + * + * It's assumed that by the next time the CLKENA is updated + * (when we set the clock next) that the voltage change will + * be over, so we don't bother setting any bits to synchronize + * with dw_mci_setup_bus(). + */ + clk_en_a = mci_readl(host, CLKENA); + clk_en_a = ~(SDMMC_CLKEN_LOW_PWR slot-id); + mci_writel(host, CLKENA, clk_en_a); + mci_send_cmd(slot, SDMMC_CMD_UPD_CLK | + SDMMC_CMD_PRV_DAT_WAIT, 0); dw_mci_disable_low_power() can be used here. Ah. I guess we don't have that locally anymore. Locally we have variants on: I'm checking on cjb/mmc branch. * https://patchwork.kernel.org/patch/3070311/ * https://patchwork.kernel.org/patch/3070251/ * https://patchwork.kernel.org/patch/3070221/ ...which removed that function. ...but I guess upstream never picked up those patches, huh? Looking back it looks like you had some feedback and it needed another spin but somehow fell off my plate. :( Maybe this is something Yuvaraj would like to pick up? It's long ago. I remember that there is no progress since my last comment. In case of patch 3070221, I want to pick up for next Kernel. + } + if (cmd-flags MMC_RSP_PRESENT) { /* We expect a response, so set this bit */ cmdr |= SDMMC_CMD_RESP_EXP; @@ -776,11 +806,15 @@ static void dw_mci_setup_bus(struct dw_mci_slot *slot, bool force_clkinit) unsigned int clock = slot-clock; u32 div; u32 clk_en_a; + u32 sdmmc_cmd_bits = SDMMC_CMD_UPD_CLK | SDMMC_CMD_PRV_DAT_WAIT; + + /* We must continue to set bit 28 in CMD until the change is complete */ + if (host-state == STATE_WAITING_CMD11_DONE) + sdmmc_cmd_bits |= SDMMC_CMD_VOLT_SWITCH; I didn't get the reason SDMMC_CMD_VOLT_SWITCH is needed during clock update(enable/disable) Can
RE: [PATCH 1/3] mmc: dw_mmc: use mmc_regulator_get_supply to handle regulators
dw_mci_init_slot(struct dw_mci *host, unsigned int id) err_setup_bus: mmc_free_host(mmc); - return -EINVAL; + return ret; } static void dw_mci_cleanup_slot(struct dw_mci_slot *slot, unsigned int id) @@ -2375,24 +2407,6 @@ int dw_mci_probe(struct dw_mci *host) } } - host-vmmc = devm_regulator_get_optional(host-dev, vmmc); - if (IS_ERR(host-vmmc)) { - ret = PTR_ERR(host-vmmc); - if (ret == -EPROBE_DEFER) - goto err_clk_ciu; - - dev_info(host-dev, no vmmc regulator found: %d\n, ret); - host-vmmc = NULL; - } else { - ret = regulator_enable(host-vmmc); - if (ret) { - if (ret != -EPROBE_DEFER) - dev_err(host-dev, - regulator_enable fail: %d\n, ret); - goto err_clk_ciu; - } - } - host-quirks = host-pdata-quirks; spin_lock_init(host-lock); @@ -2536,8 +2550,6 @@ err_workqueue: err_dmaunmap: if (host-use_dma host-dma_ops-exit) host-dma_ops-exit(host); - if (host-vmmc) - regulator_disable(host-vmmc); err_clk_ciu: if (!IS_ERR(host-ciu_clk)) @@ -2573,9 +2585,6 @@ void dw_mci_remove(struct dw_mci *host) if (host-use_dma host-dma_ops-exit) host-dma_ops-exit(host); - if (host-vmmc) - regulator_disable(host-vmmc); - if (!IS_ERR(host-ciu_clk)) clk_disable_unprepare(host-ciu_clk); @@ -2592,9 +2601,6 @@ EXPORT_SYMBOL(dw_mci_remove); */ int dw_mci_suspend(struct dw_mci *host) { - if (host-vmmc) - regulator_disable(host-vmmc); - Just to check: have you tested suspend/resume with the various combinations of keep-power-in-suspend and non-removable with your patch. I remember some of the logic being a bit complicated... Please check it and give some updates/result in next version. Thanks, Seungwon Jeon return 0; } EXPORT_SYMBOL(dw_mci_suspend); @@ -2603,15 +2609,6 @@ int dw_mci_resume(struct dw_mci *host) { int i, ret; - if (host-vmmc) { - ret = regulator_enable(host-vmmc); - if (ret) { - dev_err(host-dev, - failed to enable regulator: %d\n, ret); - return ret; - } - } - if (!dw_mci_ctrl_all_reset(host)) { ret = -ENODEV; return ret; diff --git a/drivers/mmc/host/dw_mmc.h b/drivers/mmc/host/dw_mmc.h index 738fa24..5c95d00 100644 --- a/drivers/mmc/host/dw_mmc.h +++ b/drivers/mmc/host/dw_mmc.h As I mentioned in my previous review, you should be removing struct regulator *vmmc; /* Power regulator */ from struct dw_mci since you're no longer populating it. @@ -225,6 +225,8 @@ struct dw_mci_slot { unsigned long flags; #define DW_MMC_CARD_PRESENT0 #define DW_MMC_CARD_NEED_INIT 1 +#define DW_MMC_CARD_POWERED2 +#define DW_MMC_IO_POWERED 3 I don't really think you should have two bits here. From my understanding of SD cards there should be very little reason to have vqmmc and vmmc not powered at the same time. If vqmmc is powered but vmmc is not powered then you'll get leakage and the card can pull power through the IO lines which is bad for the card. I don't think that powering vmmc without vqmmc for a short time is terribly bad but I can't quite see a good use case. Essentially you're powering the card but not able to talk to it, right? I'm not sure what the state of the IO lines would be (either driven low or floating) since presumably the pullups on the lines are powered by vqmmc too. int id; int last_detect_state; }; -- To unsubscribe from this list: send the line unsubscribe linux-mmc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html -- To unsubscribe from this list: send the line unsubscribe linux-mmc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html -- To unsubscribe from this list: send the line unsubscribe linux-samsung-soc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
RE: [PATCH 3/3] mmc: dw_mmc: Support voltage changes
(unsigned long priv) switch (state) { case STATE_IDLE: + case STATE_WAITING_CMD11_DONE: break; + case STATE_SENDING_CMD11: case STATE_SENDING_CMD: if (!test_and_clear_bit(EVENT_CMD_COMPLETE, host-pending_events)) @@ -1870,6 +1986,15 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id) } if (pending) { + /* Check volt switch first, since it can look like an error */ + if ((host-state == STATE_SENDING_CMD11) + (pending SDMMC_INT_VOLT_SWITCH)) { + mci_writel(host, RINTSTS, SDMMC_INT_VOLT_SWITCH); + pending = ~SDMMC_INT_VOLT_SWITCH; + dw_mci_cmd_interrupt(host, + pending | SDMMC_INT_CMD_DONE); Artificially adding SDMMC_INT_CMD_DONE to pending is needed to complete cmd handling? Is there any reason? Thanks, Seungwon Jeon + } + if (pending DW_MCI_CMD_ERROR_FLAGS) { mci_writel(host, RINTSTS, DW_MCI_CMD_ERROR_FLAGS); host-cmd_status = pending; @@ -1975,7 +2100,9 @@ static void dw_mci_work_routine_card(struct work_struct *work) switch (host-state) { case STATE_IDLE: + case STATE_WAITING_CMD11_DONE: break; + case STATE_SENDING_CMD11: case STATE_SENDING_CMD: mrq-cmd-error = -ENOMEDIUM; if (!mrq-data) diff --git a/drivers/mmc/host/dw_mmc.h b/drivers/mmc/host/dw_mmc.h index 5c95d00..af1d35f 100644 --- a/drivers/mmc/host/dw_mmc.h +++ b/drivers/mmc/host/dw_mmc.h @@ -99,6 +99,7 @@ #define SDMMC_INT_HLEBIT(12) #define SDMMC_INT_FRUN BIT(11) #define SDMMC_INT_HTOBIT(10) +#define SDMMC_INT_VOLT_SWITCHBIT(10) /* overloads bit 10! */ #define SDMMC_INT_DRTO BIT(9) #define SDMMC_INT_RTOBIT(8) #define SDMMC_INT_DCRC BIT(7) @@ -113,6 +114,7 @@ /* Command register defines */ #define SDMMC_CMD_START BIT(31) #define SDMMC_CMD_USE_HOLD_REG BIT(29) +#define SDMMC_CMD_VOLT_SWITCHBIT(28) #define SDMMC_CMD_CCS_EXPBIT(23) #define SDMMC_CMD_CEATA_RD BIT(22) #define SDMMC_CMD_UPD_CLKBIT(21) @@ -129,6 +131,7 @@ #define SDMMC_CMD_INDX(n)((n) 0x1F) /* Status register defines */ #define SDMMC_GET_FCNT(x)(((x)17) 0x1FFF) +#define SDMMC_STATUS_BUSYBIT(9) /* FIFOTH register defines */ #define SDMMC_SET_FIFOTH(m, r, t)(((m) 0x7) 28 | \ ((r) 0xFFF) 16 | \ @@ -149,7 +152,7 @@ #define SDMMC_GET_VERID(x) ((x) 0x) /* Card read threshold */ #define SDMMC_SET_RD_THLD(v, x) (((v) 0x1FFF) 16 | (x)) - +#define SDMMC_UHS_18VBIT(0) /* Register access macros */ #define mci_readl(dev, reg) \ __raw_readl((dev)-regs + SDMMC_##reg) diff --git a/include/linux/mmc/dw_mmc.h b/include/linux/mmc/dw_mmc.h index babaea9..9e31564 100644 --- a/include/linux/mmc/dw_mmc.h +++ b/include/linux/mmc/dw_mmc.h @@ -26,6 +26,8 @@ enum dw_mci_state { STATE_DATA_BUSY, STATE_SENDING_STOP, STATE_DATA_ERROR, + STATE_SENDING_CMD11, + STATE_WAITING_CMD11_DONE, }; enum { -- 1.7.10.4 -- To unsubscribe from this list: send the line unsubscribe linux-mmc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html -- To unsubscribe from this list: send the line unsubscribe linux-samsung-soc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
RE: [PATCHv3 3/4] mmc: dw_mmc: remove the supports-highspeed property.
On Fri, May 30, 2014, Jaehoon Chung wrote: Hi, Ulf. On 05/30/2014 05:01 PM, Ulf Hansson wrote: On 28 May 2014 07:35, Jaehoon Chung jh80.ch...@samsung.com wrote: Removed the parser for supports-highspeed. It can be parsed with cap-mmc-highsped or cap-sd-highspeed at mmc_of_parse(). Signed-off-by: Jaehoon Chung jh80.ch...@samsung.com --- drivers/mmc/host/dw_mmc.c |3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index 3285bdd..34b5210 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c @@ -2281,9 +2281,6 @@ static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host) return ERR_PTR(ret); } - if (of_find_property(np, supports-highspeed, NULL)) - pdata-caps |= MMC_CAP_SD_HIGHSPEED | MMC_CAP_MMC_HIGHSPEED; - According to DT guys, normally we shouldn't remove DT bindings. Thus, you need to keep this, unless you can get some of the DT guys to ack it. As you mentioned, this patch didn't need, right? Though, you still want to move the DTs to use common mmc bindings. And you could mark the documentation of the above binding as deprecated. I added the comment for deprecated into dw-mmc dt-binding doc file. [PATCHv3,4/4] ARM: dts: replace the slot property into slot sub-node for dwmmc. I think this patch can be discarded. then everything is ok.!? :) Once decided to turn common mmc bindings instead of driver-specific, host driver shall not need old one. I think we can remove it. Thanks, Seungwon Jeon If i'm wrong, let me know, plz. Thank you for sharing the information. Best Regards, Jaehoon Chung Kind regards Ulf Hansson -- To unsubscribe from this list: send the line unsubscribe linux-mmc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html -- To unsubscribe from this list: send the line unsubscribe linux-samsung-soc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
RE: [PATCHv3 2/4] mmc: dw_mmc: use the __mmc_of_parse to parse the slot node
On Wed, May 28, 2014, Jaehoon Chung wrote: dw-mmc controller has the multiple slot. Then it needs to parse the property for each slot. Signed-off-by: Jaehoon Chung jh80.ch...@samsung.com Acked-by: Seungwon Jeon tgih@samsung.com Thanks, Seungwon Jeon --- Changelog V3: - Fix typo. - Maintained the dw_mci_of_quirks(). Changelog V2: - None drivers/mmc/host/dw_mmc.c | 15 ++- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index 1ac227c..3285bdd 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c @@ -1015,12 +1015,11 @@ static int dw_mci_get_cd(struct mmc_host *mmc) { int present; struct dw_mci_slot *slot = mmc_priv(mmc); - struct dw_mci_board *brd = slot-host-pdata; struct dw_mci *host = slot-host; int gpio_cd = mmc_gpio_get_cd(mmc); /* Use platform get_cd function, else try onboard card detect */ - if (brd-quirks DW_MCI_QUIRK_BROKEN_CARD_DETECTION) + if (slot-quirks DW_MCI_QUIRK_BROKEN_CARD_DETECTION) present = 1; else if (!IS_ERR_VALUE(gpio_cd)) present = gpio_cd; @@ -2010,6 +2009,9 @@ static struct dw_mci_of_slot_quirks { { .quirk = disable-wp, .id = DW_MCI_SLOT_QUIRK_NO_WRITE_PROTECT, + }, { + .quirk = broken-cd, + .id = DW_MCI_QUIRK_BROKEN_CARD_DETECTION, }, }; @@ -2088,7 +2090,7 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id) if (host-pdata-caps2) mmc-caps2 = host-pdata-caps2; - mmc_of_parse(mmc); + __mmc_of_parse(mmc, dw_mci_of_find_slot_node(host-dev, slot-id)); if (host-pdata-blk_settings) { mmc-max_segs = host-pdata-blk_settings-max_segs; @@ -2234,12 +2236,7 @@ static inline bool dw_mci_ctrl_all_reset(struct dw_mci *host) static struct dw_mci_of_quirks { char *quirk; int id; -} of_quirks[] = { - { - .quirk = broken-cd, - .id = DW_MCI_QUIRK_BROKEN_CARD_DETECTION, - }, -}; +} of_quirks[] = {}; static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host) { -- 1.7.9.5 -- To unsubscribe from this list: send the line unsubscribe linux-mmc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html -- To unsubscribe from this list: send the line unsubscribe linux-samsung-soc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
RE: [PATCHv3 3/4] mmc: dw_mmc: remove the supports-highspeed property.
On Wed, May 28, 2014, Jaehoon Chung wrote: Removed the parser for supports-highspeed. It can be parsed with cap-mmc-highsped or cap-sd-highspeed at mmc_of_parse(). Signed-off-by: Jaehoon Chung jh80.ch...@samsung.com Acked-by: Seungwon Jeon tgih@samsung.com Tahnks, Seungwon Jeon --- drivers/mmc/host/dw_mmc.c |3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index 3285bdd..34b5210 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c @@ -2281,9 +2281,6 @@ static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host) return ERR_PTR(ret); } - if (of_find_property(np, supports-highspeed, NULL)) - pdata-caps |= MMC_CAP_SD_HIGHSPEED | MMC_CAP_MMC_HIGHSPEED; - return pdata; } -- 1.7.9.5 -- To unsubscribe from this list: send the line unsubscribe linux-mmc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html -- To unsubscribe from this list: send the line unsubscribe linux-samsung-soc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
RE: [PATCHv3 4/4] ARM: dts: replace the slot property into slot sub-node for dwmmc.
+ Dinh Nguyen dingu...@altera.com + Heiko Stuebner he...@sntech.de On Wed, May 28, 2014, Jaehoon Chung wrote: dw-mmc controller can support the multiple slot. So each slot's property can be difference. And support-highspeed property in dw-mmc is deprecated. support-highspeed property can be replaced to cap-sd/mmc-highspeed. Signed-off-by: Jaehoon Chung jh80.ch...@samsung.com Looks good to me. Acked-by: Seungwon Jeon tgih@samsung.com Thanks, Seungwon Jeon --- Changelog V3: - Merge [PATCH 2/5] mmc: dw_mmc: rmove the supports-highspeed property Changelog V2: - None .../devicetree/bindings/mmc/exynos-dw-mshc.txt |5 +++-- .../devicetree/bindings/mmc/k3-dw-mshc.txt |3 ++- .../devicetree/bindings/mmc/synopsys-dw-mshc.txt |6 -- arch/arm/boot/dts/exynos4412-odroidx.dts |4 ++-- arch/arm/boot/dts/exynos4412-origen.dts|4 ++-- arch/arm/boot/dts/exynos4412-trats2.dts|6 +++--- arch/arm/boot/dts/exynos5250-arndale.dts |6 +++--- arch/arm/boot/dts/exynos5250-cros-common.dtsi | 10 +- arch/arm/boot/dts/exynos5250-smdk5250.dts |6 +++--- arch/arm/boot/dts/exynos5420-arndale-octa.dts |6 +++--- arch/arm/boot/dts/exynos5420-smdk5420.dts |4 ++-- arch/arm/boot/dts/rk3066a-bqcurie2.dts |2 +- arch/arm/boot/dts/socfpga_arria5.dtsi |5 +++-- arch/arm/boot/dts/socfpga_cyclone5.dtsi|5 +++-- arch/arm/boot/dts/socfpga_vt.dts |5 +++-- 15 files changed, 42 insertions(+), 35 deletions(-) diff --git a/Documentation/devicetree/bindings/mmc/exynos-dw-mshc.txt b/Documentation/devicetree/bindings/mmc/exynos-dw-mshc.txt index 532b1d4..41cc703 100644 --- a/Documentation/devicetree/bindings/mmc/exynos-dw-mshc.txt +++ b/Documentation/devicetree/bindings/mmc/exynos-dw-mshc.txt @@ -69,8 +69,6 @@ Example: dwmmc0@1220 { num-slots = 1; - supports-highspeed; - broken-cd; fifo-depth = 0x80; card-detect-delay = 200; samsung,dw-mshc-ciu-div = 3; @@ -85,5 +83,8 @@ Example: gpc1 2 2 3 3, gpc1 3 2 3 3, gpc0 3 2 3 3, gpc0 4 2 3 3, gpc0 5 2 3 3, gpc0 6 2 3 3; + broken-cd; + cap-mmc-highspeed; + cap-sd-highspeed; }; }; diff --git a/Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt b/Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt index b8653ea..b1844c5 100644 --- a/Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt +++ b/Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt @@ -34,7 +34,6 @@ Example: num-slots = 1; vmmc-supply = ldo12; fifo-depth = 0x100; - supports-highspeed; pinctrl-names = default; pinctrl-0 = sd_pmx_pins sd_cfg_func1 sd_cfg_func2; slot@0 { @@ -42,5 +41,7 @@ Example: bus-width = 4; disable-wp; cd-gpios = gpio10 3 0; + cap-mmc-highspeed; + cap-sd-highspeed; }; }; diff --git a/Documentation/devicetree/bindings/mmc/synopsys-dw-mshc.txt b/Documentation/devicetree/bindings/mmc/synopsys-dw-mshc.txt index 2d4a725..ff393ab 100644 --- a/Documentation/devicetree/bindings/mmc/synopsys-dw-mshc.txt +++ b/Documentation/devicetree/bindings/mmc/synopsys-dw-mshc.txt @@ -67,7 +67,8 @@ Optional properties: * card-detect-delay: Delay in milli-seconds before detecting card after card insert event. The default value is 0. -* supports-highspeed: Enables support for high speed cards (up to 50MHz) +* supports-highspeed (DEPRECATED): Enables support for high speed cards (up to 50MHz) +(use cap-mmc-highspeed or cap-sd-highspeed instead) * broken-cd: as documented in mmc core bindings. @@ -98,7 +99,6 @@ board specific portions as listed below. clock-frequency = 4; clock-freq-min-max = 40 2; num-slots = 1; - supports-highspeed; broken-cd; fifo-depth = 0x80; card-detect-delay = 200; @@ -107,5 +107,7 @@ board specific portions as listed below. slot@0 { reg = 0; bus-width = 8; + cap-mmc-highspeed; + cap-sd-highspeed; }; }; diff --git a/arch/arm/boot/dts/exynos4412-odroidx.dts b/arch/arm/boot/dts/exynos4412-odroidx.dts index 31db28a..fb2cd8d 100644 --- a/arch/arm/boot/dts/exynos4412-odroidx.dts +++ b/arch/arm/boot/dts/exynos4412-odroidx.dts @@ -45,8 +45,6
RE: [PATCHv2 1/3] mmc: host: add slot argument to mmc_of_parse
On Mon, May 26, 2014, Jaehoon Chung wrote: From: Ludovic Desroches ludovic.desroc...@atmel.com Some hosts manage several slots. In these case information such as the bus width, chip detect and others are into the slot node. So we have to parse child node. If not NULL, slot node will be used instead of the device node. Signed-off-by: Ludovic Desroches ludovic.desroc...@atmel.com Signed-off-by: Jaehoon Chung jh80.ch...@samsung.com Acked-by: Seungwon Jeon tgih@samsung.com Thanks, Seungwon Jeon --- Changelog V2: - Fix the typo. drivers/mmc/core/host.c | 13 + include/linux/mmc/host.h | 10 +- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c index 95cceae..0f677b3 100644 --- a/drivers/mmc/core/host.c +++ b/drivers/mmc/core/host.c @@ -298,15 +298,17 @@ static inline void mmc_host_clk_sysfs_init(struct mmc_host *host) #endif /** - * mmc_of_parse() - parse host's device-tree node + * __mmc_of_parse() - parse host's device-tree node * @host: host whose node should be parsed. + * @slot : some device provide several slots so the node to parse + * is not the host one. * * To keep the rest of the MMC subsystem unaware of whether DT has been * used to to instantiate and configure this host instance or not, we * parse the properties and set respective generic mmc-host flags and * parameters. */ -int mmc_of_parse(struct mmc_host *host) +int __mmc_of_parse(struct mmc_host *host, struct device_node *slot) { struct device_node *np; u32 bus_width; @@ -317,7 +319,10 @@ int mmc_of_parse(struct mmc_host *host) if (!host-parent || !host-parent-of_node) return 0; - np = host-parent-of_node; + if (slot) + np = slot; + else + np = host-parent-of_node; /* bus-width is translated to MMC_CAP_*_BIT_DATA flags */ if (of_property_read_u32(np, bus-width, bus_width) 0) { @@ -459,7 +464,7 @@ out: return ret; } -EXPORT_SYMBOL(mmc_of_parse); +EXPORT_SYMBOL(__mmc_of_parse); /** * mmc_alloc_host - initialise the per-host structure. diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h index 7960424..c62af91 100644 --- a/include/linux/mmc/host.h +++ b/include/linux/mmc/host.h @@ -372,7 +372,15 @@ struct mmc_host *mmc_alloc_host(int extra, struct device *); int mmc_add_host(struct mmc_host *); void mmc_remove_host(struct mmc_host *); void mmc_free_host(struct mmc_host *); -int mmc_of_parse(struct mmc_host *host); +int __mmc_of_parse(struct mmc_host *host, struct device_node *slot); +/* + * mmc_of_parse - parse host's device-tree node + * @host: host whose node should be parsed. + */ +static inline int mmc_of_parse(struct mmc_host *host) +{ + return __mmc_of_parse(host, NULL); +} static inline void *mmc_priv(struct mmc_host *host) { -- 1.7.9.5 -- To unsubscribe from this list: send the line unsubscribe linux-mmc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html -- To unsubscribe from this list: send the line unsubscribe linux-samsung-soc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
RE: [PATCHv2 2/3] mmc: dw_mmc: use the __mmc_of_parse to parse the slot node
Hi Jaehoon, On Mon, May 26, 2014, Jaehoon Chung wrote: dw-mmc controller have the multiple slot. Have - has? Then it needs to parse the property for each slot. Signed-off-by: Jaehoon Chung jh80.ch...@samsung.com --- Changelog V2: - None drivers/mmc/host/dw_mmc.c | 25 ++--- 1 file changed, 6 insertions(+), 19 deletions(-) diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index 1ac227c..d4800f8 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c @@ -1015,12 +1015,11 @@ static int dw_mci_get_cd(struct mmc_host *mmc) { int present; struct dw_mci_slot *slot = mmc_priv(mmc); - struct dw_mci_board *brd = slot-host-pdata; struct dw_mci *host = slot-host; int gpio_cd = mmc_gpio_get_cd(mmc); /* Use platform get_cd function, else try onboard card detect */ - if (brd-quirks DW_MCI_QUIRK_BROKEN_CARD_DETECTION) + if (slot-quirks DW_MCI_QUIRK_BROKEN_CARD_DETECTION) present = 1; else if (!IS_ERR_VALUE(gpio_cd)) present = gpio_cd; @@ -2010,6 +2009,9 @@ static struct dw_mci_of_slot_quirks { { .quirk = disable-wp, .id = DW_MCI_SLOT_QUIRK_NO_WRITE_PROTECT, + }, { + .quirk = broken-cd, + .id = DW_MCI_QUIRK_BROKEN_CARD_DETECTION, }, }; @@ -2088,7 +2090,7 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id) if (host-pdata-caps2) mmc-caps2 = host-pdata-caps2; - mmc_of_parse(mmc); + __mmc_of_parse(mmc, dw_mci_of_find_slot_node(host-dev, slot-id)); if (host-pdata-blk_settings) { mmc-max_segs = host-pdata-blk_settings-max_segs; @@ -2231,23 +2233,13 @@ static inline bool dw_mci_ctrl_all_reset(struct dw_mci *host) } #ifdef CONFIG_OF -static struct dw_mci_of_quirks { - char *quirk; - int id; -} of_quirks[] = { - { - .quirk = broken-cd, - .id = DW_MCI_QUIRK_BROKEN_CARD_DETECTION, - }, -}; - Moving broken-cd to slot_quirks is reasonable. But I think of_quirks should be kept and we can add right quirks. In cae of DW_MCI_QUIRK_IDMAC_DTO and DW_MCI_QUIRK_RETRY_DELAY, we can handle those with dw_mci_of_quirks although we didn't add. static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host) { struct dw_mci_board *pdata; struct device *dev = host-dev; struct device_node *np = dev-of_node; const struct dw_mci_drv_data *drv_data = host-drv_data; - int idx, ret; + int ret; u32 clock_frequency; pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); @@ -2264,11 +2256,6 @@ static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host) pdata-num_slots = 1; } - /* get quirks */ - for (idx = 0; idx ARRAY_SIZE(of_quirks); idx++) - if (of_get_property(np, of_quirks[idx].quirk, NULL)) - pdata-quirks |= of_quirks[idx].id; - Same as above. Thanks, Seungwon Jeon if (of_property_read_u32(np, fifo-depth, pdata-fifo_depth)) dev_info(dev, fifo-depth property not found, using value of FIFOTH register as default\n); -- 1.7.9.5 -- To unsubscribe from this list: send the line unsubscribe linux-mmc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html -- To unsubscribe from this list: send the line unsubscribe linux-samsung-soc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
RE: [PATCHv2 3/3] ARM: dts: replace the broken-cd property into slot node for dwmmc.
Can this be merged with your another patch, [PATCH 2/5] mmc: dw_mmc: remove the supports-highspeed property.? On Mon, May 26, 2014, Jaehoon Chung wrote: dw-mmc controller can be support the multiple slot. can support, it would be better to correct the above message. Thanks, Seungwon Jeon So each slot's property can be difference. Signed-off-by: Jaehoon Chung jh80.ch...@samsung.com --- Changelog V2: - None arch/arm/boot/dts/exynos4412-odroidx.dts |2 +- arch/arm/boot/dts/exynos4412-origen.dts |2 +- arch/arm/boot/dts/exynos4412-trats2.dts |4 ++-- arch/arm/boot/dts/exynos5250-arndale.dts |2 +- arch/arm/boot/dts/exynos5250-cros-common.dtsi |4 ++-- arch/arm/boot/dts/exynos5250-smdk5250.dts |2 +- arch/arm/boot/dts/exynos5420-arndale-octa.dts |2 +- arch/arm/boot/dts/rk3066a-bqcurie2.dts|2 +- arch/arm/boot/dts/socfpga_arria5.dtsi |2 +- arch/arm/boot/dts/socfpga_cyclone5.dtsi |2 +- arch/arm/boot/dts/socfpga_vt.dts |2 +- 11 files changed, 13 insertions(+), 13 deletions(-) diff --git a/arch/arm/boot/dts/exynos4412-odroidx.dts b/arch/arm/boot/dts/exynos4412-odroidx.dts index 31db28a..24ec351 100644 --- a/arch/arm/boot/dts/exynos4412-odroidx.dts +++ b/arch/arm/boot/dts/exynos4412-odroidx.dts @@ -46,7 +46,6 @@ num-slots = 1; supports-highspeed; - broken-cd; card-detect-delay = 200; samsung,dw-mshc-ciu-div = 3; samsung,dw-mshc-sdr-timing = 2 3; @@ -55,6 +54,7 @@ slot@0 { reg = 0; bus-width = 8; + broken-cd; }; }; diff --git a/arch/arm/boot/dts/exynos4412-origen.dts b/arch/arm/boot/dts/exynos4412-origen.dts index e2c0dca..ed712a6 100644 --- a/arch/arm/boot/dts/exynos4412-origen.dts +++ b/arch/arm/boot/dts/exynos4412-origen.dts @@ -129,7 +129,6 @@ num-slots = 1; supports-highspeed; - broken-cd; card-detect-delay = 200; samsung,dw-mshc-ciu-div = 3; samsung,dw-mshc-sdr-timing = 2 3; @@ -138,6 +137,7 @@ slot@0 { reg = 0; bus-width = 8; + broken-cd; }; }; diff --git a/arch/arm/boot/dts/exynos4412-trats2.dts b/arch/arm/boot/dts/exynos4412-trats2.dts index 73be464..37c3cb3 100644 --- a/arch/arm/boot/dts/exynos4412-trats2.dts +++ b/arch/arm/boot/dts/exynos4412-trats2.dts @@ -460,8 +460,6 @@ mmc@1255 { num-slots = 1; supports-highspeed; - broken-cd; - non-removable; card-detect-delay = 200; vmmc-supply = vemmc_reg; clock-frequency = 4; @@ -475,6 +473,8 @@ slot@0 { reg = 0; bus-width = 8; + non-removable; + broken-cd; }; }; diff --git a/arch/arm/boot/dts/exynos5250-arndale.dts b/arch/arm/boot/dts/exynos5250-arndale.dts index 090f983..0c9a7da 100644 --- a/arch/arm/boot/dts/exynos5250-arndale.dts +++ b/arch/arm/boot/dts/exynos5250-arndale.dts @@ -400,7 +400,6 @@ status = okay; num-slots = 1; supports-highspeed; - broken-cd; card-detect-delay = 200; samsung,dw-mshc-ciu-div = 3; samsung,dw-mshc-sdr-timing = 2 3; @@ -412,6 +411,7 @@ slot@0 { reg = 0; bus-width = 8; + broken-cd; }; }; diff --git a/arch/arm/boot/dts/exynos5250-cros-common.dtsi b/arch/arm/boot/dts/exynos5250-cros- common.dtsi index 2c1560d..7ab3b94 100644 --- a/arch/arm/boot/dts/exynos5250-cros-common.dtsi +++ b/arch/arm/boot/dts/exynos5250-cros-common.dtsi @@ -249,7 +249,6 @@ mmc@1220 { num-slots = 1; supports-highspeed; - broken-cd; card-detect-delay = 200; samsung,dw-mshc-ciu-div = 3; samsung,dw-mshc-sdr-timing = 2 3; @@ -260,6 +259,7 @@ slot@0 { reg = 0; bus-width = 8; + broken-cd; }; }; @@ -283,7 +283,6 @@ mmc@1223 { num-slots = 1; supports-highspeed; - broken-cd; card-detect-delay = 200; samsung,dw-mshc-ciu-div = 3; samsung,dw-mshc-sdr-timing = 2 3; @@ -293,6 +292,7 @@ slot@0 { reg = 0; bus-width = 4; + broken-cd; }; }; diff --git a/arch/arm
RE: [PATCH] mmc: dw_mmc: Make sure we don't get stuck when we get an error
On Wed, May 21, 2014, Doug Anderson wrote: Seungwon, On Mon, May 19, 2014 at 6:51 PM, Seungwon Jeon tgih@samsung.com wrote: + } else { + /* +* If we don't have a command complete now we'll +* never get one since we just reset everything; +* better end the request. +* +* If we do have a command complete we'll fall +* through to the SENDING_STOP command and +* everything will be peachy keen. +* +* TODO: I guess we shouldn't send a stop? Please remove TODO: OK We already reset controller in dw_mci_data_complete() through mmc: dw_mmc: change to use recommended reset procedure? I guess it depends on that patch. Then, we don't need to stop sequence anymore. Even without that patch we've still pretty much stopped everything in dw_mci_fifo_reset(), so I'm not sure there's any strong dependency. ...but in our tree this did land after the patch you mention, so you could wait until it lands if you want. ciu-reset or stop/abort cmd is needed for recovery of controller FSM after getting error. dw_mci_fifo_reset eventually has ciu-reset from that patch. I think it's fine to apply after that. NOTE: We found that on some machines we were getting warnings after enabling tuning and using this patch. The warnings were benign, but we should probably squash the fix into this patch. See https://chromium-review.googlesource.com/#/c/200652/ for details. Can it be accessible? Thanks, Seungwon Jeon -Doug -- To unsubscribe from this list: send the line unsubscribe linux-mmc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html -- To unsubscribe from this list: send the line unsubscribe linux-samsung-soc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
RE: [PATCH v2] mmc: dw_mmc: Make sure we don't get stuck when we get an error
On Wed, May 21, 2014, Doug Anderson wrote: If we happened to get a data error at just the wrong time the dw_mmc driver could get into a state where it would never complete its request. That would leave the caller just hanging there. We fix this two ways and both of the two fixes on their own appear to fix the problems we've seen: 1. Fix a race in the tasklet where the interrupt setting the data error happens _just after_ we check for it, then we get a EVENT_XFER_COMPLETE. We fix this by repeating a bit of code. 2. Fix it so that if we detect that we've got an error in the data busy state and we're not going to do anything else we end the request and unblock anyone waiting. Signed-off-by: Doug Anderson diand...@chromium.org Signed-off-by: Yuvaraj Kumar C D yuvaraj...@gmail.com It will be applied after mmc: dw_mmc: change to use recommended reset procedure Acked-by: Seungwon Jeon tgih@samsung.com Thanks, Seungwon Jeon --- Changes in v2: - Removed TODO - Set cmd to NULL before calling dw_mci_request_end() drivers/mmc/host/dw_mmc.c | 46 ++ 1 file changed, 46 insertions(+) diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index cced599..54ec8b0 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c @@ -1318,6 +1318,14 @@ static void dw_mci_tasklet_func(unsigned long priv) /* fall through */ case STATE_SENDING_DATA: + /* + * We could get a data error and never a transfer + * complete so we'd better check for it here. + * + * Note that we don't really care if we also got a + * transfer complete; stopping the DMA and sending an + * abort won't hurt. + */ if (test_and_clear_bit(EVENT_DATA_ERROR, host-pending_events)) { dw_mci_stop_dma(host); @@ -1331,7 +1339,29 @@ static void dw_mci_tasklet_func(unsigned long priv) break; set_bit(EVENT_XFER_COMPLETE, host-completed_events); + + /* + * Handle an EVENT_DATA_ERROR that might have shown up + * before the transfer completed. This might not have + * been caught by the check above because the interrupt + * could have gone off between the previous check and + * the check for transfer complete. + * + * Technically this ought not be needed assuming we + * get a DATA_COMPLETE eventually (we'll notice the + * error and end the request), but it shouldn't hurt. + * + * This has the advantage of sending the stop command. + */ + if (test_and_clear_bit(EVENT_DATA_ERROR, +host-pending_events)) { + dw_mci_stop_dma(host); + send_stop_abort(host, data); + state = STATE_DATA_ERROR; + break; + } prev_state = state = STATE_DATA_BUSY; + /* fall through */ case STATE_DATA_BUSY: @@ -1354,6 +1384,22 @@ static void dw_mci_tasklet_func(unsigned long priv) /* stop command for open-ended transfer*/ if (data-stop) send_stop_abort(host, data); + } else { + /* + * If we don't have a command complete now we'll + * never get one since we just reset everything; + * better end the request. + * + * If we do have a command complete we'll fall + * through to the SENDING_STOP command and + * everything will be peachy keen. + */ + if (!test_bit(EVENT_CMD_COMPLETE, + host-pending_events)) { + host-cmd = NULL; + dw_mci_request_end(host, mrq); + goto unlock; + } } /* -- 1.9.1.423.g4596e3a -- To unsubscribe from this list: send the line unsubscribe linux-mmc in the body of a message to majord...@vger.kernel.org More
RE: [PATCH] mmc: dw_mmc: Make sure we don't get stuck when we get an error
On Sat, May 17, 2014, Doug Anderson wrote: Seungwon, On Thu, May 15, 2014 at 6:46 PM, Seungwon Jeon tgih@samsung.com wrote: On Wed, May 14, 2014, Doug Anderson wrote: Seungwon, On Mon, May 12, 2014 at 9:52 PM, Seungwon Jeon tgih@samsung.com wrote: Hi Doug, On Tue, May 13, 2014, Doug Anderson wrote: Seungwon, On Sat, May 10, 2014 at 7:11 AM, Seungwon Jeon tgih@samsung.com wrote: On Fri, May 09, 2014, Sonny Rao wrote: On Thu, May 8, 2014 at 2:42 AM, Yuvaraj Kumar yuvaraj...@gmail.com wrote: Any comments on this patch? I'll just add that without this fix, running the tuning loop for UHS modes is not reliable on dw_mmc because errors will happen and you will eventually hit this race and hang. This can happen any time there is tuning like during boot or during resume from suspend. On Thu, Mar 27, 2014 at 11:48 AM, Yuvaraj Kumar C D yuvaraj...@gmail.com wrote: From: Doug Anderson diand...@chromium.org If we happened to get a data error at just the wrong time the dw_mmc driver could get into a state where it would never complete its request. That would leave the caller just hanging there. We fix this two ways and both of the two fixes on their own appear to fix the problems we've seen: 1. Fix a race in the tasklet where the interrupt setting the data error happens _just after_ we check for it, then we get a EVENT_XFER_COMPLETE. We fix this by repeating a bit of code. I think repeating is not good approach to fix race. In your case, XFER_COMPLETE preceded data error and DTO didn't come? It seems strange case. I want to know actual error value if you can reproduce. XFER_COMPLETE didn't necessarily precede data error. Imagine this scenario: 1. Check for data error: nope 2. Interrupt happens and we get a data error and immediately xfer complete 3. Check for xfer complete: yup That's the state that we are handling. The system that dw_mmc uses where the interrupt handler has no locking makes it incredibly difficult to get things right. Can you propose an alternate fix that would avoid the race? Thank you for detailed scenario. You're right. Have you consider using spin_lock() in interrupt handler? Then, we'll need to change spin_lock() to spin_lock_irqsave() in tasklet func. And other locks in driver may need to be adjusted properly. I have certainly considered it and I think it's the right way to go, but I believe that this would be a pretty massive change to the design of dw_mmc. Someone appeared to try very hard not to use a spinlock in the interrupt handler and came up with the whole tasklet / pending events / completed events to deal with it. Yes. It might be not small changes. Moreover, it needs to test heavily. But it should be done before long. As we experienced, there are some race issue in current way. Will you update this patch? Please let me know. I would prefer not to, but I will if I need to. As you say, adding a spinlock to the IRQ handler will need to be tested heavily and I'm not sure we're in the best position to do that. I can send up the change to use a spinlock with some minimal testing if you want, though. ...of perhaps Yuvaraj can since he's the one who's been sending this patch upstream. Note that the original change was quite hard to test. The problem would show up on certain boards easier than others and would show up with certain revisions of the kernel but not with others. In other words: it was heavily timing dependent. The current patch as-is has been tested and shown to be stable for quite a while now. In this particular case it would be pretty easy to just add the spinlock around the data error / xfer complete checks, though once we have a spinlock here it seems like we'd want to start using it in other places. It would be confusing if the interrupt handler grabbed a spinlock the whole time but then only used it to protect a single small check. I'm really curious, though, why this driver can't just use a threaded irq handler and eliminate the whole interrupt / tasklet split. That seems saner in the long run. I think dw_mmc conforms itself to typical driver's implementation, which it may be about a choice of driver's design. Yup, there are a lot of different valid ways to accomplish the same thing in the kernel. ...but some of the ways drivers do things are historical and are not the suggested way of doing things anymore. I'm still a kernel noob in many ways (despite a few years of working with it), so I may be mistaken. To me it feels like the interrupt + tasklet is effectively reinventing threaded interrupts, but doing it in a custom way. Although it may not be graceful way, this patch is plainly effective. We can expect more in the next
RE: [PATCHv2] mmc: dw_mmc: change to use recommended reset procedure
On Sat, May 17, 2014, Sonny Rao wrote: On Tue, May 13, 2014 at 4:09 AM, Seungwon Jeon tgih@samsung.com wrote: On Tuesday, May 13, Sonny Rao wrote: On Mon, May 12, 2014 at 10:02 PM, Seungwon Jeon tgih@samsung.com wrote: As I mentioned in previous version, you put all reset stuff in existing fifo_reset function. Although databook mentions ciu_reset case for SBE error, it's not obvious when ciu_reset is needed in other error cases. If you intend to add some robust error handing, it would be better to make another function. The document I have actually doesn't mention error cases, it describes this procedure as Controller/DMA/FIFO Reset Usage so I believe it is saying this is the correct procedure in all cases, and based on our testing it seems to work. I understand the skepticism, as I shared it initially when I saw this, but based on our experience, this is correct and it doesn't need to live in a separate function. I agree this active error handling. But, existing fifo_reset function is focused on fifo reset purely. I think your change is close to error recovery and it seems overloaded to basic function. So, you suggest renaming function for new sequence. I think the documentation says it should always be done, not just in error recovery. I can rename the function to dw_mci_reset rather than dw_mci_fifo_reset. Is that what you mean? Or do you mean make a new function that is only called in error cases? Both are okay. And look into dw_mci_work_routine_card(). dw_mci_idmac_reset() is redundancy. I expect it can be cleaned. Quot /* Clear down the FIFO */ dw_mci_fifo_reset(host); #ifdef CONFIG_MMC_DW_IDMAC dw_mci_idmac_reset(host); #endif /Quot Ok, I'll remove that extra reset, thanks for catching. Please check my comments below. On Tue, May 13, 2014, Sonny Rao wrote: This patch changes the fifo reset code to follow the reset procedure outlined in the documentation of Synopsys Mobile storage host databook 7.2.13. Please remove this section number. No needed. It's old version. Ok v2: Add Generic DMA support per the documentation, move interrupt clear before wait make the test for DMA host-use_dma rather than host-using_dma add proper return values (although it appears no caller checks) Signed-off-by: Sonny Rao sonny...@chromium.org Signed-off-by: Yuvaraj Kumar C D yuvaraj...@samsung.com --- drivers/mmc/host/dw_mmc.c | 55 ++- drivers/mmc/host/dw_mmc.h | 1 + 2 files changed, 55 insertions(+), 1 deletion(-) diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index 55cd110..aff57e1 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c @@ -2325,6 +2325,7 @@ static bool dw_mci_ctrl_reset(struct dw_mci *host, u32 reset) static inline bool dw_mci_fifo_reset(struct dw_mci *host) { + u32 flags = SDMMC_CTRL_RESET | SDMMC_CTRL_FIFO_RESET; /* * Reseting generates a block interrupt, hence setting * the scatter-gather pointer to NULL. @@ -2334,7 +2335,59 @@ static inline bool dw_mci_fifo_reset(struct dw_mci *host) host-sg = NULL; } - return dw_mci_ctrl_reset(host, SDMMC_CTRL_FIFO_RESET); + /* + * The recommended method for resetting is to always reset the + * controller and the fifo, but differs slightly depending on the mode. + * The Generic DMA mode (non IDMAC) also needs to reset DMA where IDMAC + * mode resets IDMAC at the end. + * + */ +#ifndef CONFIG_MMC_DW_IDMAC Is it added for generic DMA? IDMAC should be considered for dma_reseet as well. Please check databook. Yeah it's a little unclear. In the 7.2.13 Controller/DMA/FIFO Reset Usage part of the document they mention It is set for what they call generic DMA, which I think is when there is an external DMA controller, and the part below that it says for DW-DMA/Non-DW-DMA that controller_reset and fifo_reset should be set. I believe this DW-DMA case refers to what is called IDMAC. So, I think it's not required for this case, but I admit I'm not sure why they also say Non-DW-DMA. If you know of a good way to differentiate the Generic DMA case I can implement it. It wasn't clear to me if the driver even supported this generic dma case, but it sounds like it might, so I added this code. In practice, on the Exynos Systems we have, which are using IDMAC, the reset procedure seems to work okay without the dma_reset bit set, but I cannot test this generic dma case. The other places in the doc where I see them mention the dma_reset bit are 7.2.21 Transmission and Reception with Internal DMAC
RE: [PATCH] mmc: dw_mmc: Make sure we don't get stuck when we get an error
On Tue, May 13, 2014, Seungwon Jeon wrote: Hi Doug, On Tue, May 13, 2014, Doug Anderson wrote: Seungwon, On Sat, May 10, 2014 at 7:11 AM, Seungwon Jeon tgih@samsung.com wrote: On Fri, May 09, 2014, Sonny Rao wrote: On Thu, May 8, 2014 at 2:42 AM, Yuvaraj Kumar yuvaraj...@gmail.com wrote: Any comments on this patch? I'll just add that without this fix, running the tuning loop for UHS modes is not reliable on dw_mmc because errors will happen and you will eventually hit this race and hang. This can happen any time there is tuning like during boot or during resume from suspend. On Thu, Mar 27, 2014 at 11:48 AM, Yuvaraj Kumar C D yuvaraj...@gmail.com wrote: From: Doug Anderson diand...@chromium.org If we happened to get a data error at just the wrong time the dw_mmc driver could get into a state where it would never complete its request. That would leave the caller just hanging there. We fix this two ways and both of the two fixes on their own appear to fix the problems we've seen: 1. Fix a race in the tasklet where the interrupt setting the data error happens _just after_ we check for it, then we get a EVENT_XFER_COMPLETE. We fix this by repeating a bit of code. I think repeating is not good approach to fix race. In your case, XFER_COMPLETE preceded data error and DTO didn't come? It seems strange case. I want to know actual error value if you can reproduce. XFER_COMPLETE didn't necessarily precede data error. Imagine this scenario: 1. Check for data error: nope 2. Interrupt happens and we get a data error and immediately xfer complete 3. Check for xfer complete: yup That's the state that we are handling. The system that dw_mmc uses where the interrupt handler has no locking makes it incredibly difficult to get things right. Can you propose an alternate fix that would avoid the race? Thank you for detailed scenario. You're right. Have you consider using spin_lock() in interrupt handler? Then, we'll need to change spin_lock() to spin_lock_irqsave() in tasklet func. And other locks in driver may need to be adjusted properly. To return above scenario: 1. Check for data error: nope 2. Check for xfer complete: nope - escape tasklet. 3. Interrupt happens and we get a data error and immediately xfer complete 4. Check for data error (Again in tasklet) : yup How about this change? Thanks, Seungwon Jeon 2. Fix it so that if we detect that we've got an error in the data busy state and we're not going to do anything else we end the request and unblock anyone waiting. Signed-off-by: Doug Anderson diand...@chromium.org Signed-off-by: Yuvaraj Kumar C D yuvaraj...@gmail.com --- drivers/mmc/host/dw_mmc.c | 47 + 1 file changed, 47 insertions(+) diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index 1d77431..4c589f1 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c @@ -1300,6 +1300,14 @@ static void dw_mci_tasklet_func(unsigned long priv) /* fall through */ case STATE_SENDING_DATA: + /* +* We could get a data error and never a transfer +* complete so we'd better check for it here. +* +* Note that we don't really care if we also got a +* transfer complete; stopping the DMA and sending an +* abort won't hurt. +*/ if (test_and_clear_bit(EVENT_DATA_ERROR, host-pending_events)) { dw_mci_stop_dma(host); @@ -1313,7 +1321,29 @@ static void dw_mci_tasklet_func(unsigned long priv) break; set_bit(EVENT_XFER_COMPLETE, host-completed_events); + + /* +* Handle an EVENT_DATA_ERROR that might have shown up +* before the transfer completed. This might not have +* been caught by the check above because the interrupt +* could have gone off between the previous check and +* the check for transfer complete. +* +* Technically this ought not be needed assuming we +* get a DATA_COMPLETE eventually (we'll notice the +* error and end the request), but it shouldn't hurt
RE: [PATCH] mmc: dw_mmc: Make sure we don't get stuck when we get an error
On Wed, May 14, 2014, Doug Anderson wrote: Seungwon, On Mon, May 12, 2014 at 9:52 PM, Seungwon Jeon tgih@samsung.com wrote: Hi Doug, On Tue, May 13, 2014, Doug Anderson wrote: Seungwon, On Sat, May 10, 2014 at 7:11 AM, Seungwon Jeon tgih@samsung.com wrote: On Fri, May 09, 2014, Sonny Rao wrote: On Thu, May 8, 2014 at 2:42 AM, Yuvaraj Kumar yuvaraj...@gmail.com wrote: Any comments on this patch? I'll just add that without this fix, running the tuning loop for UHS modes is not reliable on dw_mmc because errors will happen and you will eventually hit this race and hang. This can happen any time there is tuning like during boot or during resume from suspend. On Thu, Mar 27, 2014 at 11:48 AM, Yuvaraj Kumar C D yuvaraj...@gmail.com wrote: From: Doug Anderson diand...@chromium.org If we happened to get a data error at just the wrong time the dw_mmc driver could get into a state where it would never complete its request. That would leave the caller just hanging there. We fix this two ways and both of the two fixes on their own appear to fix the problems we've seen: 1. Fix a race in the tasklet where the interrupt setting the data error happens _just after_ we check for it, then we get a EVENT_XFER_COMPLETE. We fix this by repeating a bit of code. I think repeating is not good approach to fix race. In your case, XFER_COMPLETE preceded data error and DTO didn't come? It seems strange case. I want to know actual error value if you can reproduce. XFER_COMPLETE didn't necessarily precede data error. Imagine this scenario: 1. Check for data error: nope 2. Interrupt happens and we get a data error and immediately xfer complete 3. Check for xfer complete: yup That's the state that we are handling. The system that dw_mmc uses where the interrupt handler has no locking makes it incredibly difficult to get things right. Can you propose an alternate fix that would avoid the race? Thank you for detailed scenario. You're right. Have you consider using spin_lock() in interrupt handler? Then, we'll need to change spin_lock() to spin_lock_irqsave() in tasklet func. And other locks in driver may need to be adjusted properly. I have certainly considered it and I think it's the right way to go, but I believe that this would be a pretty massive change to the design of dw_mmc. Someone appeared to try very hard not to use a spinlock in the interrupt handler and came up with the whole tasklet / pending events / completed events to deal with it. Yes. It might be not small changes. Moreover, it needs to test heavily. But it should be done before long. As we experienced, there are some race issue in current way. Will you update this patch? Please let me know. In this particular case it would be pretty easy to just add the spinlock around the data error / xfer complete checks, though once we have a spinlock here it seems like we'd want to start using it in other places. It would be confusing if the interrupt handler grabbed a spinlock the whole time but then only used it to protect a single small check. I'm really curious, though, why this driver can't just use a threaded irq handler and eliminate the whole interrupt / tasklet split. That seems saner in the long run. I think dw_mmc conforms itself to typical driver's implementation, which it may be about a choice of driver's design. To return above scenario: 1. Check for data error: nope 2. Check for xfer complete: nope - escape tasklet. 3. Interrupt happens and we get a data error and immediately xfer complete 4. Check for data error (Again in tasklet) : yup How about this change? I'm not sure I understand. Are you suggesting a change to my code, or wondering how my code handles the above scenario? Ah, the above-mentioned steps describes scenario when changing lock scheme. Thanks, Seungwon I think your scenario works find either with or without my patch. -Doug -- To unsubscribe from this list: send the line unsubscribe linux-mmc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html -- To unsubscribe from this list: send the line unsubscribe linux-samsung-soc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
RE: [PATCHv2] mmc: dw_mmc: change to use recommended reset procedure
On Tuesday, May 13, Sonny Rao wrote: On Mon, May 12, 2014 at 10:02 PM, Seungwon Jeon tgih@samsung.com wrote: As I mentioned in previous version, you put all reset stuff in existing fifo_reset function. Although databook mentions ciu_reset case for SBE error, it's not obvious when ciu_reset is needed in other error cases. If you intend to add some robust error handing, it would be better to make another function. The document I have actually doesn't mention error cases, it describes this procedure as Controller/DMA/FIFO Reset Usage so I believe it is saying this is the correct procedure in all cases, and based on our testing it seems to work. I understand the skepticism, as I shared it initially when I saw this, but based on our experience, this is correct and it doesn't need to live in a separate function. I agree this active error handling. But, existing fifo_reset function is focused on fifo reset purely. I think your change is close to error recovery and it seems overloaded to basic function. So, you suggest renaming function for new sequence. And look into dw_mci_work_routine_card(). dw_mci_idmac_reset() is redundancy. I expect it can be cleaned. Quot /* Clear down the FIFO */ dw_mci_fifo_reset(host); #ifdef CONFIG_MMC_DW_IDMAC dw_mci_idmac_reset(host); #endif /Quot Please check my comments below. On Tue, May 13, 2014, Sonny Rao wrote: This patch changes the fifo reset code to follow the reset procedure outlined in the documentation of Synopsys Mobile storage host databook 7.2.13. Please remove this section number. No needed. It's old version. v2: Add Generic DMA support per the documentation, move interrupt clear before wait make the test for DMA host-use_dma rather than host-using_dma add proper return values (although it appears no caller checks) Signed-off-by: Sonny Rao sonny...@chromium.org Signed-off-by: Yuvaraj Kumar C D yuvaraj...@samsung.com --- drivers/mmc/host/dw_mmc.c | 55 ++- drivers/mmc/host/dw_mmc.h | 1 + 2 files changed, 55 insertions(+), 1 deletion(-) diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index 55cd110..aff57e1 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c @@ -2325,6 +2325,7 @@ static bool dw_mci_ctrl_reset(struct dw_mci *host, u32 reset) static inline bool dw_mci_fifo_reset(struct dw_mci *host) { + u32 flags = SDMMC_CTRL_RESET | SDMMC_CTRL_FIFO_RESET; /* * Reseting generates a block interrupt, hence setting * the scatter-gather pointer to NULL. @@ -2334,7 +2335,59 @@ static inline bool dw_mci_fifo_reset(struct dw_mci *host) host-sg = NULL; } - return dw_mci_ctrl_reset(host, SDMMC_CTRL_FIFO_RESET); + /* + * The recommended method for resetting is to always reset the + * controller and the fifo, but differs slightly depending on the mode. + * The Generic DMA mode (non IDMAC) also needs to reset DMA where IDMAC + * mode resets IDMAC at the end. + * + */ +#ifndef CONFIG_MMC_DW_IDMAC Is it added for generic DMA? IDMAC should be considered for dma_reseet as well. Please check databook. Yeah it's a little unclear. In the 7.2.13 Controller/DMA/FIFO Reset Usage part of the document they mention It is set for what they call generic DMA, which I think is when there is an external DMA controller, and the part below that it says for DW-DMA/Non-DW-DMA that controller_reset and fifo_reset should be set. I believe this DW-DMA case refers to what is called IDMAC. So, I think it's not required for this case, but I admit I'm not sure why they also say Non-DW-DMA. If you know of a good way to differentiate the Generic DMA case I can implement it. It wasn't clear to me if the driver even supported this generic dma case, but it sounds like it might, so I added this code. In practice, on the Exynos Systems we have, which are using IDMAC, the reset procedure seems to work okay without the dma_reset bit set, but I cannot test this generic dma case. The other places in the doc where I see them mention the dma_reset bit are 7.2.21 Transmission and Reception with Internal DMAC (IDMAC) and the description of the CTRL register, and in 7.1 Software/Hardware Restrictions where they say it will terminate any pending transfer. DW-DMA means Synopsys's DMA controller not IDMAC. SDMMC_CTRL_DMA_RESET can apply in all type DMA interface. + if (host-use_dma) + flags |= SDMMC_CTRL_DMA_RESET; +#endif + if (dw_mci_ctrl_reset(host, flags)) { + /* + * In all cases we clear the RAWINTS register to clear any + * interrupts. + */ I think interrupt masking is needed before reset
RE: [PATCH] mmc: dw_mmc: Make sure we don't get stuck when we get an error
Hi Doug, On Tue, May 13, 2014, Doug Anderson wrote: Seungwon, On Sat, May 10, 2014 at 7:11 AM, Seungwon Jeon tgih@samsung.com wrote: On Fri, May 09, 2014, Sonny Rao wrote: On Thu, May 8, 2014 at 2:42 AM, Yuvaraj Kumar yuvaraj...@gmail.com wrote: Any comments on this patch? I'll just add that without this fix, running the tuning loop for UHS modes is not reliable on dw_mmc because errors will happen and you will eventually hit this race and hang. This can happen any time there is tuning like during boot or during resume from suspend. On Thu, Mar 27, 2014 at 11:48 AM, Yuvaraj Kumar C D yuvaraj...@gmail.com wrote: From: Doug Anderson diand...@chromium.org If we happened to get a data error at just the wrong time the dw_mmc driver could get into a state where it would never complete its request. That would leave the caller just hanging there. We fix this two ways and both of the two fixes on their own appear to fix the problems we've seen: 1. Fix a race in the tasklet where the interrupt setting the data error happens _just after_ we check for it, then we get a EVENT_XFER_COMPLETE. We fix this by repeating a bit of code. I think repeating is not good approach to fix race. In your case, XFER_COMPLETE preceded data error and DTO didn't come? It seems strange case. I want to know actual error value if you can reproduce. XFER_COMPLETE didn't necessarily precede data error. Imagine this scenario: 1. Check for data error: nope 2. Interrupt happens and we get a data error and immediately xfer complete 3. Check for xfer complete: yup That's the state that we are handling. The system that dw_mmc uses where the interrupt handler has no locking makes it incredibly difficult to get things right. Can you propose an alternate fix that would avoid the race? Thank you for detailed scenario. You're right. Have you consider using spin_lock() in interrupt handler? Then, we'll need to change spin_lock() to spin_lock_irqsave() in tasklet func. And other locks in driver may need to be adjusted properly. To return above scenario: 1. Check for data error: nope 2. Check for xfer complete: nope - escape tasklet. 3. Interrupt happens and we get a data error and immediately xfer complete 4. Check for data error (Again in tasklet) : yup How about this change? Thanks, Seungwon Jeon 2. Fix it so that if we detect that we've got an error in the data busy state and we're not going to do anything else we end the request and unblock anyone waiting. Signed-off-by: Doug Anderson diand...@chromium.org Signed-off-by: Yuvaraj Kumar C D yuvaraj...@gmail.com --- drivers/mmc/host/dw_mmc.c | 47 + 1 file changed, 47 insertions(+) diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index 1d77431..4c589f1 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c @@ -1300,6 +1300,14 @@ static void dw_mci_tasklet_func(unsigned long priv) /* fall through */ case STATE_SENDING_DATA: + /* +* We could get a data error and never a transfer +* complete so we'd better check for it here. +* +* Note that we don't really care if we also got a +* transfer complete; stopping the DMA and sending an +* abort won't hurt. +*/ if (test_and_clear_bit(EVENT_DATA_ERROR, host-pending_events)) { dw_mci_stop_dma(host); @@ -1313,7 +1321,29 @@ static void dw_mci_tasklet_func(unsigned long priv) break; set_bit(EVENT_XFER_COMPLETE, host-completed_events); + + /* +* Handle an EVENT_DATA_ERROR that might have shown up +* before the transfer completed. This might not have +* been caught by the check above because the interrupt +* could have gone off between the previous check and +* the check for transfer complete. +* +* Technically this ought not be needed assuming we +* get a DATA_COMPLETE eventually (we'll notice the +* error and end the request), but it shouldn't hurt. +* +* This has the advantage of sending the stop command. +*/ + if (test_and_clear_bit(EVENT_DATA_ERROR
RE: [PATCHv2] mmc: dw_mmc: change to use recommended reset procedure
As I mentioned in previous version, you put all reset stuff in existing fifo_reset function. Although databook mentions ciu_reset case for SBE error, it's not obvious when ciu_reset is needed in other error cases. If you intend to add some robust error handing, it would be better to make another function. Please check my comments below. On Tue, May 13, 2014, Sonny Rao wrote: This patch changes the fifo reset code to follow the reset procedure outlined in the documentation of Synopsys Mobile storage host databook 7.2.13. v2: Add Generic DMA support per the documentation, move interrupt clear before wait make the test for DMA host-use_dma rather than host-using_dma add proper return values (although it appears no caller checks) Signed-off-by: Sonny Rao sonny...@chromium.org Signed-off-by: Yuvaraj Kumar C D yuvaraj...@samsung.com --- drivers/mmc/host/dw_mmc.c | 55 ++- drivers/mmc/host/dw_mmc.h | 1 + 2 files changed, 55 insertions(+), 1 deletion(-) diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index 55cd110..aff57e1 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c @@ -2325,6 +2325,7 @@ static bool dw_mci_ctrl_reset(struct dw_mci *host, u32 reset) static inline bool dw_mci_fifo_reset(struct dw_mci *host) { + u32 flags = SDMMC_CTRL_RESET | SDMMC_CTRL_FIFO_RESET; /* * Reseting generates a block interrupt, hence setting * the scatter-gather pointer to NULL. @@ -2334,7 +2335,59 @@ static inline bool dw_mci_fifo_reset(struct dw_mci *host) host-sg = NULL; } - return dw_mci_ctrl_reset(host, SDMMC_CTRL_FIFO_RESET); + /* + * The recommended method for resetting is to always reset the + * controller and the fifo, but differs slightly depending on the mode. + * The Generic DMA mode (non IDMAC) also needs to reset DMA where IDMAC + * mode resets IDMAC at the end. + * + */ +#ifndef CONFIG_MMC_DW_IDMAC Is it added for generic DMA? IDMAC should be considered for dma_reseet as well. Please check databook. + if (host-use_dma) + flags |= SDMMC_CTRL_DMA_RESET; +#endif + if (dw_mci_ctrl_reset(host, flags)) { + /* + * In all cases we clear the RAWINTS register to clear any + * interrupts. + */ I think interrupt masking is needed before reset because we will not handle it anymore. And Is there any reason to move interrupt clear here compared with previous version? + mci_writel(host, RINTSTS, 0x); + + /* if using dma we wait for dma_req to clear */ + if (host-use_dma) { + unsigned long timeout = jiffies + msecs_to_jiffies(500); + u32 status; + do { + status = mci_readl(host, STATUS); + if (!(status SDMMC_STATUS_DMA_REQ)) + break; + cpu_relax(); What did you intend here? If you intent busy-wait, how about using sleep instead? + } while (time_before(jiffies, timeout)); + + if (status SDMMC_STATUS_DMA_REQ) { + dev_err(host-dev, + %s: Timeout waiting for dma_req to + clear during reset, __func__); + return false; + } + + /* when using DMA next we reset the fifo again */ + dw_mci_ctrl_reset(host, SDMMC_CTRL_FIFO_RESET); + } + } else { + dev_err(host-dev, %s: Reset bits didn't clear, __func__); If ciu_reset is cleared, clk update below is needed? Thanks, Seungwon Jeon + return false; + } + +#ifdef CONFIG_MMC_DW_IDMAC + /* It is also recommended that we reset and reprogram idmac */ + dw_mci_idmac_reset(host); +#endif + + /* After a CTRL reset we need to have CIU set clock registers */ + mci_send_cmd(host-cur_slot, SDMMC_CMD_UPD_CLK, 0); + + return true; } static inline bool dw_mci_ctrl_all_reset(struct dw_mci *host) diff --git a/drivers/mmc/host/dw_mmc.h b/drivers/mmc/host/dw_mmc.h index 6bf24ab..2505804 100644 --- a/drivers/mmc/host/dw_mmc.h +++ b/drivers/mmc/host/dw_mmc.h @@ -129,6 +129,7 @@ #define SDMMC_CMD_INDX(n)((n) 0x1F) /* Status register defines */ #define SDMMC_GET_FCNT(x)(((x)17) 0x1FFF) +#define SDMMC_STATUS_DMA_REQ BIT(31) /* FIFOTH register defines */ #define SDMMC_SET_FIFOTH(m, r, t)(((m) 0x7) 28 | \ ((r) 0xFFF) 16 | \ -- 1.9.1.423.g4596e3a -- To unsubscribe from this list: send the line unsubscribe linux-mmc in the body of a message to majord
RE: [PATCH] mmc: dw_mmc: change to use recommended reset procedure
Hi Sonny, Can you separate procedure? Reset all are handled in fifo-reset. And ciu reset is always needed for error handling? Thanks, Seungwon Jeon On Sat, May 10, 2014, Sonny Rao wrote: On Fri, May 9, 2014 at 12:32 AM, Jaehoon Chung jh80.ch...@samsung.com wrote: Hi, Sonny. You can discard the my previous some comment. As you mentioned, this reset sequence is recommended at Synopsys TRM. Add the minor question. On 05/09/2014 01:27 PM, Jaehoon Chung wrote: Hi, Sonny. I have checked the Synopsys TRM.. On 05/09/2014 10:34 AM, Sonny Rao wrote: On Thu, May 8, 2014 at 6:15 PM, Jaehoon Chung jh80.ch...@samsung.com wrote: On 05/08/2014 06:40 PM, Yuvaraj Kumar wrote: Any comments on this patch? On Wed, Mar 26, 2014 at 5:16 PM, Yuvaraj Kumar C D yuvaraj...@gmail.com wrote: From: Sonny Rao sonny...@chromium.org This patch changes the fifo reset code to follow the reset procedure outlined in the documentation of Synopsys Mobile storage host databook 7.2.13. Without this patch, we could able to see eMMC was not detected after multiple reboots due to driver hangs while eMMC tuning for HS200. Signed-off-by: Sonny Rao sonny...@chromium.org Signed-off-by: Yuvaraj Kumar C D yuvaraj...@samsung.org --- drivers/mmc/host/dw_mmc.c | 48 - drivers/mmc/host/dw_mmc.h |1 + 2 files changed, 48 insertions(+), 1 deletion(-) diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index 32dd81d..1d77431 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c @@ -2220,7 +2220,53 @@ static inline bool dw_mci_fifo_reset(struct dw_mci *host) host-sg = NULL; } - return dw_mci_ctrl_reset(host, SDMMC_CTRL_FIFO_RESET); + /* +* The recommended method for resetting is to always reset the +* controller and the fifo, but differs slightly depending on the mode. +* Note that this doesn't handle the generic DMA (not IDMAC) case. +*/ not IDMAC is confused.. The documentation describes three different possible modes. There's a mode that doesn't use IDMAC but still does DMA. But as far as I can tell this driver doesn't support that way. We can just remove that wording if it's confusing. How did it know whether dma is generic DMA or not? That's a good question. I wasn't sure whether the driver supported it or not. It looks like it definitely supports IDMAC through the CONFIG_MMC_DW_IDMAC flag, but I wasn't sure if it was supported the generic dma. Maybe if CONFIG_MMC_DW_IDMAC isn't specified but host-dma_ops is not NULL then we are using the generic dma mode. + if (dw_mci_ctrl_reset(host, SDMMC_CTRL_RESET | SDMMC_CTRL_FIFO_RESET)) { + unsigned long timeout = jiffies + msecs_to_jiffies(500); + u32 status, rint; + + /* if using dma we wait for dma_req to clear */ + if (host-using_dma) { + do { + status = mci_readl(host, STATUS); + if (!(status SDMMC_STATUS_DMA_REQ)) + break; + cpu_relax(); + } while (time_before(jiffies, timeout)); + + if (status SDMMC_STATUS_DMA_REQ) + dev_err(host-dev, + %s: Timeout waiting for dma_req to + clear during reset, __func__); + + /* when using DMA next we reset the fifo again */ + dw_mci_ctrl_reset(host, SDMMC_CTRL_FIFO_RESET); + } + /* +* In all cases we clear the RAWINTS register to clear any +* interrupts. +*/ + rint = mci_readl(host, RINTSTS); + rint = rint (~mci_readl(host, MINTSTS)); you use the status or temp instead of rint. (you can reuse the variable.) And can use status = ~mci_readl(host,MINTSTS); Just clear the RINTSTS register? why do you add these? This will look at what is not masked, and only clear those bits. Well, i known if clear the RINTSTS register, recommended to use 0xfff and set the value for interrupt. Can be used 0xfff? Yeah we probably can. We just lose information about interrupts that were masked, but maybe we just don't care about any of them anyway, so it doesn't matter. Best Regards, Jaehoon Chung + if (rint) + mci_writel(host, RINTSTS, rint); + + } else + dev_err(host-dev, %s: Reset bits didn't clear, __func__); Just display the error log? I didn't understand this. If you displayed the error log
RE: [PATCH] mmc: dw_mmc: Make sure we don't get stuck when we get an error
command and +* everything will be peachy keen. +* +* TODO: I guess we shouldn't send a stop? +*/ + if (!test_bit(EVENT_CMD_COMPLETE, + host-pending_events)) { + dw_mci_request_end(host, mrq); + goto unlock; + } Can you explain what happens above? What is it for? Thanks, Seungwon Jeon -- To unsubscribe from this list: send the line unsubscribe linux-samsung-soc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
RE: [PATCH] ARM: dts: disable MDMA1 node for smdk5420 board
On Tue, April 22, 2014, Tushar Behera wrote: On 22 April 2014 07:48, Kukjin Kim kgene@samsung.com wrote: Seungwon Jeon wrote: + Javi Merino and Tushar Behera This change is similar to commit 3da355c(ARM: dts: Disable MDMA1 node for arndale-octa board). If MDMA1 region is configured with secure mode, it makes the boot failure with the following. Unhandled fault: imprecise external abort (0x1406) at 0x If so, how about adding the 'disabled' status in 5420 dtsi file? Then if 'enabling' is required, we can enable in each board dt file... That should be okay. While at it, we can remove the node disabling code from Arndale-Octa board DTS file. OK, I'll consider both. Thanks, Seungwon Jeon - Kukjin Signed-off-by: Seungwon Jeon tgih@samsung.com --- arch/arm/boot/dts/exynos5420-smdk5420.dts |6 ++ 1 files changed, 6 insertions(+), 0 deletions(-) diff --git a/arch/arm/boot/dts/exynos5420-smdk5420.dts b/arch/arm/boot/dts/exynos5420-smdk5420.dts index 6910485..9a48e3f 100644 --- a/arch/arm/boot/dts/exynos5420-smdk5420.dts +++ b/arch/arm/boot/dts/exynos5420-smdk5420.dts @@ -373,4 +373,10 @@ }; }; }; + + amba { + mdma1: mdma@11C1 { + status = disabled; + }; + }; }; -- 1.7.0.4 -- Tushar Behera -- To unsubscribe from this list: send the line unsubscribe linux-samsung-soc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2] ARM: dts: disable MDMA1 node for Exynos5420
This change places MDMA1 in disabled node for Exynos5420. If MDMA1 region is configured with secure mode, it makes the boot failure with the following on smdk5420 board. (Unhandled fault: imprecise external abort (0x1406) at 0x) Thus, arndale-octa board don't need to do the same thing anymore. Signed-off-by: Seungwon Jeon tgih@samsung.com --- Note: This patch comes from [PATCH] ARM: dts: disable MDMA1 node for smdk5420 board arch/arm/boot/dts/exynos5420-arndale-octa.dts | 12 arch/arm/boot/dts/exynos5420.dtsi |7 +++ 2 files changed, 7 insertions(+), 12 deletions(-) diff --git a/arch/arm/boot/dts/exynos5420-arndale-octa.dts b/arch/arm/boot/dts/exynos5420-arndale-octa.dts index 80a3bf4..896a2a6 100644 --- a/arch/arm/boot/dts/exynos5420-arndale-octa.dts +++ b/arch/arm/boot/dts/exynos5420-arndale-octa.dts @@ -364,16 +364,4 @@ gpio-key,wakeup; }; }; - - amba { - mdma1: mdma@11C1 { - /* -* MDMA1 can support both secure and non-secure -* AXI transactions. When this is enabled in the kernel -* for boards that run in secure mode, we are getting -* imprecise external aborts causing the kernel to oops. -*/ - status = disabled; - }; - }; }; diff --git a/arch/arm/boot/dts/exynos5420.dtsi b/arch/arm/boot/dts/exynos5420.dtsi index c3a9a66..97cbcdd 100644 --- a/arch/arm/boot/dts/exynos5420.dtsi +++ b/arch/arm/boot/dts/exynos5420.dtsi @@ -336,6 +336,13 @@ #dma-cells = 1; #dma-channels = 8; #dma-requests = 1; + /* +* MDMA1 can support both secure and non-secure +* AXI transactions. When this is enabled in the kernel +* for boards that run in secure mode, we are getting +* imprecise external aborts causing the kernel to oops. +*/ + status = disabled; }; }; -- 1.7.0.4 -- To unsubscribe from this list: send the line unsubscribe linux-samsung-soc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH] ARM: dts: disable MDMA1 node for smdk5420 board
This change is similar to commit 3da355c(ARM: dts: Disable MDMA1 node for arndale-octa board). If MDMA1 region is configured with secure mode, it makes the boot failure with the following. Unhandled fault: imprecise external abort (0x1406) at 0x Signed-off-by: Seungwon Jeon tgih@samsung.com --- arch/arm/boot/dts/exynos5420-smdk5420.dts |6 ++ 1 files changed, 6 insertions(+), 0 deletions(-) diff --git a/arch/arm/boot/dts/exynos5420-smdk5420.dts b/arch/arm/boot/dts/exynos5420-smdk5420.dts index 6910485..9a48e3f 100644 --- a/arch/arm/boot/dts/exynos5420-smdk5420.dts +++ b/arch/arm/boot/dts/exynos5420-smdk5420.dts @@ -373,4 +373,10 @@ }; }; }; + + amba { + mdma1: mdma@11C1 { + status = disabled; + }; + }; }; -- 1.7.0.4 -- To unsubscribe from this list: send the line unsubscribe linux-samsung-soc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
RE: [PATCH v2 4/7] mmc: dw_mmc: exynos: incorporate ciu_div into timing property
Hi Jaehoon, On Mon, April 14, 2014, Jaehoon Chung wrote: Hi, Seungwon. On 03/26/2014 08:31 PM, Seungwon Jeon wrote: ciu_div may not be common value for all speed mode. So, it needs to be attached to CLKSEL timing. Signed-off-by: Seungwon Jeon tgih@samsung.com --- drivers/mmc/host/dw_mmc-exynos.c | 75 ++ drivers/mmc/host/dw_mmc-exynos.h |1 + 2 files changed, 53 insertions(+), 23 deletions(-) diff --git a/drivers/mmc/host/dw_mmc-exynos.c b/drivers/mmc/host/dw_mmc-exynos.c index bab97e9..39f9114 100644 --- a/drivers/mmc/host/dw_mmc-exynos.c +++ b/drivers/mmc/host/dw_mmc-exynos.c @@ -39,6 +39,7 @@ struct dw_mci_exynos_priv_data { u8 ciu_div; u32 sdr_timing; u32 ddr_timing; + u32 hs200_timing; u32 cur_speed; }; @@ -64,6 +65,18 @@ static struct dw_mci_exynos_compatible { }, }; +static inline u8 dw_mci_exynos_get_ciu_div(struct dw_mci *host) +{ + struct dw_mci_exynos_priv_data *priv = host-priv; + + if (priv-ctrl_type == DW_MCI_TYPE_EXYNOS4412) + return EXYNOS4412_FIXED_CIU_CLK_DIV; + else if (priv-ctrl_type == DW_MCI_TYPE_EXYNOS4210) + return EXYNOS4210_FIXED_CIU_CLK_DIV; + else + return SDMMC_CLKSEL_GET_DIV(mci_readl(host, CLKSEL)) + 1; +} + static int dw_mci_exynos_priv_init(struct dw_mci *host) { struct dw_mci_exynos_priv_data *priv = host-priv; @@ -77,6 +90,8 @@ static int dw_mci_exynos_priv_init(struct dw_mci *host) SDMMC_MPSCTRL_NON_SECURE_WRITE_BIT); } + priv-ciu_div = dw_mci_exynos_get_ciu_div(host); + return 0; } @@ -84,7 +99,7 @@ static int dw_mci_exynos_setup_clock(struct dw_mci *host) { struct dw_mci_exynos_priv_data *priv = host-priv; - host-bus_hz /= (priv-ciu_div + 1); + host-bus_hz /= priv-ciu_div; return 0; } @@ -151,9 +166,10 @@ static void dw_mci_exynos_set_ios(struct dw_mci *host, struct mmc_ios *ios) struct dw_mci_exynos_priv_data *priv = host-priv; unsigned int wanted = ios-clock; unsigned long actual; - u8 div = priv-ciu_div + 1; - if (ios-timing == MMC_TIMING_MMC_DDR52) { + if (ios-timing == MMC_TIMING_MMC_HS200) { + mci_writel(host, CLKSEL, priv-hs200_timing); + } else if (ios-timing == MMC_TIMING_MMC_DDR52) { mci_writel(host, CLKSEL, priv-ddr_timing); /* Should be double rate for DDR mode */ if (ios-bus_width == MMC_BUS_WIDTH_8) @@ -174,6 +190,7 @@ static void dw_mci_exynos_set_ios(struct dw_mci *host, struct mmc_ios *ios) wanted = EXYNOS_CCLKIN_MIN; if (wanted != priv-cur_speed) { + u8 div = dw_mci_exynos_get_ciu_div(host); int ret = clk_set_rate(host-ciu_clk, wanted * div); if (ret) dev_warn(host-dev, @@ -186,14 +203,34 @@ static void dw_mci_exynos_set_ios(struct dw_mci *host, struct mmc_ios *ios) } } +static int dw_mci_exynos_dt_populate_timing(struct dw_mci *host, + unsigned int ctrl_type, + const char *propname, + u32 *out_values) +{ + struct device_node *np = host-dev-of_node; + u32 timing[3]; + int ret; + + ret = of_property_read_u32_array(np, propname, timing, 3); + if (ret) + return ret; + + if (ctrl_type == DW_MCI_TYPE_EXYNOS4412 || + ctrl_type == DW_MCI_TYPE_EXYNOS4210) + timing[2] = 0; + + *out_values = SDMMC_CLKSEL_TIMING(timing[0], timing[1], timing[2]); + + return 0; +} + + static int dw_mci_exynos_parse_dt(struct dw_mci *host) { struct dw_mci_exynos_priv_data *priv; struct device_node *np = host-dev-of_node; - u32 timing[2]; - u32 div = 0; - int idx; - int ret; + int idx, ret; priv = devm_kzalloc(host-dev, sizeof(*priv), GFP_KERNEL); if (!priv) { @@ -206,29 +243,21 @@ static int dw_mci_exynos_parse_dt(struct dw_mci *host) priv-ctrl_type = exynos_compat[idx].ctrl_type; } - if (priv-ctrl_type == DW_MCI_TYPE_EXYNOS4412) - priv-ciu_div = EXYNOS4412_FIXED_CIU_CLK_DIV - 1; - else if (priv-ctrl_type == DW_MCI_TYPE_EXYNOS4210) - priv-ciu_div = EXYNOS4210_FIXED_CIU_CLK_DIV - 1; - else { - of_property_read_u32(np, samsung,dw-mshc-ciu-div, div); - priv-ciu_div = div; - } Did you remove the property of ciu-div? I didn't find anywhere it's used, when this is removed. Then it needs to remove the properties into device-tree. And i want to maintain the property of ciu-div. The related patch has been posted
[PATCH v2 2/7] mmc: dw_mmc: exynos: don't use if clock isn't available
Add checking whether the clock is valid. Signed-off-by: Seungwon Jeon tgih@samsung.com --- drivers/mmc/host/dw_mmc-exynos.c | 11 +++ 1 files changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/mmc/host/dw_mmc-exynos.c b/drivers/mmc/host/dw_mmc-exynos.c index a67e784..a2d06c5 100644 --- a/drivers/mmc/host/dw_mmc-exynos.c +++ b/drivers/mmc/host/dw_mmc-exynos.c @@ -117,9 +117,9 @@ static int dw_mci_exynos_priv_init(struct dw_mci *host) static int dw_mci_exynos_setup_clock(struct dw_mci *host) { struct dw_mci_exynos_priv_data *priv = host-priv; - unsigned long rate = clk_get_rate(host-ciu_clk); - host-bus_hz = rate / (priv-ciu_div + 1); + host-bus_hz /= (priv-ciu_div + 1); + return 0; } @@ -196,8 +196,11 @@ static void dw_mci_exynos_set_ios(struct dw_mci *host, struct mmc_ios *ios) mci_writel(host, CLKSEL, priv-sdr_timing); } - /* Don't care if wanted clock is zero */ - if (!wanted) + /* +* Don't care if wanted clock is zero or +* ciu clock is unavailable +*/ + if (!wanted || IS_ERR(host-ciu_clk)) return; /* Guaranteed minimum frequency for cclkin */ -- 1.7.4.1 -- To unsubscribe from this list: send the line unsubscribe linux-samsung-soc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 1/7] mmc: dw_mmc: fix the max_blk_count in IDMAC
Even though 1MB is reserved for descriptor table in IDMAC, the dw_mmc host driver is allowed to receive only maximum 128KB block length in one request. This is caused by setting improper max_blk_count. It needs to be e adjusted so that descriptor table is used fully. It is found that the performance is improved with the increased the max_blk_count. Signed-off-by: Seungwon Jeon tgih@samsung.com --- drivers/mmc/host/dw_mmc.c |4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index 3a6721e..aeb38f9 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c @@ -2101,9 +2101,9 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id) #ifdef CONFIG_MMC_DW_IDMAC mmc-max_segs = host-ring_size; mmc-max_blk_size = 65536; - mmc-max_blk_count = host-ring_size; mmc-max_seg_size = 0x1000; - mmc-max_req_size = mmc-max_seg_size * mmc-max_blk_count; + mmc-max_req_size = mmc-max_seg_size * host-ring_size; + mmc-max_blk_count = mmc-max_req_size / 512; #else mmc-max_segs = 64; mmc-max_blk_size = 65536; /* BLKSIZ is 16 bits */ -- 1.7.4.1 -- To unsubscribe from this list: send the line unsubscribe linux-samsung-soc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 3/7] mmc: dw_mmc: exynos: move definitions to header file
Move some parts related to definition to header file. Signed-off-by: Seungwon Jeon tgih@samsung.com --- drivers/mmc/host/dw_mmc-exynos.c | 46 --- drivers/mmc/host/dw_mmc-exynos.h | 55 ++ 2 files changed, 61 insertions(+), 40 deletions(-) create mode 100644 drivers/mmc/host/dw_mmc-exynos.h diff --git a/drivers/mmc/host/dw_mmc-exynos.c b/drivers/mmc/host/dw_mmc-exynos.c index a2d06c5..bab97e9 100644 --- a/drivers/mmc/host/dw_mmc-exynos.c +++ b/drivers/mmc/host/dw_mmc-exynos.c @@ -21,42 +21,8 @@ #include dw_mmc.h #include dw_mmc-pltfm.h +#include dw_mmc-exynos.h -#define NUM_PINS(x)(x + 2) - -#define SDMMC_CLKSEL 0x09C -#define SDMMC_CLKSEL_CCLK_SAMPLE(x)(((x) 7) 0) -#define SDMMC_CLKSEL_CCLK_DRIVE(x) (((x) 7) 16) -#define SDMMC_CLKSEL_CCLK_DIVIDER(x) (((x) 7) 24) -#define SDMMC_CLKSEL_GET_DRV_WD3(x)(((x) 16) 0x7) -#define SDMMC_CLKSEL_TIMING(x, y, z) (SDMMC_CLKSEL_CCLK_SAMPLE(x) | \ - SDMMC_CLKSEL_CCLK_DRIVE(y) |\ - SDMMC_CLKSEL_CCLK_DIVIDER(z)) -#define SDMMC_CLKSEL_WAKEUP_INTBIT(11) - -#define EXYNOS4210_FIXED_CIU_CLK_DIV 2 -#define EXYNOS4412_FIXED_CIU_CLK_DIV 4 - -/* Block number in eMMC */ -#define DWMCI_BLOCK_NUM0x - -#define SDMMC_EMMCP_BASE 0x1000 -#define SDMMC_MPSECURITY (SDMMC_EMMCP_BASE + 0x0010) -#define SDMMC_MPSBEGIN0(SDMMC_EMMCP_BASE + 0x0200) -#define SDMMC_MPSEND0 (SDMMC_EMMCP_BASE + 0x0204) -#define SDMMC_MPSCTRL0 (SDMMC_EMMCP_BASE + 0x020C) - -/* SMU control bits */ -#define DWMCI_MPSCTRL_SECURE_READ_BIT BIT(7) -#define DWMCI_MPSCTRL_SECURE_WRITE_BIT BIT(6) -#define DWMCI_MPSCTRL_NON_SECURE_READ_BIT BIT(5) -#define DWMCI_MPSCTRL_NON_SECURE_WRITE_BIT BIT(4) -#define DWMCI_MPSCTRL_USE_FUSE_KEY BIT(3) -#define DWMCI_MPSCTRL_ECB_MODE BIT(2) -#define DWMCI_MPSCTRL_ENCRYPTION BIT(1) -#define DWMCI_MPSCTRL_VALIDBIT(0) - -#define EXYNOS_CCLKIN_MIN 5000/* unit: HZ */ /* Variations in Exynos specific dw-mshc controller */ enum dw_mci_exynos_type { @@ -104,11 +70,11 @@ static int dw_mci_exynos_priv_init(struct dw_mci *host) if (priv-ctrl_type == DW_MCI_TYPE_EXYNOS5420_SMU) { mci_writel(host, MPSBEGIN0, 0); - mci_writel(host, MPSEND0, DWMCI_BLOCK_NUM); - mci_writel(host, MPSCTRL0, DWMCI_MPSCTRL_SECURE_WRITE_BIT | - DWMCI_MPSCTRL_NON_SECURE_READ_BIT | - DWMCI_MPSCTRL_VALID | - DWMCI_MPSCTRL_NON_SECURE_WRITE_BIT); + mci_writel(host, MPSEND0, SDMMC_ENDING_SEC_NR_MAX); + mci_writel(host, MPSCTRL0, SDMMC_MPSCTRL_SECURE_WRITE_BIT | + SDMMC_MPSCTRL_NON_SECURE_READ_BIT | + SDMMC_MPSCTRL_VALID | + SDMMC_MPSCTRL_NON_SECURE_WRITE_BIT); } return 0; diff --git a/drivers/mmc/host/dw_mmc-exynos.h b/drivers/mmc/host/dw_mmc-exynos.h new file mode 100644 index 000..2554e2f --- /dev/null +++ b/drivers/mmc/host/dw_mmc-exynos.h @@ -0,0 +1,55 @@ +/* + * Exynos Specific Extensions for Synopsys DW Multimedia Card Interface driver + * + * Copyright (C) 2012-2014 Samsung Electronics Co., Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#ifndef _DW_MMC_EXYNOS_H_ +#define _DW_MMC_EXYNOS_H_ + +/* Extended Register's Offset */ +#define SDMMC_CLKSEL 0x09C + +/* CLKSEL register defines */ +#define SDMMC_CLKSEL_CCLK_SAMPLE(x)(((x) 7) 0) +#define SDMMC_CLKSEL_CCLK_DRIVE(x) (((x) 7) 16) +#define SDMMC_CLKSEL_CCLK_DIVIDER(x) (((x) 7) 24) +#define SDMMC_CLKSEL_GET_DRV_WD3(x)(((x) 16) 0x7) +#define SDMMC_CLKSEL_TIMING(x, y, z) (SDMMC_CLKSEL_CCLK_SAMPLE(x) | \ +SDMMC_CLKSEL_CCLK_DRIVE(y) | \ +SDMMC_CLKSEL_CCLK_DIVIDER(z)) +#define SDMMC_CLKSEL_WAKEUP_INTBIT(11) + +/* Protector Register */ +#define SDMMC_EMMCP_BASE 0x1000 +#define SDMMC_MPSECURITY (SDMMC_EMMCP_BASE + 0x0010) +#define SDMMC_MPSBEGIN0(SDMMC_EMMCP_BASE + 0x0200) +#define SDMMC_MPSEND0 (SDMMC_EMMCP_BASE + 0x0204) +#define SDMMC_MPSCTRL0 (SDMMC_EMMCP_BASE + 0x020C) + +/* SMU control defines */ +#define SDMMC_MPSCTRL_SECURE_READ_BIT BIT(7) +#define SDMMC_MPSCTRL_SECURE_WRITE_BIT BIT(6) +#define SDMMC_MPSCTRL_NON_SECURE_READ_BIT BIT(5) +#define SDMMC_MPSCTRL_NON_SECURE_WRITE_BIT BIT(4
[PATCH v2 6/7] ARM: dts: drop dw-mshc-ciu-div property from Exynos
As dw-mshc-ciu-div is strongly close to timing property, it is merged with each timing property. Signed-off-by: Seungwon Jeon tgih@samsung.com --- .../devicetree/bindings/mmc/exynos-dw-mshc.txt | 12 +--- arch/arm/boot/dts/exynos4412-odroidx.dts |5 ++--- arch/arm/boot/dts/exynos4412-origen.dts|5 ++--- arch/arm/boot/dts/exynos4412-trats2.dts|5 ++--- arch/arm/boot/dts/exynos5250-arndale.dts | 10 -- arch/arm/boot/dts/exynos5250-cros-common.dtsi | 15 ++- arch/arm/boot/dts/exynos5250-smdk5250.dts | 10 -- arch/arm/boot/dts/exynos5420-arndale-octa.dts | 10 -- arch/arm/boot/dts/exynos5420-smdk5420.dts | 10 -- 9 files changed, 33 insertions(+), 49 deletions(-) diff --git a/Documentation/devicetree/bindings/mmc/exynos-dw-mshc.txt b/Documentation/devicetree/bindings/mmc/exynos-dw-mshc.txt index 532b1d4..ca1914f 100644 --- a/Documentation/devicetree/bindings/mmc/exynos-dw-mshc.txt +++ b/Documentation/devicetree/bindings/mmc/exynos-dw-mshc.txt @@ -19,10 +19,6 @@ Required Properties: - samsung,exynos5420-dw-mshc: for controllers with Samsung Exynos5420 specific extensions. -* samsung,dw-mshc-ciu-div: Specifies the divider value for the card interface - unit (ciu) clock. This property is applicable only for Exynos5 SoC's and - ignored for Exynos4 SoC's. The valid range of divider value is 0 to 7. - * samsung,dw-mshc-sdr-timing: Specifies the value of CIU clock phase shift value in transmit mode and CIU clock phase shift value in receive mode for single data rate mode operation. Refer notes below for the order of the cells and the @@ -38,6 +34,9 @@ Required Properties: The order of the cells should be - First Cell: CIU clock phase shift value for tx mode. - Second Cell: CIU clock phase shift value for rx mode. + - Thrid Cell: Specifies the divider value for the card interface + unit (ciu) clock. This property is applicable only for Exynos5 SoC's and + ignored for Exynos4 SoC's. The valid range of divider value is 0 to 7. Valid values for SDR and DDR CIU clock timing for Exynos5250: - valid value for tx phase shift and rx phase shift is 0 to 7. @@ -73,9 +72,8 @@ Example: broken-cd; fifo-depth = 0x80; card-detect-delay = 200; - samsung,dw-mshc-ciu-div = 3; - samsung,dw-mshc-sdr-timing = 2 3; - samsung,dw-mshc-ddr-timing = 1 2; + samsung,dw-mshc-sdr-timing = 2 3 3; + samsung,dw-mshc-ddr-timing = 1 2 3; slot@0 { reg = 0; diff --git a/arch/arm/boot/dts/exynos4412-odroidx.dts b/arch/arm/boot/dts/exynos4412-odroidx.dts index 9804fcb..99f32db 100644 --- a/arch/arm/boot/dts/exynos4412-odroidx.dts +++ b/arch/arm/boot/dts/exynos4412-odroidx.dts @@ -48,9 +48,8 @@ supports-highspeed; broken-cd; card-detect-delay = 200; - samsung,dw-mshc-ciu-div = 3; - samsung,dw-mshc-sdr-timing = 2 3; - samsung,dw-mshc-ddr-timing = 1 2; + samsung,dw-mshc-sdr-timing = 2 3 0; + samsung,dw-mshc-ddr-timing = 1 2 0; slot@0 { reg = 0; diff --git a/arch/arm/boot/dts/exynos4412-origen.dts b/arch/arm/boot/dts/exynos4412-origen.dts index 6bc0539..7c0b535 100644 --- a/arch/arm/boot/dts/exynos4412-origen.dts +++ b/arch/arm/boot/dts/exynos4412-origen.dts @@ -131,9 +131,8 @@ supports-highspeed; broken-cd; card-detect-delay = 200; - samsung,dw-mshc-ciu-div = 3; - samsung,dw-mshc-sdr-timing = 2 3; - samsung,dw-mshc-ddr-timing = 1 2; + samsung,dw-mshc-sdr-timing = 2 3 0; + samsung,dw-mshc-ddr-timing = 1 2 0; slot@0 { reg = 0; diff --git a/arch/arm/boot/dts/exynos4412-trats2.dts b/arch/arm/boot/dts/exynos4412-trats2.dts index 4f851cc..556e414 100644 --- a/arch/arm/boot/dts/exynos4412-trats2.dts +++ b/arch/arm/boot/dts/exynos4412-trats2.dts @@ -451,9 +451,8 @@ card-detect-delay = 200; vmmc-supply = vemmc_reg; clock-frequency = 4; - samsung,dw-mshc-ciu-div = 0; - samsung,dw-mshc-sdr-timing = 2 3; - samsung,dw-mshc-ddr-timing = 1 2; + samsung,dw-mshc-sdr-timing = 2 3 0; + samsung,dw-mshc-ddr-timing = 1 2 0; pinctrl-0 = sd4_clk sd4_cmd sd4_bus4 sd4_bus8; pinctrl-names = default; status = okay; diff --git a/arch/arm/boot/dts/exynos5250-arndale.dts b/arch/arm/boot/dts/exynos5250-arndale.dts index b42e658..dc53b51 100644 --- a/arch/arm/boot/dts/exynos5250-arndale.dts +++ b
[PATCH v2 7/7] ARM: dts: add HS400 support for Exynos5420
HS400 timing value set is added for SMDK5420. And GPIO line for RCLK should be pull-down state. Signed-off-by: Seungwon Jeon tgih@samsung.com --- .../devicetree/bindings/mmc/exynos-dw-mshc.txt |6 ++ arch/arm/boot/dts/exynos5420-pinctrl.dtsi |7 +++ arch/arm/boot/dts/exynos5420-smdk5420.dts |5 - 3 files changed, 17 insertions(+), 1 deletions(-) diff --git a/Documentation/devicetree/bindings/mmc/exynos-dw-mshc.txt b/Documentation/devicetree/bindings/mmc/exynos-dw-mshc.txt index ca1914f..39c3014 100644 --- a/Documentation/devicetree/bindings/mmc/exynos-dw-mshc.txt +++ b/Documentation/devicetree/bindings/mmc/exynos-dw-mshc.txt @@ -29,6 +29,9 @@ Required Properties: data rate mode operation. Refer notes below for the order of the cells and the valid values. +* samsung,dw-mshc-hs200-timing: Similar with dw-mshc-sdr-timing. +* samsung,dw-mshc-hs400-timing: Similar with dw-mshc-ddr-timing. + Notes for the sdr-timing and ddr-timing values: The order of the cells should be @@ -45,6 +48,9 @@ Required Properties: - if CIU clock divider value is 0 (that is divide by 1), both tx and rx phase shift clocks should be 0. +* read-strobe-delay: RCLK (Data strobe) delay to control HS400 mode + (Latency value for delay line in Read path) + Required properties for a slot: * gpios: specifies a list of gpios used for command, clock and data bus. The diff --git a/arch/arm/boot/dts/exynos5420-pinctrl.dtsi b/arch/arm/boot/dts/exynos5420-pinctrl.dtsi index e62c8eb..51233ee 100644 --- a/arch/arm/boot/dts/exynos5420-pinctrl.dtsi +++ b/arch/arm/boot/dts/exynos5420-pinctrl.dtsi @@ -194,6 +194,13 @@ samsung,pin-drv = 3; }; + sd0_rclk: sd0-rclk { + samsung,pins = gpc0-7; + samsung,pin-function = 2; + samsung,pin-pud = 1; + samsung,pin-drv = 3; + }; + sd1_clk: sd1-clk { samsung,pins = gpc1-0; samsung,pin-function = 2; diff --git a/arch/arm/boot/dts/exynos5420-smdk5420.dts b/arch/arm/boot/dts/exynos5420-smdk5420.dts index 3ad4ef3..4796d44 100644 --- a/arch/arm/boot/dts/exynos5420-smdk5420.dts +++ b/arch/arm/boot/dts/exynos5420-smdk5420.dts @@ -38,8 +38,11 @@ card-detect-delay = 200; samsung,dw-mshc-sdr-timing = 0 4 3; samsung,dw-mshc-ddr-timing = 0 2 3; + samsung,dw-mshc-hs200-timing = 0 2 3; + samsung,dw-mshc-hs400-timing = 0 2 1; + read-strobe-delay = 90; pinctrl-names = default; - pinctrl-0 = sd0_clk sd0_cmd sd0_bus4 sd0_bus8; + pinctrl-0 = sd0_clk sd0_cmd sd0_bus4 sd0_bus8 sd0_rclk; slot@0 { reg = 0; -- 1.7.4.1 -- To unsubscribe from this list: send the line unsubscribe linux-samsung-soc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
RE: [PATCH 2/7] mmc: dw_mmc: exynos: don't use if clock isn't available
On Mon, March 24, 2014, Jaehoon Chung wrote: Hi, Seungwon. On 03/21/2014 11:03 PM, Seungwon Jeon wrote: Adds checking whether the clock is valid. Signed-off-by: Seungwon Jeon tgih@samsung.com --- drivers/mmc/host/dw_mmc-exynos.c | 14 +++--- 1 files changed, 11 insertions(+), 3 deletions(-) diff --git a/drivers/mmc/host/dw_mmc-exynos.c b/drivers/mmc/host/dw_mmc-exynos.c index a67e784..89aa019 100644 --- a/drivers/mmc/host/dw_mmc-exynos.c +++ b/drivers/mmc/host/dw_mmc-exynos.c @@ -117,7 +117,12 @@ static int dw_mci_exynos_priv_init(struct dw_mci *host) static int dw_mci_exynos_setup_clock(struct dw_mci *host) { struct dw_mci_exynos_priv_data *priv = host-priv; - unsigned long rate = clk_get_rate(host-ciu_clk); + unsigned long rate; + + if (IS_ERR(host-ciu_clk)) + rate = host-bus_hz; + else + rate = clk_get_rate(host-ciu_clk); host-bus_hz = rate / (priv-ciu_div + 1); how about this? host-bus_hz /= (priv-ciu_div + 1); host-bus_hz is already set to host-bus_hz or clk_get_rate() into dw_mmc.c. OK. It would be better. Thanks, Seungwon Jeon Best Regards, Jaehoon Chung return 0; @@ -196,8 +201,11 @@ static void dw_mci_exynos_set_ios(struct dw_mci *host, struct mmc_ios *ios) mci_writel(host, CLKSEL, priv-sdr_timing); } - /* Don't care if wanted clock is zero */ - if (!wanted) + /* +* Don't care if wanted clock is zero or +* ciu clock is unavailable +*/ + if (!wanted || IS_ERR(host-ciu_clk)) return; /* Guaranteed minimum frequency for cclkin */ -- To unsubscribe from this list: send the line unsubscribe linux-mmc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html -- To unsubscribe from this list: send the line unsubscribe linux-samsung-soc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
RE: [PATCH 3/7] mmc: dw_mmc: exynos: move definitions to header file
On Mon, March 24, 2014, Jaehoon Chung wrote: Hi, Seungwon. On 03/21/2014 11:03 PM, Seungwon Jeon wrote: Moves some parts related to definition to header file Signed-off-by: Seungwon Jeon tgih@samsung.com --- drivers/mmc/host/dw_mmc-exynos.c | 46 --- drivers/mmc/host/dw_mmc-exynos.h | 55 ++ 2 files changed, 61 insertions(+), 40 deletions(-) create mode 100644 drivers/mmc/host/dw_mmc-exynos.h diff --git a/drivers/mmc/host/dw_mmc-exynos.c b/drivers/mmc/host/dw_mmc-exynos.c index 89aa019..801861b 100644 --- a/drivers/mmc/host/dw_mmc-exynos.c +++ b/drivers/mmc/host/dw_mmc-exynos.c @@ -21,42 +21,8 @@ #include dw_mmc.h #include dw_mmc-pltfm.h +#include dw_mmc-exynos.h -#define NUM_PINS(x)(x + 2) - -#define SDMMC_CLKSEL 0x09C -#define SDMMC_CLKSEL_CCLK_SAMPLE(x)(((x) 7) 0) -#define SDMMC_CLKSEL_CCLK_DRIVE(x) (((x) 7) 16) -#define SDMMC_CLKSEL_CCLK_DIVIDER(x) (((x) 7) 24) -#define SDMMC_CLKSEL_GET_DRV_WD3(x)(((x) 16) 0x7) -#define SDMMC_CLKSEL_TIMING(x, y, z) (SDMMC_CLKSEL_CCLK_SAMPLE(x) | \ - SDMMC_CLKSEL_CCLK_DRIVE(y) |\ - SDMMC_CLKSEL_CCLK_DIVIDER(z)) -#define SDMMC_CLKSEL_WAKEUP_INTBIT(11) - -#define EXYNOS4210_FIXED_CIU_CLK_DIV 2 -#define EXYNOS4412_FIXED_CIU_CLK_DIV 4 - -/* Block number in eMMC */ -#define DWMCI_BLOCK_NUM0x - -#define SDMMC_EMMCP_BASE 0x1000 -#define SDMMC_MPSECURITY (SDMMC_EMMCP_BASE + 0x0010) -#define SDMMC_MPSBEGIN0(SDMMC_EMMCP_BASE + 0x0200) -#define SDMMC_MPSEND0 (SDMMC_EMMCP_BASE + 0x0204) -#define SDMMC_MPSCTRL0 (SDMMC_EMMCP_BASE + 0x020C) - -/* SMU control bits */ -#define DWMCI_MPSCTRL_SECURE_READ_BIT BIT(7) -#define DWMCI_MPSCTRL_SECURE_WRITE_BIT BIT(6) -#define DWMCI_MPSCTRL_NON_SECURE_READ_BIT BIT(5) -#define DWMCI_MPSCTRL_NON_SECURE_WRITE_BIT BIT(4) -#define DWMCI_MPSCTRL_USE_FUSE_KEY BIT(3) -#define DWMCI_MPSCTRL_ECB_MODE BIT(2) -#define DWMCI_MPSCTRL_ENCRYPTION BIT(1) -#define DWMCI_MPSCTRL_VALIDBIT(0) - -#define EXYNOS_CCLKIN_MIN 5000/* unit: HZ */ /* Variations in Exynos specific dw-mshc controller */ enum dw_mci_exynos_type { @@ -104,11 +70,11 @@ static int dw_mci_exynos_priv_init(struct dw_mci *host) if (priv-ctrl_type == DW_MCI_TYPE_EXYNOS5420_SMU) { mci_writel(host, MPSBEGIN0, 0); - mci_writel(host, MPSEND0, DWMCI_BLOCK_NUM); - mci_writel(host, MPSCTRL0, DWMCI_MPSCTRL_SECURE_WRITE_BIT | - DWMCI_MPSCTRL_NON_SECURE_READ_BIT | - DWMCI_MPSCTRL_VALID | - DWMCI_MPSCTRL_NON_SECURE_WRITE_BIT); + mci_writel(host, MPSEND0, SDMMC_ENDING_SEC_NR_MAX); + mci_writel(host, MPSCTRL0, SDMMC_MPSCTRL_SECURE_WRITE_BIT | + SDMMC_MPSCTRL_NON_SECURE_READ_BIT | + SDMMC_MPSCTRL_VALID | + SDMMC_MPSCTRL_NON_SECURE_WRITE_BIT); } return 0; diff --git a/drivers/mmc/host/dw_mmc-exynos.h b/drivers/mmc/host/dw_mmc-exynos.h new file mode 100644 index 000..a4c6e10 --- /dev/null +++ b/drivers/mmc/host/dw_mmc-exynos.h @@ -0,0 +1,55 @@ +/* + * Exynos Specific Extensions for Synopsys DW Multimedia Card Interface driver + * + * Copyright (C) 201333Samsung Electronics Co., Ltd. 201 Typo? :) Oh, thank you for detect. Thanks, Seungwon Jeon + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#ifndef _DW_MMC_EXYNOS_H_ +#define _DW_MMC_EXYNOS_H_ + +/* Extended Register's Offset */ +#define SDMMC_CLKSEL 0x09C + +/* CLKSEL register defines */ +#define SDMMC_CLKSEL_CCLK_SAMPLE(x)(((x) 7) 0) +#define SDMMC_CLKSEL_CCLK_DRIVE(x) (((x) 7) 16) +#define SDMMC_CLKSEL_CCLK_DIVIDER(x) (((x) 7) 24) +#define SDMMC_CLKSEL_GET_DRV_WD3(x)(((x) 16) 0x7) +#define SDMMC_CLKSEL_TIMING(x, y, z) (SDMMC_CLKSEL_CCLK_SAMPLE(x) | \ +SDMMC_CLKSEL_CCLK_DRIVE(y) | \ +SDMMC_CLKSEL_CCLK_DIVIDER(z)) +#define SDMMC_CLKSEL_WAKEUP_INTBIT(11) + +/* Protector Register */ +#define SDMMC_EMMCP_BASE 0x1000 +#define SDMMC_MPSECURITY (SDMMC_EMMCP_BASE + 0x0010) +#define SDMMC_MPSBEGIN0(SDMMC_EMMCP_BASE + 0x0200) +#define SDMMC_MPSEND0
[PATCH 0/7] mmc: dw_mmc: update host driver including HS400 support
This patch-set includes several driver's updates. Specially, HS400 mode is enabled for eMMC5.0 spec. Seungwon Jeon (7): mmc: dw_mmc: fix the max_blk_count in IDMAC mmc: dw_mmc: exynos: don't use if clock isn't available mmc: dw_mmc: exynos: move definitions to header file mmc: dw_mmc: exynos: incorporate ciu_div into timing property mmc: dw_mmc: exynos: support eMMC's HS400 mode ARM: dts: drop dw-mshc-ciu-div property from Exynos ARM: dts: add HS400 support for Exynos5420 .../devicetree/bindings/mmc/exynos-dw-mshc.txt | 18 +- arch/arm/boot/dts/exynos4412-odroidx.dts |5 +- arch/arm/boot/dts/exynos4412-origen.dts|5 +- arch/arm/boot/dts/exynos4412-trats2.dts|5 +- arch/arm/boot/dts/exynos5250-arndale.dts | 10 +- arch/arm/boot/dts/exynos5250-cros-common.dtsi | 15 +- arch/arm/boot/dts/exynos5250-smdk5250.dts | 10 +- arch/arm/boot/dts/exynos5420-arndale-octa.dts | 10 +- arch/arm/boot/dts/exynos5420-pinctrl.dtsi |7 + arch/arm/boot/dts/exynos5420-smdk5420.dts | 15 +- drivers/mmc/host/dw_mmc-exynos.c | 267 +--- drivers/mmc/host/dw_mmc-exynos.h | 70 + drivers/mmc/host/dw_mmc.c |7 +- 13 files changed, 303 insertions(+), 141 deletions(-) create mode 100644 drivers/mmc/host/dw_mmc-exynos.h -- 1.7.4.1 -- To unsubscribe from this list: send the line unsubscribe linux-samsung-soc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 1/7] mmc: dw_mmc: fix the max_blk_count in IDMAC
Even though 1MB is reserved for descriptor table in IDMAC, the dw_mmc host driver is allowed to receive only maximum 128KB block length in one request. This is caused by setting improper max_blk_count. It needs to be e adjusted so that descriptor table is used fully. It is found that the performance is improved with the increased the max_blk_count. Signed-off-by: Seungwon Jeon tgih@samsung.com --- drivers/mmc/host/dw_mmc.c |4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index 3a6721e..aeb38f9 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c @@ -2101,9 +2101,9 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id) #ifdef CONFIG_MMC_DW_IDMAC mmc-max_segs = host-ring_size; mmc-max_blk_size = 65536; - mmc-max_blk_count = host-ring_size; mmc-max_seg_size = 0x1000; - mmc-max_req_size = mmc-max_seg_size * mmc-max_blk_count; + mmc-max_req_size = mmc-max_seg_size * host-ring_size; + mmc-max_blk_count = mmc-max_req_size / 512; #else mmc-max_segs = 64; mmc-max_blk_size = 65536; /* BLKSIZ is 16 bits */ -- 1.7.4.1 -- To unsubscribe from this list: send the line unsubscribe linux-samsung-soc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 2/7] mmc: dw_mmc: exynos: don't use if clock isn't available
Adds checking whether the clock is valid. Signed-off-by: Seungwon Jeon tgih@samsung.com --- drivers/mmc/host/dw_mmc-exynos.c | 14 +++--- 1 files changed, 11 insertions(+), 3 deletions(-) diff --git a/drivers/mmc/host/dw_mmc-exynos.c b/drivers/mmc/host/dw_mmc-exynos.c index a67e784..89aa019 100644 --- a/drivers/mmc/host/dw_mmc-exynos.c +++ b/drivers/mmc/host/dw_mmc-exynos.c @@ -117,7 +117,12 @@ static int dw_mci_exynos_priv_init(struct dw_mci *host) static int dw_mci_exynos_setup_clock(struct dw_mci *host) { struct dw_mci_exynos_priv_data *priv = host-priv; - unsigned long rate = clk_get_rate(host-ciu_clk); + unsigned long rate; + + if (IS_ERR(host-ciu_clk)) + rate = host-bus_hz; + else + rate = clk_get_rate(host-ciu_clk); host-bus_hz = rate / (priv-ciu_div + 1); return 0; @@ -196,8 +201,11 @@ static void dw_mci_exynos_set_ios(struct dw_mci *host, struct mmc_ios *ios) mci_writel(host, CLKSEL, priv-sdr_timing); } - /* Don't care if wanted clock is zero */ - if (!wanted) + /* +* Don't care if wanted clock is zero or +* ciu clock is unavailable +*/ + if (!wanted || IS_ERR(host-ciu_clk)) return; /* Guaranteed minimum frequency for cclkin */ -- 1.7.4.1 -- To unsubscribe from this list: send the line unsubscribe linux-samsung-soc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 7/7] ARM: dts: add HS400 support for Exynos5420
HS400 timing value set is added for SMDK5420. And GPIO line for RCLK should be pull-down state. Signed-off-by: Seungwon Jeon tgih@samsung.com --- .../devicetree/bindings/mmc/exynos-dw-mshc.txt |6 ++ arch/arm/boot/dts/exynos5420-pinctrl.dtsi |7 +++ arch/arm/boot/dts/exynos5420-smdk5420.dts |5 - 3 files changed, 17 insertions(+), 1 deletions(-) diff --git a/Documentation/devicetree/bindings/mmc/exynos-dw-mshc.txt b/Documentation/devicetree/bindings/mmc/exynos-dw-mshc.txt index ca1914f..39c3014 100644 --- a/Documentation/devicetree/bindings/mmc/exynos-dw-mshc.txt +++ b/Documentation/devicetree/bindings/mmc/exynos-dw-mshc.txt @@ -29,6 +29,9 @@ Required Properties: data rate mode operation. Refer notes below for the order of the cells and the valid values. +* samsung,dw-mshc-hs200-timing: Similar with dw-mshc-sdr-timing. +* samsung,dw-mshc-hs400-timing: Similar with dw-mshc-ddr-timing. + Notes for the sdr-timing and ddr-timing values: The order of the cells should be @@ -45,6 +48,9 @@ Required Properties: - if CIU clock divider value is 0 (that is divide by 1), both tx and rx phase shift clocks should be 0. +* read-strobe-delay: RCLK (Data strobe) delay to control HS400 mode + (Latency value for delay line in Read path) + Required properties for a slot: * gpios: specifies a list of gpios used for command, clock and data bus. The diff --git a/arch/arm/boot/dts/exynos5420-pinctrl.dtsi b/arch/arm/boot/dts/exynos5420-pinctrl.dtsi index e62c8eb..51233ee 100644 --- a/arch/arm/boot/dts/exynos5420-pinctrl.dtsi +++ b/arch/arm/boot/dts/exynos5420-pinctrl.dtsi @@ -194,6 +194,13 @@ samsung,pin-drv = 3; }; + sd0_rclk: sd0-rclk { + samsung,pins = gpc0-7; + samsung,pin-function = 2; + samsung,pin-pud = 1; + samsung,pin-drv = 3; + }; + sd1_clk: sd1-clk { samsung,pins = gpc1-0; samsung,pin-function = 2; diff --git a/arch/arm/boot/dts/exynos5420-smdk5420.dts b/arch/arm/boot/dts/exynos5420-smdk5420.dts index 3ad4ef3..4796d44 100644 --- a/arch/arm/boot/dts/exynos5420-smdk5420.dts +++ b/arch/arm/boot/dts/exynos5420-smdk5420.dts @@ -38,8 +38,11 @@ card-detect-delay = 200; samsung,dw-mshc-sdr-timing = 0 4 3; samsung,dw-mshc-ddr-timing = 0 2 3; + samsung,dw-mshc-hs200-timing = 0 2 3; + samsung,dw-mshc-hs400-timing = 0 2 1; + read-strobe-delay = 90; pinctrl-names = default; - pinctrl-0 = sd0_clk sd0_cmd sd0_bus4 sd0_bus8; + pinctrl-0 = sd0_clk sd0_cmd sd0_bus4 sd0_bus8 sd0_rclk; slot@0 { reg = 0; -- 1.7.4.1 -- To unsubscribe from this list: send the line unsubscribe linux-samsung-soc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 5/7] mmc: dw_mmc: exynos: support eMMC's HS400 mode
Implements HS400 support for Exynos's host driver. And this patch includes some updates as new mode is added. Signed-off-by: Seungwon Jeon tgih@samsung.com --- drivers/mmc/host/dw_mmc-exynos.c | 140 +++--- drivers/mmc/host/dw_mmc-exynos.h | 14 drivers/mmc/host/dw_mmc.c|3 +- 3 files changed, 130 insertions(+), 27 deletions(-) diff --git a/drivers/mmc/host/dw_mmc-exynos.c b/drivers/mmc/host/dw_mmc-exynos.c index ce261c8..5c9dc9a 100644 --- a/drivers/mmc/host/dw_mmc-exynos.c +++ b/drivers/mmc/host/dw_mmc-exynos.c @@ -40,7 +40,12 @@ struct dw_mci_exynos_priv_data { u32 sdr_timing; u32 ddr_timing; u32 hs200_timing; + u32 hs400_timing; + u32 tuned_sample; u32 cur_speed; + u32 dqs_delay; + u32 saved_dqs_en; + u32 saved_strobe_ctrl; }; static struct dw_mci_exynos_compatible { @@ -90,6 +95,16 @@ static int dw_mci_exynos_priv_init(struct dw_mci *host) SDMMC_MPSCTRL_NON_SECURE_WRITE_BIT); } + if (priv-ctrl_type = DW_MCI_TYPE_EXYNOS5420) { + priv-saved_strobe_ctrl = mci_readl(host, HS400_DLINE_CTRL); + priv-saved_dqs_en = mci_readl(host, HS400_DQS_EN); + priv-saved_dqs_en |= AXI_NON_BLOCKING_WR; + mci_writel(host, HS400_DQS_EN, priv-saved_dqs_en); + if (!priv-dqs_delay) + priv-dqs_delay = + DQS_CTRL_GET_RD_DELAY(priv-saved_strobe_ctrl); + } + priv-ciu_div = dw_mci_exynos_get_ciu_div(host); return 0; @@ -109,6 +124,14 @@ static int dw_mci_exynos_setup_clock(struct dw_mci *host) return 0; } +static void dw_mci_exynos_set_clksel_timing(struct dw_mci *host, u32 timing) +{ + u32 clksel; + clksel = mci_readl(host, CLKSEL); + clksel = (clksel ~SDMMC_CLKSEL_TIMING_MASK) | timing; + mci_writel(host, CLKSEL, clksel); +} + #ifdef CONFIG_PM_SLEEP static int dw_mci_exynos_suspend(struct device *dev) { @@ -166,23 +189,39 @@ static void dw_mci_exynos_prepare_command(struct dw_mci *host, u32 *cmdr) *cmdr |= SDMMC_CMD_USE_HOLD_REG; } -static void dw_mci_exynos_set_ios(struct dw_mci *host, struct mmc_ios *ios) +static void dw_mci_exynos_config_hs400(struct dw_mci *host, u32 timing) { struct dw_mci_exynos_priv_data *priv = host-priv; - unsigned int wanted = ios-clock; - unsigned long actual; + u32 dqs, strobe; - if (ios-timing == MMC_TIMING_MMC_HS200) { - mci_writel(host, CLKSEL, priv-hs200_timing); - } else if (ios-timing == MMC_TIMING_MMC_DDR52) { - mci_writel(host, CLKSEL, priv-ddr_timing); - /* Should be double rate for DDR mode */ - if (ios-bus_width == MMC_BUS_WIDTH_8) - wanted = 1; + /* +* Not suppported to configure register +* related to HS400 +*/ + if (priv-ctrl_type DW_MCI_TYPE_EXYNOS5420) + return; + + dqs = priv-saved_dqs_en; + strobe = priv-saved_strobe_ctrl; + + if (timing == MMC_TIMING_MMC_HS400) { + dqs |= DATA_STROBE_EN; + strobe = DQS_CTRL_RD_DELAY(strobe, priv-dqs_delay); } else { - mci_writel(host, CLKSEL, priv-sdr_timing); + dqs = ~DATA_STROBE_EN; } + mci_writel(host, HS400_DQS_EN, dqs); + mci_writel(host, HS400_DLINE_CTRL, strobe); +} + +static void dw_mci_exynos_adjust_clock(struct dw_mci *host, unsigned int wanted) +{ + struct dw_mci_exynos_priv_data *priv = host-priv; + unsigned long actual; + u8 div; + int ret; + /* * Don't care if wanted clock is zero or * ciu clock is unavailable @@ -194,18 +233,57 @@ static void dw_mci_exynos_set_ios(struct dw_mci *host, struct mmc_ios *ios) if (wanted EXYNOS_CCLKIN_MIN) wanted = EXYNOS_CCLKIN_MIN; - if (wanted != priv-cur_speed) { - u8 div = dw_mci_exynos_get_ciu_div(host); - int ret = clk_set_rate(host-ciu_clk, wanted * div); - if (ret) - dev_warn(host-dev, - failed to set clk-rate %u error: %d\n, -wanted * div, ret); - actual = clk_get_rate(host-ciu_clk); - host-bus_hz = actual / div; - priv-cur_speed = wanted; - host-current_speed = 0; + if (wanted == priv-cur_speed) + return; + + div = dw_mci_exynos_get_ciu_div(host); + ret = clk_set_rate(host-ciu_clk, wanted * div); + if (ret
[PATCH 6/7] ARM: dts: drop dw-mshc-ciu-div property from Exynos
As dw-mshc-ciu-div is strongly close to timing property, it is merged with each timing property. Signed-off-by: Seungwon Jeon tgih@samsung.com --- .../devicetree/bindings/mmc/exynos-dw-mshc.txt | 12 +--- arch/arm/boot/dts/exynos4412-odroidx.dts |5 ++--- arch/arm/boot/dts/exynos4412-origen.dts|5 ++--- arch/arm/boot/dts/exynos4412-trats2.dts|5 ++--- arch/arm/boot/dts/exynos5250-arndale.dts | 10 -- arch/arm/boot/dts/exynos5250-cros-common.dtsi | 15 ++- arch/arm/boot/dts/exynos5250-smdk5250.dts | 10 -- arch/arm/boot/dts/exynos5420-arndale-octa.dts | 10 -- arch/arm/boot/dts/exynos5420-smdk5420.dts | 10 -- 9 files changed, 33 insertions(+), 49 deletions(-) diff --git a/Documentation/devicetree/bindings/mmc/exynos-dw-mshc.txt b/Documentation/devicetree/bindings/mmc/exynos-dw-mshc.txt index 532b1d4..ca1914f 100644 --- a/Documentation/devicetree/bindings/mmc/exynos-dw-mshc.txt +++ b/Documentation/devicetree/bindings/mmc/exynos-dw-mshc.txt @@ -19,10 +19,6 @@ Required Properties: - samsung,exynos5420-dw-mshc: for controllers with Samsung Exynos5420 specific extensions. -* samsung,dw-mshc-ciu-div: Specifies the divider value for the card interface - unit (ciu) clock. This property is applicable only for Exynos5 SoC's and - ignored for Exynos4 SoC's. The valid range of divider value is 0 to 7. - * samsung,dw-mshc-sdr-timing: Specifies the value of CIU clock phase shift value in transmit mode and CIU clock phase shift value in receive mode for single data rate mode operation. Refer notes below for the order of the cells and the @@ -38,6 +34,9 @@ Required Properties: The order of the cells should be - First Cell: CIU clock phase shift value for tx mode. - Second Cell: CIU clock phase shift value for rx mode. + - Thrid Cell: Specifies the divider value for the card interface + unit (ciu) clock. This property is applicable only for Exynos5 SoC's and + ignored for Exynos4 SoC's. The valid range of divider value is 0 to 7. Valid values for SDR and DDR CIU clock timing for Exynos5250: - valid value for tx phase shift and rx phase shift is 0 to 7. @@ -73,9 +72,8 @@ Example: broken-cd; fifo-depth = 0x80; card-detect-delay = 200; - samsung,dw-mshc-ciu-div = 3; - samsung,dw-mshc-sdr-timing = 2 3; - samsung,dw-mshc-ddr-timing = 1 2; + samsung,dw-mshc-sdr-timing = 2 3 3; + samsung,dw-mshc-ddr-timing = 1 2 3; slot@0 { reg = 0; diff --git a/arch/arm/boot/dts/exynos4412-odroidx.dts b/arch/arm/boot/dts/exynos4412-odroidx.dts index 9804fcb..99f32db 100644 --- a/arch/arm/boot/dts/exynos4412-odroidx.dts +++ b/arch/arm/boot/dts/exynos4412-odroidx.dts @@ -48,9 +48,8 @@ supports-highspeed; broken-cd; card-detect-delay = 200; - samsung,dw-mshc-ciu-div = 3; - samsung,dw-mshc-sdr-timing = 2 3; - samsung,dw-mshc-ddr-timing = 1 2; + samsung,dw-mshc-sdr-timing = 2 3 0; + samsung,dw-mshc-ddr-timing = 1 2 0; slot@0 { reg = 0; diff --git a/arch/arm/boot/dts/exynos4412-origen.dts b/arch/arm/boot/dts/exynos4412-origen.dts index 6bc0539..7c0b535 100644 --- a/arch/arm/boot/dts/exynos4412-origen.dts +++ b/arch/arm/boot/dts/exynos4412-origen.dts @@ -131,9 +131,8 @@ supports-highspeed; broken-cd; card-detect-delay = 200; - samsung,dw-mshc-ciu-div = 3; - samsung,dw-mshc-sdr-timing = 2 3; - samsung,dw-mshc-ddr-timing = 1 2; + samsung,dw-mshc-sdr-timing = 2 3 0; + samsung,dw-mshc-ddr-timing = 1 2 0; slot@0 { reg = 0; diff --git a/arch/arm/boot/dts/exynos4412-trats2.dts b/arch/arm/boot/dts/exynos4412-trats2.dts index 4f851cc..556e414 100644 --- a/arch/arm/boot/dts/exynos4412-trats2.dts +++ b/arch/arm/boot/dts/exynos4412-trats2.dts @@ -451,9 +451,8 @@ card-detect-delay = 200; vmmc-supply = vemmc_reg; clock-frequency = 4; - samsung,dw-mshc-ciu-div = 0; - samsung,dw-mshc-sdr-timing = 2 3; - samsung,dw-mshc-ddr-timing = 1 2; + samsung,dw-mshc-sdr-timing = 2 3 0; + samsung,dw-mshc-ddr-timing = 1 2 0; pinctrl-0 = sd4_clk sd4_cmd sd4_bus4 sd4_bus8; pinctrl-names = default; status = okay; diff --git a/arch/arm/boot/dts/exynos5250-arndale.dts b/arch/arm/boot/dts/exynos5250-arndale.dts index b42e658..dc53b51 100644 --- a/arch/arm/boot/dts/exynos5250-arndale.dts +++ b
[PATCH 4/7] mmc: dw_mmc: exynos: incorporate ciu_div into timing property
ciu_div may not be common value for all speed mode. So, it needs to be attached to CLKSEL timing. Signed-off-by: Seungwon Jeon tgih@samsung.com --- drivers/mmc/host/dw_mmc-exynos.c | 75 ++ drivers/mmc/host/dw_mmc-exynos.h |1 + 2 files changed, 53 insertions(+), 23 deletions(-) diff --git a/drivers/mmc/host/dw_mmc-exynos.c b/drivers/mmc/host/dw_mmc-exynos.c index 801861b..ce261c8 100644 --- a/drivers/mmc/host/dw_mmc-exynos.c +++ b/drivers/mmc/host/dw_mmc-exynos.c @@ -39,6 +39,7 @@ struct dw_mci_exynos_priv_data { u8 ciu_div; u32 sdr_timing; u32 ddr_timing; + u32 hs200_timing; u32 cur_speed; }; @@ -64,6 +65,18 @@ static struct dw_mci_exynos_compatible { }, }; +static inline u8 dw_mci_exynos_get_ciu_div(struct dw_mci *host) +{ + struct dw_mci_exynos_priv_data *priv = host-priv; + + if (priv-ctrl_type == DW_MCI_TYPE_EXYNOS4412) + return EXYNOS4412_FIXED_CIU_CLK_DIV; + else if (priv-ctrl_type == DW_MCI_TYPE_EXYNOS4210) + return EXYNOS4210_FIXED_CIU_CLK_DIV; + else + return SDMMC_CLKSEL_GET_DIV(mci_readl(host, CLKSEL)) + 1; +} + static int dw_mci_exynos_priv_init(struct dw_mci *host) { struct dw_mci_exynos_priv_data *priv = host-priv; @@ -77,6 +90,8 @@ static int dw_mci_exynos_priv_init(struct dw_mci *host) SDMMC_MPSCTRL_NON_SECURE_WRITE_BIT); } + priv-ciu_div = dw_mci_exynos_get_ciu_div(host); + return 0; } @@ -90,7 +105,7 @@ static int dw_mci_exynos_setup_clock(struct dw_mci *host) else rate = clk_get_rate(host-ciu_clk); - host-bus_hz = rate / (priv-ciu_div + 1); + host-bus_hz = rate / priv-ciu_div; return 0; } @@ -156,9 +171,10 @@ static void dw_mci_exynos_set_ios(struct dw_mci *host, struct mmc_ios *ios) struct dw_mci_exynos_priv_data *priv = host-priv; unsigned int wanted = ios-clock; unsigned long actual; - u8 div = priv-ciu_div + 1; - if (ios-timing == MMC_TIMING_MMC_DDR52) { + if (ios-timing == MMC_TIMING_MMC_HS200) { + mci_writel(host, CLKSEL, priv-hs200_timing); + } else if (ios-timing == MMC_TIMING_MMC_DDR52) { mci_writel(host, CLKSEL, priv-ddr_timing); /* Should be double rate for DDR mode */ if (ios-bus_width == MMC_BUS_WIDTH_8) @@ -179,6 +195,7 @@ static void dw_mci_exynos_set_ios(struct dw_mci *host, struct mmc_ios *ios) wanted = EXYNOS_CCLKIN_MIN; if (wanted != priv-cur_speed) { + u8 div = dw_mci_exynos_get_ciu_div(host); int ret = clk_set_rate(host-ciu_clk, wanted * div); if (ret) dev_warn(host-dev, @@ -191,14 +208,34 @@ static void dw_mci_exynos_set_ios(struct dw_mci *host, struct mmc_ios *ios) } } +static int dw_mci_exynos_dt_populate_timing(struct dw_mci *host, + unsigned int ctrl_type, + const char *propname, + u32 *out_values) +{ + struct device_node *np = host-dev-of_node; + u32 timing[3]; + int ret; + + ret = of_property_read_u32_array(np, propname, timing, 3); + if (ret) + return ret; + + if (ctrl_type == DW_MCI_TYPE_EXYNOS4412 || + ctrl_type == DW_MCI_TYPE_EXYNOS4210) + timing[2] = 0; + + *out_values = SDMMC_CLKSEL_TIMING(timing[0], timing[1], timing[2]); + + return 0; +} + + static int dw_mci_exynos_parse_dt(struct dw_mci *host) { struct dw_mci_exynos_priv_data *priv; struct device_node *np = host-dev-of_node; - u32 timing[2]; - u32 div = 0; - int idx; - int ret; + int idx, ret; priv = devm_kzalloc(host-dev, sizeof(*priv), GFP_KERNEL); if (!priv) { @@ -211,29 +248,21 @@ static int dw_mci_exynos_parse_dt(struct dw_mci *host) priv-ctrl_type = exynos_compat[idx].ctrl_type; } - if (priv-ctrl_type == DW_MCI_TYPE_EXYNOS4412) - priv-ciu_div = EXYNOS4412_FIXED_CIU_CLK_DIV - 1; - else if (priv-ctrl_type == DW_MCI_TYPE_EXYNOS4210) - priv-ciu_div = EXYNOS4210_FIXED_CIU_CLK_DIV - 1; - else { - of_property_read_u32(np, samsung,dw-mshc-ciu-div, div); - priv-ciu_div = div; - } - - ret = of_property_read_u32_array(np, - samsung,dw-mshc-sdr-timing, timing, 2); + ret = dw_mci_exynos_dt_populate_timing(host, priv-ctrl_type, + samsung,dw-mshc-sdr-timing, priv-sdr_timing); if (ret) return ret; - priv
[PATCH] ARM: dts: add clock provider for mshc node for Exynos4412 SOC
Clock lookup information is required as driver can manipulate clock rate properly. Signed-off-by: Seungwon Jeon tgih@samsung.com --- arch/arm/boot/dts/exynos4412.dtsi |2 ++ 1 files changed, 2 insertions(+), 0 deletions(-) diff --git a/arch/arm/boot/dts/exynos4412.dtsi b/arch/arm/boot/dts/exynos4412.dtsi index ec1b166..9cbe59a 100644 --- a/arch/arm/boot/dts/exynos4412.dtsi +++ b/arch/arm/boot/dts/exynos4412.dtsi @@ -41,5 +41,7 @@ interrupts = 0 77 0; #address-cells = 1; #size-cells = 0; + clocks = clock 301, clock 149; + clock-name = biu, ciu; }; }; -- 1.7.0.4 -- To unsubscribe from this list: send the line unsubscribe linux-samsung-soc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
RE: linux 3.13-rc1 make dw_mmc-exynos more worse
On Tue, November 26, 2013, Randy wrote: Thanks Jaehoon, I have noticed that before it, but in dw_mmc driver, I won't meet this problem. As you can seen in dts, I have defined a clock source. Or the clock source what I choose is not correct? I don't know how to debug this, I don't know much about it. Actually, I don't really understand the contain in chapter 7 of datasheet. I am sorry for that. Would you like to tell me some more about it? Can you add the followings for you test? arch/arm/boot/dts/exynos4412.dtsi + clocks = clock 301, clock 149; + clock-name = biu, ciu; Thanks, Seungwon Jeon 于 2013年11月26日 12:32, Jaehoon Chung 写道: Hi, Randy, It seems a problem that controller didn't find the clock source. Also you can see the below message. Did you check the clock source? [1.125000] s3c-sdhci 1255.sdhci: failed to get io clock Actually, need to prevent the null pointer dereference for clock in dw-mmc.c And If dw-mmc controller can be used, recommend to use it. dw-mmc can use DDR mode, but sdhci can't. Best Regards, Jaehoon Chung On 11/26/2013 10:47 AM, randy wrote: 于 2013年11月26日 08:41, Tomasz Figa 写道: On Sunday 24 of November 2013 22:18:46 Olof Johansson wrote: Hi, On Sun, Nov 24, 2013 at 4:07 AM, randy lxr1...@hotmail.com wrote: -BEGIN PGP SIGNED MESSAGE- Hash: SHA1 After pull the merge of 3.13-rc1, the dw_mmc-exynos will make the boot stock.In 3.13, it is just stocked udev in 3.13 and makse udev timeout but kernel report the emmc device is found. And in the Documentation/devicetree/bindings/mmc/exynos-dw-mshc.txt I saw that it is need to define which gpio ports that a emmc slot use, but when I watched others dts, they use pinctrl, which is correct? Here is the log and dts [..] ===log begin = [..] [0.00] CPU EXYNOS4412 (id 0xe4412011) [..] [1.095000] mmc0: no vmmc regulator found [ 1.13] mmc0: SDHCI controller on samsung-hsmmc [1253.sdhci] using ADMA [1.13] Synopsys Designware Multimedia Card Interface Driver [ 1.13] Unable to handle kernel NULL pointer dereference at virtual address 002a [ 1.13] pgd = c0004000 [1.13] [002a] *pgd= [ 1.135000] Internal error: Oops: 5 [#1] PREEMPT SMP ARM [ 1.14] Modules linked in: [ 1.14] CPU: 0 PID: 1 Comm: swapper/0 Not tainted 3.13.0-rc1-8-g584fa45-dirty #3 [ 1.15] task: ef0a4000 ti: ef0a8000 task.ti: ef0a8000 [ 1.155000] PC is at clk_get_rate+0x18/0x5c [1.16] LR is at clk_prepare_lock+0xc/0xd8 [1.165000] pc : [c0319400] lr : [c0318864]psr: a113 [ 1.165000] sp : ef0a9e20 ip : ee94eb40 fp : [ 1.175000] r10: c0571510 r9 : ef0a8000 r8 : ef227a10 [ 1.18] r7 : c043544c r6 : fffe r5 : ee94ead0 r4 : fffe [1.185000] r3 : ef0a4000 r2 : 0001 r1 : 02b9 r0 : 0001 [ 1.195000] Flags: NzCv IRQs on FIQs on Mode SVC_32 ISA ARM Segment kernel [ 1.20] Control: 10c5387d Table: 4000404a DAC: 0015 [1.205000] Process swapper/0 (pid: 1, stack limit = 0xef0a8240) [1.21] Stack: (0xef0a9e20 to 0xef0aa000) [1.215000] 9e20: c0308474 ee9ea610 ee94ead0 c0308488 c0308474 ee9ea610 c030592c [ 1.225000] 9e40: ef227a10 1000 c043544c c020a920 c0838b04 17d78400 ee9ea610 ef227a00 [ 1.235000] 9e60: ef227a10 c05d6b1c c05d6b1c c05890b0 ef0a8000 c0571510 c0269448 [ 1.24] 9e80: c0269430 ef227a10 c061291c c0268088 ef227a10 c05d6b1c ef227a44 [ 1.25] 9ea0: c026822c c05d6b1c c02681a0 c02668a8 ef005478 ef212740 [ 1.255000] 9ec0: c05d6b1c ef2c7900 c05cf438 c0267864 c0511e38 c05d6b1c 0006 c05d6b1c [1.265000] 9ee0: 0006 c059575c c05df580 c026884c c05a2e14 0006 c00088dc [ 1.275000] 9f00: c0603f70 ef163e00 c040e334 6113 c05b5000 a113 c05b5054 c05b5050 [ 1.28] 9f20: c05df580 c054ad68 c0839c96 c04247b4 0093 c0035158 c05b5054 c05a2a20 [1.29] 9f40: c050ae2c c054a438 0006 0006 c05a2e14 0006 c059575c [ 1.30] 9f60: c05df580 0093 c0595768 c0571510 c0571c48 0006 0006 [ 1.305000] 9f80: c0571510 c003df68 c0403544 [1.315000] 9fa0: c040354c c000e738 [ 1.32] 9fc0: [ 1.33] 9fe0: 0013 be73efa4 bffd [1.34] [c0319400] (clk_get_rate+0x18/0x5c) from [c0308488] (dw_mci_exynos_setup_clock+0x14/0x2c) [1.35] [c0308488] (dw_mci_exynos_setup_clock+0x14/0x2c) from [c030592c] (dw_mci_probe+0x15c/0xca4) [1.36] [c030592c] (dw_mci_probe+0x15c/0xca4) from [c0269448] (platform_drv_probe
RE: linux 3.13-rc1 make dw_mmc-exynos more worse
On Mon, November 25, 2013, Olof Johansson wrote: Hi, On Sun, Nov 24, 2013 at 4:07 AM, randy lxr1...@hotmail.com wrote: -BEGIN PGP SIGNED MESSAGE- Hash: SHA1 After pull the merge of 3.13-rc1, the dw_mmc-exynos will make the boot stock.In 3.13, it is just stocked udev in 3.13 and makse udev timeout but kernel report the emmc device is found. And in the Documentation/devicetree/bindings/mmc/exynos-dw-mshc.txt I saw that it is need to define which gpio ports that a emmc slot use, but when I watched others dts, they use pinctrl, which is correct? Here is the log and dts [..] ===log begin = [..] [0.00] CPU EXYNOS4412 (id 0xe4412011) [..] [1.095000] mmc0: no vmmc regulator found [1.13] mmc0: SDHCI controller on samsung-hsmmc [1253.sdhci] using ADMA [1.13] Synopsys Designware Multimedia Card Interface Driver [1.13] Unable to handle kernel NULL pointer dereference at virtual address 002a [1.13] pgd = c0004000 [1.13] [002a] *pgd= [1.135000] Internal error: Oops: 5 [#1] PREEMPT SMP ARM [1.14] Modules linked in: [1.14] CPU: 0 PID: 1 Comm: swapper/0 Not tainted 3.13.0-rc1-8-g584fa45-dirty #3 [1.15] task: ef0a4000 ti: ef0a8000 task.ti: ef0a8000 [1.155000] PC is at clk_get_rate+0x18/0x5c [1.16] LR is at clk_prepare_lock+0xc/0xd8 [1.165000] pc : [c0319400]lr : [c0318864]psr: a113 [1.165000] sp : ef0a9e20 ip : ee94eb40 fp : [1.175000] r10: c0571510 r9 : ef0a8000 r8 : ef227a10 [1.18] r7 : c043544c r6 : fffe r5 : ee94ead0 r4 : fffe [1.185000] r3 : ef0a4000 r2 : 0001 r1 : 02b9 r0 : 0001 [1.195000] Flags: NzCv IRQs on FIQs on Mode SVC_32 ISA ARM Segment kernel [1.20] Control: 10c5387d Table: 4000404a DAC: 0015 [1.205000] Process swapper/0 (pid: 1, stack limit = 0xef0a8240) [1.21] Stack: (0xef0a9e20 to 0xef0aa000) [1.215000] 9e20: c0308474 ee9ea610 ee94ead0 c0308488 c0308474 ee9ea610 c030592c [1.225000] 9e40: ef227a10 1000 c043544c c020a920 c0838b04 17d78400 ee9ea610 ef227a00 [1.235000] 9e60: ef227a10 c05d6b1c c05d6b1c c05890b0 ef0a8000 c0571510 c0269448 [1.24] 9e80: c0269430 ef227a10 c061291c c0268088 ef227a10 c05d6b1c ef227a44 [1.25] 9ea0: c026822c c05d6b1c c02681a0 c02668a8 ef005478 ef212740 [1.255000] 9ec0: c05d6b1c ef2c7900 c05cf438 c0267864 c0511e38 c05d6b1c 0006 c05d6b1c [1.265000] 9ee0: 0006 c059575c c05df580 c026884c c05a2e14 0006 c00088dc [1.275000] 9f00: c0603f70 ef163e00 c040e334 6113 c05b5000 a113 c05b5054 c05b5050 [1.28] 9f20: c05df580 c054ad68 c0839c96 c04247b4 0093 c0035158 c05b5054 c05a2a20 [1.29] 9f40: c050ae2c c054a438 0006 0006 c05a2e14 0006 c059575c [1.30] 9f60: c05df580 0093 c0595768 c0571510 c0571c48 0006 0006 [1.305000] 9f80: c0571510 c003df68 c0403544 [1.315000] 9fa0: c040354c c000e738 [1.32] 9fc0: [1.33] 9fe0: 0013 be73efa4 bffd [1.34] [c0319400] (clk_get_rate+0x18/0x5c) from [c0308488] (dw_mci_exynos_setup_clock+0x14/0x2c) [1.35] [c0308488] (dw_mci_exynos_setup_clock+0x14/0x2c) from [c030592c] (dw_mci_probe+0x15c/0xca4) [1.36] [c030592c] (dw_mci_probe+0x15c/0xca4) from [c0269448] (platform_drv_probe+0x18/0x48) [1.365000] [c0269448] (platform_drv_probe+0x18/0x48) from [c0268088] (driver_probe_device+0x100/0x218) [1.375000] [c0268088] (driver_probe_device+0x100/0x218) from [c026822c] (__driver_attach+0x8c/0x90) [1.385000] [c026822c] (__driver_attach+0x8c/0x90) from [c02668a8] (bus_for_each_dev+0x54/0x88) [1.395000] [c02668a8] (bus_for_each_dev+0x54/0x88) from [c0267864] (bus_add_driver+0xd4/0x1d0) [1.405000] [c0267864] (bus_add_driver+0xd4/0x1d0) from [c026884c] (driver_register+0x78/0xf4) [1.415000] [c026884c] (driver_register+0x78/0xf4) from [c00088dc] (do_one_initcall+0xec/0x148) [1.42] [c00088dc] (do_one_initcall+0xec/0x148) from [c0571c48] (kernel_init_freeable+0xfc/0x1c8) [1.43] [c0571c48] (kernel_init_freeable+0xfc/0x1c8) from [c040354c] (kernel_init+0x8/0x110) [1.44] [c040354c] (kernel_init+0x8/0x110) from [c000e738] (ret_from_fork+0x14/0x3c) [1.45] Code: ebfffd18 e354 01a05004 0a08 (e594302c) Looks like a clock issue on 4412? I only have 5250 that I boot test on, no EXYNOS4 coverage at all (I had an
RE: [RFC V3 0/4] dw_mmc platform specific private data and SMU init
On Thursday, August 29, 2013, Jaehoon Chung wrote: Hi Yuvaraj, I have tested on Exynos4 series. I didn't test for SMU feature. If Seungwon could test or review and confirm this patch, then looks good to me. With exynos4 series, Tested-by: Jaehoon Chung jh80.ch...@samsung.com Just now, this series looks good to me. But direct access for SMU concerning (4/4, exynos: configure SMU in exynos5420') will be removed in driver before long. I will sort your patches with the pending others. Acked-by: Seungwon Jeon tgih@samsung.com Thanks, Seungwon Jeon Best Regards. Jaehoon Chung On 08/28/2013 09:08 PM, Yuvaraj Kumar C D wrote: changes from V2: 1.dropped the bypass-smu quirk mmc: dw_mmc: exynos: configure SMU in exynos5420. 2.Changed the subject line for this patch add a quirk for SMU - configure SMU in exynos5420 mmc: dw_mmc: exynos: configure SMU in exynos5420 was earlier mmc: dw_mmc: exynos: add a quirk for SMU. changes from V1: 1.Added a new RFC patch mmc: dw_mmc: socfpga: move socfpga private init 2.Avoid code duplication in mmc: dw_mmc: exynos: add a quirk for SMU. Yuvaraj Kumar C D (4): mmc: dw_mmc: exynos: move the exynos private init mmc: dw_mmc: socfpga: move socfpga private init mmc: dw_mmc: move the platform specific init call mmc: dw_mmc: exynos: configure SMU in exynos5420. drivers/mmc/host/dw_mmc-exynos.c | 56 +++-- drivers/mmc/host/dw_mmc-pltfm.c |7 - drivers/mmc/host/dw_mmc-socfpga.c | 29 ++- drivers/mmc/host/dw_mmc.c |9 ++ 4 files changed, 65 insertions(+), 36 deletions(-) -- To unsubscribe from this list: send the line unsubscribe linux-mmc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html -- To unsubscribe from this list: send the line unsubscribe linux-samsung-soc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
RE: [RFC V3 4/4] mmc: dw_mmc: exynos: configure SMU in exynos5420.
On Wed, August 28, 2013, Yuvaraj Kumar C D wrote: Exynos5420 Mobile Storage Host controller has Security Management Unit (SMU) for channel 0 and channel 1 (mainly for eMMC).This patch configures SMU for exynos5420. This patch is on top of the below patch by Doug Anderson. mmc: dw_mmc: Add exynos resume_noirq callback to clear WAKEUP_INT changes since V2: 1.Droppped the bypass-smu quirk. 2.Changed the subject line for this patch add a quirk for SMU - configure SMU in exynos5420 changes since V1: 1.avoid code duplication by calling dw_mci_exynos_priv_init in resume path. Signed-off-by: Yuvaraj Kumar C D yuvaraj...@samsung.com Signed-off-by: Alim Akhtar alim.akh...@samsung.com --- drivers/mmc/host/dw_mmc-exynos.c | 29 + 1 file changed, 29 insertions(+) diff --git a/drivers/mmc/host/dw_mmc-exynos.c b/drivers/mmc/host/dw_mmc-exynos.c index 19c845b..db28f10 100644 --- a/drivers/mmc/host/dw_mmc-exynos.c +++ b/drivers/mmc/host/dw_mmc-exynos.c @@ -35,6 +35,25 @@ #define EXYNOS4210_FIXED_CIU_CLK_DIV 2 #define EXYNOS4412_FIXED_CIU_CLK_DIV 4 +/* Block number in eMMC */ +#define DWMCI_BLOCK_NUM 0x + +#define SDMMC_EMMCP_BASE 0x1000 +#define SDMMC_MPSECURITY (SDMMC_EMMCP_BASE + 0x0010) +#define SDMMC_MPSBEGIN0 (SDMMC_EMMCP_BASE + 0x0200) +#define SDMMC_MPSEND0(SDMMC_EMMCP_BASE + 0x0204) +#define SDMMC_MPSCTRL0 (SDMMC_EMMCP_BASE + 0x020C) + +/* SMU control bits */ +#define DWMCI_MPSCTRL_SECURE_READ_BITBIT(7) +#define DWMCI_MPSCTRL_SECURE_WRITE_BIT BIT(6) +#define DWMCI_MPSCTRL_NON_SECURE_READ_BITBIT(5) +#define DWMCI_MPSCTRL_NON_SECURE_WRITE_BIT BIT(4) +#define DWMCI_MPSCTRL_USE_FUSE_KEY BIT(3) +#define DWMCI_MPSCTRL_ECB_MODE BIT(2) +#define DWMCI_MPSCTRL_ENCRYPTION BIT(1) +#define DWMCI_MPSCTRL_VALID BIT(0) + /* Variations in Exynos specific dw-mshc controller */ enum dw_mci_exynos_type { DW_MCI_TYPE_EXYNOS4210, @@ -74,6 +93,15 @@ static int dw_mci_exynos_priv_init(struct dw_mci *host) { struct dw_mci_exynos_priv_data *priv = host-priv; + if (priv-ctrl_type == DW_MCI_TYPE_EXYNOS5420) { + mci_writel(host, MPSBEGIN0, 0); + mci_writel(host, MPSEND0, DWMCI_BLOCK_NUM); + mci_writel(host, MPSCTRL0, DWMCI_MPSCTRL_SECURE_WRITE_BIT | + DWMCI_MPSCTRL_NON_SECURE_READ_BIT | + DWMCI_MPSCTRL_VALID | + DWMCI_MPSCTRL_NON_SECURE_WRITE_BIT); Yuvaraj, Just one thing to check. ch#0 and #1 of three hosts are only valid for SMU control. Did you consider #2 host? It seems not. Thanks, Seungwon Jeon + } + return 0; } @@ -107,6 +135,7 @@ static int dw_mci_exynos_resume(struct device *dev) { struct dw_mci *host = dev_get_drvdata(dev); + dw_mci_exynos_priv_init(host); return dw_mci_resume(host); } -- 1.7.9.5 -- To unsubscribe from this list: send the line unsubscribe linux-mmc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html -- To unsubscribe from this list: send the line unsubscribe linux-samsung-soc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
RE: [RFC V3 4/4] mmc: dw_mmc: exynos: configure SMU in exynos5420.
On Thu, August 29, 2013, Alim Akhtar wrote: Hi Seungwon, On Thu, Aug 29, 2013 at 1:53 PM, Seungwon Jeon tgih@samsung.com wrote: On Wed, August 28, 2013, Yuvaraj Kumar C D wrote: Exynos5420 Mobile Storage Host controller has Security Management Unit (SMU) for channel 0 and channel 1 (mainly for eMMC).This patch configures SMU for exynos5420. This patch is on top of the below patch by Doug Anderson. mmc: dw_mmc: Add exynos resume_noirq callback to clear WAKEUP_INT changes since V2: 1.Droppped the bypass-smu quirk. 2.Changed the subject line for this patch add a quirk for SMU - configure SMU in exynos5420 changes since V1: 1.avoid code duplication by calling dw_mci_exynos_priv_init in resume path. Signed-off-by: Yuvaraj Kumar C D yuvaraj...@samsung.com Signed-off-by: Alim Akhtar alim.akh...@samsung.com --- drivers/mmc/host/dw_mmc-exynos.c | 29 + 1 file changed, 29 insertions(+) diff --git a/drivers/mmc/host/dw_mmc-exynos.c b/drivers/mmc/host/dw_mmc-exynos.c index 19c845b..db28f10 100644 --- a/drivers/mmc/host/dw_mmc-exynos.c +++ b/drivers/mmc/host/dw_mmc-exynos.c @@ -35,6 +35,25 @@ #define EXYNOS4210_FIXED_CIU_CLK_DIV 2 #define EXYNOS4412_FIXED_CIU_CLK_DIV 4 +/* Block number in eMMC */ +#define DWMCI_BLOCK_NUM 0x + +#define SDMMC_EMMCP_BASE 0x1000 +#define SDMMC_MPSECURITY (SDMMC_EMMCP_BASE + 0x0010) +#define SDMMC_MPSBEGIN0 (SDMMC_EMMCP_BASE + 0x0200) +#define SDMMC_MPSEND0(SDMMC_EMMCP_BASE + 0x0204) +#define SDMMC_MPSCTRL0 (SDMMC_EMMCP_BASE + 0x020C) + +/* SMU control bits */ +#define DWMCI_MPSCTRL_SECURE_READ_BITBIT(7) +#define DWMCI_MPSCTRL_SECURE_WRITE_BIT BIT(6) +#define DWMCI_MPSCTRL_NON_SECURE_READ_BITBIT(5) +#define DWMCI_MPSCTRL_NON_SECURE_WRITE_BIT BIT(4) +#define DWMCI_MPSCTRL_USE_FUSE_KEY BIT(3) +#define DWMCI_MPSCTRL_ECB_MODE BIT(2) +#define DWMCI_MPSCTRL_ENCRYPTION BIT(1) +#define DWMCI_MPSCTRL_VALID BIT(0) + /* Variations in Exynos specific dw-mshc controller */ enum dw_mci_exynos_type { DW_MCI_TYPE_EXYNOS4210, @@ -74,6 +93,15 @@ static int dw_mci_exynos_priv_init(struct dw_mci *host) { struct dw_mci_exynos_priv_data *priv = host-priv; + if (priv-ctrl_type == DW_MCI_TYPE_EXYNOS5420) { + mci_writel(host, MPSBEGIN0, 0); + mci_writel(host, MPSEND0, DWMCI_BLOCK_NUM); + mci_writel(host, MPSCTRL0, DWMCI_MPSCTRL_SECURE_WRITE_BIT | + DWMCI_MPSCTRL_NON_SECURE_READ_BIT | + DWMCI_MPSCTRL_VALID | + DWMCI_MPSCTRL_NON_SECURE_WRITE_BIT); Yuvaraj, Just one thing to check. ch#0 and #1 of three hosts are only valid for SMU control. Did you consider #2 host? It seems not. Only host#0 and host#1 has SMU (On exynos5420). Host #2 does not contain SMU. Let me clear it. I mean that current change allows for ch2 to access registers related to SMU, even though ch2 doesn't actually has SMU. It's not valid IO area. Thanks, Seungwon Jeon -- To unsubscribe from this list: send the line unsubscribe linux-samsung-soc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
RE: [RFC V3 4/4] mmc: dw_mmc: exynos: configure SMU in exynos5420.
Yuvaraj Kumar wrote: On Thu, Aug 29, 2013 at 3:14 PM, Seungwon Jeon tgih@samsung.com wrote: On Thu, August 29, 2013, Alim Akhtar wrote: Hi Seungwon, On Thu, Aug 29, 2013 at 1:53 PM, Seungwon Jeon tgih@samsung.com wrote: On Wed, August 28, 2013, Yuvaraj Kumar C D wrote: Exynos5420 Mobile Storage Host controller has Security Management Unit (SMU) for channel 0 and channel 1 (mainly for eMMC).This patch configures SMU for exynos5420. This patch is on top of the below patch by Doug Anderson. mmc: dw_mmc: Add exynos resume_noirq callback to clear WAKEUP_INT changes since V2: 1.Droppped the bypass-smu quirk. 2.Changed the subject line for this patch add a quirk for SMU - configure SMU in exynos5420 changes since V1: 1.avoid code duplication by calling dw_mci_exynos_priv_init in resume path. Signed-off-by: Yuvaraj Kumar C D yuvaraj...@samsung.com Signed-off-by: Alim Akhtar alim.akh...@samsung.com --- drivers/mmc/host/dw_mmc-exynos.c | 29 + 1 file changed, 29 insertions(+) diff --git a/drivers/mmc/host/dw_mmc-exynos.c b/drivers/mmc/host/dw_mmc-exynos.c index 19c845b..db28f10 100644 --- a/drivers/mmc/host/dw_mmc-exynos.c +++ b/drivers/mmc/host/dw_mmc-exynos.c @@ -35,6 +35,25 @@ #define EXYNOS4210_FIXED_CIU_CLK_DIV 2 #define EXYNOS4412_FIXED_CIU_CLK_DIV 4 +/* Block number in eMMC */ +#define DWMCI_BLOCK_NUM 0x + +#define SDMMC_EMMCP_BASE 0x1000 +#define SDMMC_MPSECURITY (SDMMC_EMMCP_BASE + 0x0010) +#define SDMMC_MPSBEGIN0 (SDMMC_EMMCP_BASE + 0x0200) +#define SDMMC_MPSEND0(SDMMC_EMMCP_BASE + 0x0204) +#define SDMMC_MPSCTRL0 (SDMMC_EMMCP_BASE + 0x020C) + +/* SMU control bits */ +#define DWMCI_MPSCTRL_SECURE_READ_BITBIT(7) +#define DWMCI_MPSCTRL_SECURE_WRITE_BIT BIT(6) +#define DWMCI_MPSCTRL_NON_SECURE_READ_BITBIT(5) +#define DWMCI_MPSCTRL_NON_SECURE_WRITE_BIT BIT(4) +#define DWMCI_MPSCTRL_USE_FUSE_KEY BIT(3) +#define DWMCI_MPSCTRL_ECB_MODE BIT(2) +#define DWMCI_MPSCTRL_ENCRYPTION BIT(1) +#define DWMCI_MPSCTRL_VALID BIT(0) + /* Variations in Exynos specific dw-mshc controller */ enum dw_mci_exynos_type { DW_MCI_TYPE_EXYNOS4210, @@ -74,6 +93,15 @@ static int dw_mci_exynos_priv_init(struct dw_mci *host) { struct dw_mci_exynos_priv_data *priv = host-priv; + if (priv-ctrl_type == DW_MCI_TYPE_EXYNOS5420) { + mci_writel(host, MPSBEGIN0, 0); + mci_writel(host, MPSEND0, DWMCI_BLOCK_NUM); + mci_writel(host, MPSCTRL0, DWMCI_MPSCTRL_SECURE_WRITE_BIT | + DWMCI_MPSCTRL_NON_SECURE_READ_BIT | + DWMCI_MPSCTRL_VALID | + DWMCI_MPSCTRL_NON_SECURE_WRITE_BIT); Yuvaraj, Just one thing to check. ch#0 and #1 of three hosts are only valid for SMU control. Did you consider #2 host? It seems not. Only host#0 and host#1 has SMU (On exynos5420). Host #2 does not contain SMU. Let me clear it. I mean that current change allows for ch2 to access registers related to SMU, even though ch2 doesn't actually has SMU. It's not valid IO area. No,host#0 and host#1 are compatible with samsung,exynos5420-dw-mshc but host#2 is compatible with the samsung,exynos5250-dw-mshc. Below is the DT patch posted in another thread. [1] [PATCH V4] ARM: dts: Add dwmmc DT nodes for exynos5420 SOC http://www.mail-archive.com/linux-samsung-soc@vger.kernel.org/msg21985.html I will resubmit the DT patch[1] with reg = 0x1222 0x1000 for host#2. Hmm. If we notice exynos5420's other newly added registers apart from SMU, it is difficult to say exynos5420 is compatible with exynos5250 fully for #2. But because there is no use case for new registers, it could be acceptable. Ok, we should be careful to configure DT file though. Thanks, Seungwon Jeon -- To unsubscribe from this list: send the line unsubscribe linux-samsung-soc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
RE: [RFC V3 2/4] mmc: dw_mmc: socfpga: move socfpga private init
On Wed, August 28, 2013, Yuvaraj Kumar C D wrote: Currently platform specific private data initialisation is done by dw_mci_socfpga_priv_init and dw_mci_socfpga_parse_dt.As we already have separate platform specific device tree parser dw_mci_socfpga_parse_dt, move the dw_mci_socfpga_priv_init code to dw_mci_socfpga_parse_dt. We can use the dw_mci_socfpga_priv_init to do some actual platform specific initialisation. This patch is compile tested only. CC'ed Dinh Nguyen Thanks, Seungwon Jeon changes since V2: none Signed-off-by: Yuvaraj Kumar C D yuvaraj...@samsung.com --- drivers/mmc/host/dw_mmc-socfpga.c | 29 ++--- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/drivers/mmc/host/dw_mmc-socfpga.c b/drivers/mmc/host/dw_mmc-socfpga.c index 14b5961..953f260 100644 --- a/drivers/mmc/host/dw_mmc-socfpga.c +++ b/drivers/mmc/host/dw_mmc-socfpga.c @@ -38,20 +38,6 @@ struct dw_mci_socfpga_priv_data { static int dw_mci_socfpga_priv_init(struct dw_mci *host) { - struct dw_mci_socfpga_priv_data *priv; - - priv = devm_kzalloc(host-dev, sizeof(*priv), GFP_KERNEL); - if (!priv) { - dev_err(host-dev, mem alloc failed for private data\n); - return -ENOMEM; - } - - priv-sysreg = syscon_regmap_lookup_by_compatible(altr,sys-mgr); - if (IS_ERR(priv-sysreg)) { - dev_err(host-dev, regmap for altr,sys-mgr lookup failed.\n); - return PTR_ERR(priv-sysreg); - } - host-priv = priv; return 0; } @@ -79,12 +65,24 @@ static void dw_mci_socfpga_prepare_command(struct dw_mci *host, u32 *cmdr) static int dw_mci_socfpga_parse_dt(struct dw_mci *host) { - struct dw_mci_socfpga_priv_data *priv = host-priv; + struct dw_mci_socfpga_priv_data *priv; struct device_node *np = host-dev-of_node; u32 timing[2]; u32 div = 0; int ret; + priv = devm_kzalloc(host-dev, sizeof(*priv), GFP_KERNEL); + if (!priv) { + dev_err(host-dev, mem alloc failed for private data\n); + return -ENOMEM; + } + + priv-sysreg = syscon_regmap_lookup_by_compatible(altr,sys-mgr); + if (IS_ERR(priv-sysreg)) { + dev_err(host-dev, regmap for altr,sys-mgr lookup failed.\n); + return PTR_ERR(priv-sysreg); + } + ret = of_property_read_u32(np, altr,dw-mshc-ciu-div, div); if (ret) dev_info(host-dev, No dw-mshc-ciu-div specified, assuming 1); @@ -96,6 +94,7 @@ static int dw_mci_socfpga_parse_dt(struct dw_mci *host) return ret; priv-hs_timing = SYSMGR_SDMMC_CTRL_SET(timing[0], timing[1]); + host-priv = priv; return 0; } -- 1.7.9.5 -- To unsubscribe from this list: send the line unsubscribe linux-mmc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html -- To unsubscribe from this list: send the line unsubscribe linux-samsung-soc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
RE: [RFC V3 4/4] mmc: dw_mmc: exynos: configure SMU in exynos5420.
On Thu, August 29, 2013, Tomasz Figa wrote: Hi Seungwon, On Thursday 29 of August 2013 19:36:28 Seungwon Jeon wrote: Yuvaraj Kumar wrote: On Thu, Aug 29, 2013 at 3:14 PM, Seungwon Jeon tgih@samsung.com wrote: On Thu, August 29, 2013, Alim Akhtar wrote: Hi Seungwon, On Thu, Aug 29, 2013 at 1:53 PM, Seungwon Jeon tgih@samsung.com wrote: On Wed, August 28, 2013, Yuvaraj Kumar C D wrote: Exynos5420 Mobile Storage Host controller has Security Management Unit (SMU) for channel 0 and channel 1 (mainly for eMMC).This patch configures SMU for exynos5420. This patch is on top of the below patch by Doug Anderson. mmc: dw_mmc: Add exynos resume_noirq callback to clear WAKEUP_INT changes since V2: 1.Droppped the bypass-smu quirk. 2.Changed the subject line for this patch add a quirk for SMU - configure SMU in exynos5420 changes since V1: 1.avoid code duplication by calling dw_mci_exynos_priv_init in resume path. Signed-off-by: Yuvaraj Kumar C D yuvaraj...@samsung.com Signed-off-by: Alim Akhtar alim.akh...@samsung.com --- drivers/mmc/host/dw_mmc-exynos.c | 29 + 1 file changed, 29 insertions(+) diff --git a/drivers/mmc/host/dw_mmc-exynos.c b/drivers/mmc/host/dw_mmc-exynos.c index 19c845b..db28f10 100644 --- a/drivers/mmc/host/dw_mmc-exynos.c +++ b/drivers/mmc/host/dw_mmc-exynos.c @@ -35,6 +35,25 @@ #define EXYNOS4210_FIXED_CIU_CLK_DIV 2 #define EXYNOS4412_FIXED_CIU_CLK_DIV 4 +/* Block number in eMMC */ +#define DWMCI_BLOCK_NUM 0x + +#define SDMMC_EMMCP_BASE 0x1000 +#define SDMMC_MPSECURITY (SDMMC_EMMCP_BASE + 0x0010) +#define SDMMC_MPSBEGIN0 (SDMMC_EMMCP_BASE + 0x0200) +#define SDMMC_MPSEND0 (SDMMC_EMMCP_BASE + 0x0204) +#define SDMMC_MPSCTRL0 (SDMMC_EMMCP_BASE + 0x020C) + +/* SMU control bits */ +#define DWMCI_MPSCTRL_SECURE_READ_BITBIT(7) +#define DWMCI_MPSCTRL_SECURE_WRITE_BIT BIT(6) +#define DWMCI_MPSCTRL_NON_SECURE_READ_BITBIT(5) +#define DWMCI_MPSCTRL_NON_SECURE_WRITE_BIT BIT(4) +#define DWMCI_MPSCTRL_USE_FUSE_KEY BIT(3) +#define DWMCI_MPSCTRL_ECB_MODE BIT(2) +#define DWMCI_MPSCTRL_ENCRYPTION BIT(1) +#define DWMCI_MPSCTRL_VALID BIT(0) + /* Variations in Exynos specific dw-mshc controller */ enum dw_mci_exynos_type { DW_MCI_TYPE_EXYNOS4210, @@ -74,6 +93,15 @@ static int dw_mci_exynos_priv_init(struct dw_mci *host) { struct dw_mci_exynos_priv_data *priv = host-priv; + if (priv-ctrl_type == DW_MCI_TYPE_EXYNOS5420) { + mci_writel(host, MPSBEGIN0, 0); + mci_writel(host, MPSEND0, DWMCI_BLOCK_NUM); + mci_writel(host, MPSCTRL0, DWMCI_MPSCTRL_SECURE_WRITE_BIT | + DWMCI_MPSCTRL_NON_SECURE_READ_BIT | + DWMCI_MPSCTRL_VALID | + DWMCI_MPSCTRL_NON_SECURE_WRITE_BIT); Yuvaraj, Just one thing to check. ch#0 and #1 of three hosts are only valid for SMU control. Did you consider #2 host? It seems not. Only host#0 and host#1 has SMU (On exynos5420). Host #2 does not contain SMU. Let me clear it. I mean that current change allows for ch2 to access registers related to SMU, even though ch2 doesn't actually has SMU. It's not valid IO area. No,host#0 and host#1 are compatible with samsung,exynos5420-dw-mshc but host#2 is compatible with the samsung,exynos5250-dw-mshc. Below is the DT patch posted in another thread. [1] [PATCH V4] ARM: dts: Add dwmmc DT nodes for exynos5420 SOC http://www.mail-archive.com/linux-samsung-soc@vger.kernel.org/msg21985. html I will resubmit the DT patch[1] with reg = 0x1222 0x1000 for host#2. Hmm. If we notice exynos5420's other newly added registers apart from SMU, it is difficult to say exynos5420 is compatible with exynos5250 fully for #2. But because there is no use case for new registers, it could be acceptable. Ok, we should be careful to configure DT file though. Could you elaborate a bit more on the differences in DW MMC IP between Exynos5250 and Exynos5420? If the differences are significant, then it might be necessary to use different compatible value, as it should not depend on any use case (or lack of). Actually the reason is that extended register of ch2 doesn't work rather than none of use case. Ch2 is targeted for removable card type. If the DW MMC version used in Exynos 5420 provides the whole set of functionality
RE: [PATCH v5 0/4] mmc: dw_mmc: fixes for suspend/resume on exynos
Hi Doug, Do you have any update for this series? Please let me know. Thanks, Seungwon Jeon On Sat, August 10, 2013, Doug Anderson wrote: This series of patches addresses some suspend/resume problems with dw_mmc on exynos platforms, espeically exynos5420. Since suspend/resume is not fully working on ToT Linux (v3.11-rc4) on exynos5250-snow, this series was tested against the current ToT ChromeOS 3.8 tree. I have confirmed basic booting and eMMC / SD card usage (and compiling, honest!) against ToT Linux. I have received confirmation from Samsung that the problem solved is a silicon errata on exynos5420 and that this is a good fix. Changes in v5: - Remove force_clkinit as per Jaehoon. - Update commit message to (hopefully) be clearer. - Cleaned up dw_mci_exynos_resume_noirq() comment as per Seungwon. - Don't memcpy dev_pm_ops structure, define a new one. Changes in v4: - Take Seungwon's suggestion and don't add any dw_mmc-pltfm code. Changes in v3: - Add freeze/thaw and poweroff/restore noirq entries. Changes in v2: - Fix typo (some - come) - Use ~0 instead of 0x; add comment about value - Use suspend_noirq as per James Hogan. Doug Anderson (4): mmc: dw_mmc: Invalidate cache of current_speed after suspend/resume mmc: dw_mmc: Add exynos resume_noirq callback to clear WAKEUP_INT mmc: dw_mmc: Always setup the bus after suspend/resume mmc: dw_mmc: Set timeout to max upon resume drivers/mmc/host/dw_mmc-exynos.c | 56 +++- drivers/mmc/host/dw_mmc.c| 21 ++- 2 files changed, 69 insertions(+), 8 deletions(-) -- 1.8.3 -- To unsubscribe from this list: send the line unsubscribe linux-mmc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html -- To unsubscribe from this list: send the line unsubscribe linux-samsung-soc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
RE: [PATCH v5 2/4] mmc: dw_mmc: Add exynos resume_noirq callback to clear WAKEUP_INT
Doug, Looks good to me except for minor comment. On Sat, August 10, 2013, Doug Anderson wrote: If the WAKEUP_INT is asserted at wakeup and not cleared, we'll end up looping around forever. This has been seen to happen on exynos5420 silicon despite the fact that we haven't enabled any wakeup events due to a silicon errata. It is safe to do on all exynos variants. Signed-off-by: Doug Anderson diand...@chromium.org --- Changes in v5: - Cleaned up dw_mci_exynos_resume_noirq() comment as per Seungwon. - Don't memcpy dev_pm_ops structure, define a new one. Changes in v4: - Take Seungwon's suggestion and don't add any dw_mmc-pltfm code. Changes in v3: - Add freeze/thaw and poweroff/restore noirq entries. Changes in v2: - Use suspend_noirq as per James Hogan. drivers/mmc/host/dw_mmc-exynos.c | 56 +++- 1 file changed, 55 insertions(+), 1 deletion(-) diff --git a/drivers/mmc/host/dw_mmc-exynos.c b/drivers/mmc/host/dw_mmc-exynos.c index 866edef..7d88583 100644 --- a/drivers/mmc/host/dw_mmc-exynos.c +++ b/drivers/mmc/host/dw_mmc-exynos.c @@ -30,6 +30,7 @@ #define SDMMC_CLKSEL_TIMING(x, y, z) (SDMMC_CLKSEL_CCLK_SAMPLE(x) | \ SDMMC_CLKSEL_CCLK_DRIVE(y) |\ SDMMC_CLKSEL_CCLK_DIVIDER(z)) +#define SDMMC_CLKSEL_WAKEUP_INT BIT(11) #define EXYNOS4210_FIXED_CIU_CLK_DIV 2 #define EXYNOS4412_FIXED_CIU_CLK_DIV 4 @@ -100,6 +101,52 @@ static int dw_mci_exynos_setup_clock(struct dw_mci *host) return 0; } +#ifdef CONFIG_PM_SLEEP +/* + * TODO: we should probably disable the clock to the card in the suspend path. In suspend, clock is gated, isn't it? Rather, no comment looks better, if intention is not clear. Thanks, Seungwon Jeon + */ +static int dw_mci_exynos_suspend(struct device *dev) +{ + struct dw_mci *host = dev_get_drvdata(dev); + + return dw_mci_suspend(host); +} + +static int dw_mci_exynos_resume(struct device *dev) +{ + struct dw_mci *host = dev_get_drvdata(dev); + + return dw_mci_resume(host); +} + +/** + * dw_mci_exynos_resume_noirq - Exynos-specific resume code + * + * On exynos5420 there is a silicon errata that will sometimes leave the + * WAKEUP_INT bit in the CLKSEL register asserted. This bit is 1 to indicate + * that it fired and we can clear it by writing a 1 back. Clear it to prevent + * interrupts from going off constantly. + * + * We run this code on all exynos variants because it doesn't hurt. + */ + +static int dw_mci_exynos_resume_noirq(struct device *dev) +{ + struct dw_mci *host = dev_get_drvdata(dev); + u32 clksel; + + clksel = mci_readl(host, CLKSEL); + if (clksel SDMMC_CLKSEL_WAKEUP_INT) + mci_writel(host, CLKSEL, clksel); + + return 0; +} +#else +#define dw_mci_exynos_suspendNULL +#define dw_mci_exynos_resume NULL +#define dw_mci_exynos_resume_noirq NULL +#endif /* CONFIG_PM_SLEEP */ + static void dw_mci_exynos_prepare_command(struct dw_mci *host, u32 *cmdr) { /* @@ -187,13 +234,20 @@ static int dw_mci_exynos_probe(struct platform_device *pdev) return dw_mci_pltfm_register(pdev, drv_data); } +const struct dev_pm_ops dw_mci_exynos_pmops = { + SET_SYSTEM_SLEEP_PM_OPS(dw_mci_exynos_suspend, dw_mci_exynos_resume) + .resume_noirq = dw_mci_exynos_resume_noirq, + .thaw_noirq = dw_mci_exynos_resume_noirq, + .restore_noirq = dw_mci_exynos_resume_noirq, +}; + static struct platform_driver dw_mci_exynos_pltfm_driver = { .probe = dw_mci_exynos_probe, .remove = __exit_p(dw_mci_pltfm_remove), .driver = { .name = dwmmc_exynos, .of_match_table = dw_mci_exynos_match, - .pm = dw_mci_pltfm_pmops, + .pm = dw_mci_exynos_pmops, }, }; -- 1.8.3 -- To unsubscribe from this list: send the line unsubscribe linux-mmc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html -- To unsubscribe from this list: send the line unsubscribe linux-samsung-soc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
RE: [PATCH v4 2/4] mmc: dw_mmc: Add exynos resume_noirq callback to clear WAKEUP_INT
On Wed, August 07, 2013, Doug Anderson wrote: If the WAKEUP_INT is asserted at wakeup and not cleared, we'll end up looping around forever. This has been seen to happen on exynos5420 silicon despite the fact that we haven't enabled any wakeup events due to a silicon errata. It is safe to do on all exynos variants. Signed-off-by: Doug Anderson diand...@chromium.org --- Changes in v4: - Take Seungwon's suggestion and don't add any dw_mmc-pltfm code. Changes in v3: - Add freeze/thaw and poweroff/restore noirq entries. Changes in v2: - Use suspend_noirq as per James Hogan. drivers/mmc/host/dw_mmc-exynos.c | 51 ++-- 1 file changed, 49 insertions(+), 2 deletions(-) diff --git a/drivers/mmc/host/dw_mmc-exynos.c b/drivers/mmc/host/dw_mmc-exynos.c index 866edef..0c1f192 100644 --- a/drivers/mmc/host/dw_mmc-exynos.c +++ b/drivers/mmc/host/dw_mmc-exynos.c @@ -30,6 +30,7 @@ #define SDMMC_CLKSEL_TIMING(x, y, z) (SDMMC_CLKSEL_CCLK_SAMPLE(x) | \ SDMMC_CLKSEL_CCLK_DRIVE(y) |\ SDMMC_CLKSEL_CCLK_DIVIDER(z)) +#define SDMMC_CLKSEL_WAKEUP_INT BIT(11) #define EXYNOS4210_FIXED_CIU_CLK_DIV 2 #define EXYNOS4412_FIXED_CIU_CLK_DIV 4 @@ -100,6 +101,30 @@ static int dw_mci_exynos_setup_clock(struct dw_mci *host) return 0; } +/** + * dw_mci_exynos_resume_noirq - Exynos-specific resume code + * + * On exynos5420 there is a silicon errata that will sometimes leave the + * WAKEUP_INT bit in the CLKSEL register asserted. This bit is 1 to indicate + * that it fired and we can clear it by writing a 1 back. Clear it to prevent + * interrupts from going off constantly. + * + * We run this code on all exynos variants because it doesn't hurt and the bug + * may be more widespread than just exynos5420. I guess just above comment can be removed. (Not be widespread) Updating the origin value of CLKSEL looks like no harm while SDMMC_CLKSEL_WAKEUP_INT is cleared. + */ + +static int dw_mci_exynos_resume_noirq(struct device *dev) +{ + struct dw_mci *host = dev_get_drvdata(dev); + u32 clksel; + + clksel = mci_readl(host, CLKSEL); + if (clksel SDMMC_CLKSEL_WAKEUP_INT) + mci_writel(host, CLKSEL, clksel); + + return 0; +} + static void dw_mci_exynos_prepare_command(struct dw_mci *host, u32 *cmdr) { /* @@ -187,17 +212,39 @@ static int dw_mci_exynos_probe(struct platform_device *pdev) return dw_mci_pltfm_register(pdev, drv_data); } +static struct dev_pm_ops dw_mci_exynos_pmops; + static struct platform_driver dw_mci_exynos_pltfm_driver = { .probe = dw_mci_exynos_probe, .remove = __exit_p(dw_mci_pltfm_remove), .driver = { .name = dwmmc_exynos, .of_match_table = dw_mci_exynos_match, - .pm = dw_mci_pltfm_pmops, + .pm = dw_mci_exynos_pmops, }, }; -module_platform_driver(dw_mci_exynos_pltfm_driver); +static int __init dw_mci_exynos_init(void) +{ + /* Add a noirq resume to platform pmops */ + memcpy(dw_mci_exynos_pmops, dw_mci_pltfm_pmops, +sizeof(dw_mci_exynos_pmops)); + WARN_ON(dw_mci_exynos_pmops.resume_noirq || + dw_mci_exynos_pmops.thaw_noirq || + dw_mci_exynos_pmops.restore_noirq); + dw_mci_exynos_pmops.resume_noirq = dw_mci_exynos_resume_noirq; + dw_mci_exynos_pmops.thaw_noirq = dw_mci_exynos_resume_noirq; + dw_mci_exynos_pmops.restore_noirq = dw_mci_exynos_resume_noirq; If CONFIG_PM_SLEEP is not defined, we don't need to add it. And also, instead of reusing dw_mci_pltfm_pmops, how about defining dw_mci_exynos_pmops's own? Of course, suspend/resume will not different with dw_mci_pltfm* just now. But specific code for exynos would be added soon. Thanks, Seungwon Jeon -- To unsubscribe from this list: send the line unsubscribe linux-samsung-soc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
RE: dw_mmc: Does anyone use multiple slots?
On Fri, August 09, 2013, Chris Ball wrote: On Fri, Aug 09 2013, Olof Johansson wrote: On Thu, Aug 8, 2013 at 5:16 PM, Doug Anderson diand...@google.com wrote: I guess my overall question is: if there are no actual implementations of multislot, shouldn't we kill it and simplify the code a whole lot? If someone out there has a real multislot device they can step back in and do it more correctly? Of course we need to find someone to actually go through and do the killing of multislot, but finding that person might be easier if there was some agreement that it was good to do. There clearly seems to be no in-tree users of multislot. If someone new comes in, we have the code in the history and can revert the removal (or at least use it as reference for re-introduction). I vote for removing it. It adds really annoying complexity for something that nobody uses. I agree with Olof, for what it's worth. (The maintainers of the driver are Jaehoon and Seungwon, though.) I feel like there is no actual use case for that though origin Synopsys IP supports. Multi-slot might be not useful in terms of performance because shared bus should be allowed. (At least this is the way I see it, though) As Exynos's host does so, other hosts which are introduced in Linux seems use one card per host. If it's really not found now, I could agree on this topic. Thanks, Seungwon Jeon -- To unsubscribe from this list: send the line unsubscribe linux-samsung-soc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
RE: [PATCH v2 3/5] mmc: dw_mmc: Add exynos resume_noirq callback to clear WAKEUP_INT
On Thu, July 11, 2013, Doug Anderson wrote: Seungwon, On Wed, Jul 10, 2013 at 7:54 AM, Seungwon Jeon tgih@samsung.com wrote: On Wed, July 10, 2013, Doug Anderson wrote: If the WAKEUP_INT is asserted at wakeup and not cleared, we'll end up looping around forever. This has been seen to happen on exynos5420 silicon despite the fact that we haven't enabled any wakeup events. Signed-off-by: Doug Anderson diand...@chromium.org --- Changes in v2: - Use suspend_noirq as per James Hogan. drivers/mmc/host/dw_mmc-exynos.c | 23 +++ 1 file changed, 23 insertions(+) diff --git a/drivers/mmc/host/dw_mmc-exynos.c b/drivers/mmc/host/dw_mmc-exynos.c index f013e7e..36b9620 100644 --- a/drivers/mmc/host/dw_mmc-exynos.c +++ b/drivers/mmc/host/dw_mmc-exynos.c @@ -30,6 +30,7 @@ #define SDMMC_CLKSEL_TIMING(x, y, z) (SDMMC_CLKSEL_CCLK_SAMPLE(x) | \ SDMMC_CLKSEL_CCLK_DRIVE(y) |\ SDMMC_CLKSEL_CCLK_DIVIDER(z)) +#define SDMMC_CLKSEL_WAKEUP_INT BIT(11) #define SDMMC_CMD_USE_HOLD_REG BIT(29) @@ -102,6 +103,27 @@ static int dw_mci_exynos_setup_clock(struct dw_mci *host) return 0; } +/** + * dw_mci_exynos_resume_noirq - Exynos-specific resume code + * + * We have seen cases (at least on the exynos5420) where turning off the INT + * power rail during suspend will leave the WAKEUP_INT bit in the CLKSEL + * register asserted. This bit is 1 to indicate that it fired and we can + * clear it by writing a 1 back. Clear it to prevent interrupts from going off + * constantly. + */ As I know this bit is auto-cleared. Did you find the cause of this problem? How about your GPIO setting in sleep? Currently, we don't know why the problem is happened. At least, we should make it clear. Yes, the documentation that I have says that this bit is auto cleared as well but doesn't indicate under what conditions it is auto cleared. From testing how this bit reacts I have found that writing a 1 to it clears the bit--in other words it behaves like bits in RINTSTS. That's a terrible design for a bit in a register with shared config but appears to be how it works. Note: in a sense it will be auto cleared because doing a read-modify-write of any other bits in this register will clear the interrupt. I have asked for official confirmation. We have found that on exynos5420 bits 8-10 of CLKSEL are marked as RESERVED. Those bits are documented to enable the WAKEUP_INT on exynos5250. My best guess is that these bits are not used on exynos5420 and the WAKEUP_INT line is left floating, which means it can fire randomly. I have also asked for official confirmation about this. Sorry for late response. Yes, it's not clear. If you get the confirmation, could you share this problem? Possibly, auto-clear may not be implemented. Then, manual should be correct. Thanks, Seungwon Jeon I will likely merge this change locally in our kernel tree while waiting for a response. If you would like to wait before Acking that's very reasonable. Do you have any other problems with this change assuming my understanding above is correct? -Doug -- To unsubscribe from this list: send the line unsubscribe linux-mmc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html -- To unsubscribe from this list: send the line unsubscribe linux-samsung-soc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
RE: [PATCH v2 3/5] mmc: dw_mmc: Add exynos resume_noirq callback to clear WAKEUP_INT
On Wed, July 10, 2013, Doug Anderson wrote: If the WAKEUP_INT is asserted at wakeup and not cleared, we'll end up looping around forever. This has been seen to happen on exynos5420 silicon despite the fact that we haven't enabled any wakeup events. Signed-off-by: Doug Anderson diand...@chromium.org --- Changes in v2: - Use suspend_noirq as per James Hogan. drivers/mmc/host/dw_mmc-exynos.c | 23 +++ 1 file changed, 23 insertions(+) diff --git a/drivers/mmc/host/dw_mmc-exynos.c b/drivers/mmc/host/dw_mmc-exynos.c index f013e7e..36b9620 100644 --- a/drivers/mmc/host/dw_mmc-exynos.c +++ b/drivers/mmc/host/dw_mmc-exynos.c @@ -30,6 +30,7 @@ #define SDMMC_CLKSEL_TIMING(x, y, z) (SDMMC_CLKSEL_CCLK_SAMPLE(x) | \ SDMMC_CLKSEL_CCLK_DRIVE(y) |\ SDMMC_CLKSEL_CCLK_DIVIDER(z)) +#define SDMMC_CLKSEL_WAKEUP_INT BIT(11) #define SDMMC_CMD_USE_HOLD_REG BIT(29) @@ -102,6 +103,27 @@ static int dw_mci_exynos_setup_clock(struct dw_mci *host) return 0; } +/** + * dw_mci_exynos_resume_noirq - Exynos-specific resume code + * + * We have seen cases (at least on the exynos5420) where turning off the INT + * power rail during suspend will leave the WAKEUP_INT bit in the CLKSEL + * register asserted. This bit is 1 to indicate that it fired and we can + * clear it by writing a 1 back. Clear it to prevent interrupts from going off + * constantly. + */ As I know this bit is auto-cleared. Did you find the cause of this problem? How about your GPIO setting in sleep? Currently, we don't know why the problem is happened. At least, we should make it clear. Thanks, Seungwon Jeon + +static int dw_mci_exynos_resume_noirq(struct dw_mci *host) +{ + u32 clksel; + + clksel = mci_readl(host, CLKSEL); + if (clksel SDMMC_CLKSEL_WAKEUP_INT) + mci_writel(host, CLKSEL, clksel); + + return 0; +} + static void dw_mci_exynos_prepare_command(struct dw_mci *host, u32 *cmdr) { /* @@ -165,6 +187,7 @@ static const struct dw_mci_drv_data exynos_drv_data = { .caps = exynos_dwmmc_caps, .init = dw_mci_exynos_priv_init, .setup_clock= dw_mci_exynos_setup_clock, + .resume_noirq = dw_mci_exynos_resume_noirq, .prepare_command= dw_mci_exynos_prepare_command, .set_ios= dw_mci_exynos_set_ios, .parse_dt = dw_mci_exynos_parse_dt, -- 1.8.3 -- To unsubscribe from this list: send the line unsubscribe linux-mmc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html -- To unsubscribe from this list: send the line unsubscribe linux-samsung-soc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
RE: [PATCH v4] mmc: dw_mmc: let device core setup the default pin configuration
On Wednesday, April 10, 2013, Doug Anderson wrote: Thomas, On Wed, Apr 10, 2013 at 6:56 AM, Doug Anderson diand...@chromium.org wrote: On Wed, Apr 10, 2013 at 5:48 AM, Thomas Abraham thomas.abra...@linaro.org wrote: The call to regulator_enable() is prior to the call to mmc_add_host(). Hence, call to mmc_fre_host is not required in this case. So the above change should be right. Are you sure that mmc_free_host() is the opposite of mmc_add_host() and not mmc_alloc_host()? I'll double-check myself in a few hours when I'm in front of a computer. OK, I double checked and I'm still convinced that the free is needed because we've already called mmc_alloc_host(). Current code always makes sure to free when it returns an error and that seems right to me. mmc_alloc_host corresponds to mmc_free_host. And mmc_add_host matches with mmc_remove_host. Let's focus on mmc_alloc_host. mmc_alloc_host is called prior to regulator_enable. So, if regulator_enable is failed, call of mmc_free_host makes sense. Thanks, Seungwon Jeon -Doug -- To unsubscribe from this list: send the line unsubscribe linux-mmc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html -- To unsubscribe from this list: send the line unsubscribe linux-samsung-soc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
RE: [PATCH v3] mmc: dw_mmc: let device core setup the default pin configuration
On Friday, April 05, 2013, Thomas Abraham wrote: With device core now able to setup the default pin configuration, the pin configuration code based on the deprecated Samsung specific gpio bindings is removed. Signed-off-by: Thomas Abraham thomas.abra...@linaro.org Acked-by: Seungwon Jeon tgih@samsung.com I hope that your another patch is merged. ARM: dts: add pinctrl nodes for Exynos5250 SoC I didn't check whether it is applied. Thanks, Seungwon Jeon -- To unsubscribe from this list: send the line unsubscribe linux-samsung-soc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
RE: [PATCH v2] mmc: dwmmc: let device core setup the default pin configuration
On Wednesday, April 03, 2013, Doug Anderson wrote: Thomas, On Mon, Apr 1, 2013 at 11:09 PM, Thomas Abraham thomas.abra...@linaro.org wrote: With device core now able to setup the default pin configuration, the pin configuration code based on the deprecated Samsung specific gpio bindings is removed. Signed-off-by: Thomas Abraham thomas.abra...@linaro.org Acked-by: Linus Walleij linus.wall...@linaro.org Reviewed-by: Doug Anderson diand...@chromium.org Tested-by: Doug Anderson diand...@chromium.org You missed Seungwon's other feedback. Please change the title from mmc: dwmmc: let device core setup the default pin configuration to mmc: dw_mmc: let device core setup the default pin configuration. He requested that the tag have the underscore in it for consistency. If you're resending, it also seems like it might be nice to rebase this atop: 0f6e73d mmc: dw_mmc: Add MSHC compatible for Exynos4412 ...just to avoid the simple merge conflict when applying? Otherwise everything here looks great... -Doug Thomas, It's a conflict to merge. Please do rebase the patch. Thanks, Seungwon Jeon -- To unsubscribe from this list: send the line unsubscribe linux-samsung-soc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
RE: [PATCH] mmc: dwmmc: let device core setup the default pin configuration
Hi Thomas, On Wednesday, March 06, 2013, Thomas Abraham wrote: With device core now able to setup the default pin configuration, the pin configuration code based on the deprecated Samsung specific gpio bindings is removed. 'setup_bus' callback is still useful in dw_mci_drv_data? Considering the purpose, it would be good to remove. And, could you change commit prefix for consistency? dwmmc - dw_mmc Thanks, Seungwon Jeon Signed-off-by: Thomas Abraham thomas.abra...@linaro.org --- drivers/mmc/host/dw_mmc-exynos.c | 38 -- 1 files changed, 0 insertions(+), 38 deletions(-) diff --git a/drivers/mmc/host/dw_mmc-exynos.c b/drivers/mmc/host/dw_mmc-exynos.c index 72fd0f2..467d043 100644 --- a/drivers/mmc/host/dw_mmc-exynos.c +++ b/drivers/mmc/host/dw_mmc-exynos.c @@ -152,43 +152,6 @@ static int dw_mci_exynos_parse_dt(struct dw_mci *host) return 0; } -static int dw_mci_exynos_setup_bus(struct dw_mci *host, - struct device_node *slot_np, u8 bus_width) -{ - int idx, gpio, ret; - - if (!slot_np) - return -EINVAL; - - /* cmd + clock + bus-width pins */ - for (idx = 0; idx NUM_PINS(bus_width); idx++) { - gpio = of_get_gpio(slot_np, idx); - if (!gpio_is_valid(gpio)) { - dev_err(host-dev, invalid gpio: %d\n, gpio); - return -EINVAL; - } - - ret = devm_gpio_request(host-dev, gpio, dw-mci-bus); - if (ret) { - dev_err(host-dev, gpio [%d] request failed\n, gpio); - return -EBUSY; - } - } - - if (host-pdata-quirks DW_MCI_QUIRK_BROKEN_CARD_DETECTION) - return 0; - - gpio = of_get_named_gpio(slot_np, samsung,cd-pinmux-gpio, 0); - if (gpio_is_valid(gpio)) { - if (devm_gpio_request(host-dev, gpio, dw-mci-cd)) - dev_err(host-dev, gpio [%d] request failed\n, gpio); - } else { - dev_info(host-dev, cd gpio not available); - } - - return 0; -} - /* Exynos5250 controller specific capabilities */ static unsigned long exynos5250_dwmmc_caps[4] = { MMC_CAP_UHS_DDR50 | MMC_CAP_1_8V_DDR | @@ -205,7 +168,6 @@ static const struct dw_mci_drv_data exynos5250_drv_data = { .prepare_command= dw_mci_exynos_prepare_command, .set_ios= dw_mci_exynos_set_ios, .parse_dt = dw_mci_exynos_parse_dt, - .setup_bus = dw_mci_exynos_setup_bus, }; static const struct of_device_id dw_mci_exynos_match[] = { -- 1.6.6.rc2 -- To unsubscribe from this list: send the line unsubscribe linux-mmc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html -- To unsubscribe from this list: send the line unsubscribe linux-samsung-soc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
RE: [PATCH v3 1/4] mmc: dw_mmc: Add disable-wp device tree property
Doug, Thanks to work. Looks good to me with other patches. Acked-by: Seungwon Jeon tgih@samsung.com On Friday, November 30, 2012, Doug Anderson wrote: The disable-wp property is used to specify that a given SD card slot doesn't have a concept of write protect. This eliminates the need for special case code for SD slots that should never be write protected (like a micro SD slot or a dev board). The dw_mmc driver is special in needing to specify disable-wp because the lack of a wp-gpios property means to use the special purpose write protect line. On some other mmc devices the lack of wp-gpios means that write protect should be disabled. Signed-off-by: Doug Anderson diand...@chromium.org --- Changes in v3: - New for this version of the patch series. Chose disable-wp rather than the discussed broken-internal-wp since it mapped more cleanly to an existing quirk (and the only reason to specify that the internal wp is broken is if you're disabling the write protect anyway). .../devicetree/bindings/mmc/synopsis-dw-mshc.txt | 12 +- drivers/mmc/host/dw_mmc.c | 36 +++- include/linux/mmc/dw_mmc.h |4 ++ 3 files changed, 49 insertions(+), 3 deletions(-) diff --git a/Documentation/devicetree/bindings/mmc/synopsis-dw-mshc.txt b/Documentation/devicetree/bindings/mmc/synopsis-dw-mshc.txt index 06cd32d08..726fd21 100644 --- a/Documentation/devicetree/bindings/mmc/synopsis-dw-mshc.txt +++ b/Documentation/devicetree/bindings/mmc/synopsis-dw-mshc.txt @@ -26,8 +26,16 @@ Required Properties: * bus-width: as documented in mmc core bindings. * wp-gpios: specifies the write protect gpio line. The format of the - gpio specifier depends on the gpio controller. If the write-protect - line is not available, this property is optional. + gpio specifier depends on the gpio controller. If a GPIO is not used + for write-protect, this property is optional. + + * disable-wp: If the wp-gpios property isn't present then (by default) + we'd assume that the write protect is hooked up directly to the + controller's special purpose write protect line (accessible via + the WRTPRT register). However, it's possible that we simply don't + want write protect. In that case specify 'disable-wp'. + NOTE: This property is not required for slots known to always + connect to eMMC or SDIO cards. Optional properties: diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index 7342029..b47b1e9 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c @@ -74,6 +74,7 @@ struct idmac_desc { * struct dw_mci_slot - MMC slot state * @mmc: The mmc_host representing this slot. * @host: The MMC controller this slot is using. + * @quirks: Slot-level quirks (DW_MCI_SLOT_QUIRK_XXX) * @ctype: Card type for this slot. * @mrq: mmc_request currently being processed or waiting to be * processed, or NULL when the slot is idle. @@ -88,6 +89,8 @@ struct dw_mci_slot { struct mmc_host *mmc; struct dw_mci *host; + int quirks; + u32 ctype; struct mmc_request *mrq; @@ -828,7 +831,8 @@ static int dw_mci_get_ro(struct mmc_host *mmc) struct dw_mci_board *brd = slot-host-pdata; /* Use platform get_ro function, else try on board write protect */ - if (brd-quirks DW_MCI_QUIRK_NO_WRITE_PROTECT) + if ((brd-quirks DW_MCI_QUIRK_NO_WRITE_PROTECT) || + (slot-quirks DW_MCI_SLOT_QUIRK_NO_WRITE_PROTECT)) read_only = 0; else if (brd-get_ro) read_only = brd-get_ro(slot-id); @@ -1788,6 +1792,30 @@ static struct device_node *dw_mci_of_find_slot_node(struct device *dev, u8 slot) return NULL; } +static struct dw_mci_of_slot_quirks { + char *quirk; + int id; +} of_slot_quirks[] = { + { + .quirk = disable-wp, + .id = DW_MCI_SLOT_QUIRK_NO_WRITE_PROTECT, + }, +}; + +static int dw_mci_of_get_slot_quirks(struct device *dev, u8 slot) +{ + struct device_node *np = dw_mci_of_find_slot_node(dev, slot); + int quirks = 0; + int idx; + + /* get quirks */ + for (idx = 0; idx ARRAY_SIZE(of_slot_quirks); idx++) + if (of_get_property(np, of_slot_quirks[idx].quirk, NULL)) + quirks |= of_slot_quirks[idx].id; + + return quirks; +} + /* find out bus-width for a given slot */ static u32 dw_mci_of_get_bus_wd(struct device *dev, u8 slot) { @@ -1803,6 +1831,10 @@ static u32 dw_mci_of_get_bus_wd(struct device *dev, u8 slot) return bus_wd; } #else /* CONFIG_OF */ +static int dw_mci_of_get_slot_quirks(struct device *dev, u8 slot) +{ + return 0; +} static u32 dw_mci_of_get_bus_wd(struct device *dev, u8 slot
RE: [PATCH v2 1/2] mmc: dw_mmc: exynos: Stop claiming wp-gpio
Yes. pin of write protection is common property. This change is good. I have some suggestion below. Could you check it? On Friday, November 23, 2012, Doug Anderson wrote: The exynos code claimed wp-gpio with devm_gpio_request() but never did anything with it. That meant that anyone using a write protect GPIO would effectively be write protected all the time. A future change will move the wp-gpio support to the core dw_mmc.c file. Now the exynos-specific code won't claim the GPIO but will just set the DW_MCI_QUIRK_NO_WRITE_PROTECT quirk if write protect won't be used. Signed-off-by: Doug Anderson diand...@chromium.org --- Changes in v2: - Nothing new in this patch drivers/mmc/host/dw_mmc-exynos.c | 12 ++-- 1 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/mmc/host/dw_mmc-exynos.c b/drivers/mmc/host/dw_mmc-exynos.c index 4d50da6..58cc03e 100644 --- a/drivers/mmc/host/dw_mmc-exynos.c +++ b/drivers/mmc/host/dw_mmc-exynos.c @@ -175,12 +175,12 @@ static int dw_mci_exynos_setup_bus(struct dw_mci *host, } } - gpio = of_get_named_gpio(slot_np, wp-gpios, 0); - if (gpio_is_valid(gpio)) { - if (devm_gpio_request(host-dev, gpio, dw-mci-wp)) - dev_info(host-dev, gpio [%d] request failed\n, - gpio); - } else { + /* + * If there are no write-protect GPIOs present then we assume no write + * protect. The mci_readl() in dw_mmc.c won't work since it's not + * hooked up on exynos. + */ + if (!of_find_property(slot_np, wp-gpios, NULL)) { dev_info(host-dev, wp gpio not available); host-pdata-quirks |= DW_MCI_QUIRK_NO_WRITE_PROTECT; } All card types need this quirk in case wp-gpio property is empty? I think wp-pin is valid for SD card, not eMMC/SDIO. Of course, I know origin code did it. How about removing whole checking routine? Instead, new definition for this quirk can be added into 'dw_mci_of_quirks'(dw_mmc.c) and dts file. Thanks, Seungwon Jeon -- 1.7.7.3 -- To unsubscribe from this list: send the line unsubscribe linux-samsung-soc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
RE: [PATCH v2 1/2] mmc: dw_mmc: exynos: Stop claiming wp-gpio
Hi Doug, On Thursday, November 29, 2012, Doug Anderson wrote: Seungwon, Thanks for the review. See below for comments. If you'd like me to respin then please let me know. Otherwise I look forward to your ack. On Wed, Nov 28, 2012 at 1:29 AM, Seungwon Jeon tgih@samsung.com wrote: Yes. pin of write protection is common property. This change is good. I have some suggestion below. Could you check it? On Friday, November 23, 2012, Doug Anderson wrote: The exynos code claimed wp-gpio with devm_gpio_request() but never did anything with it. That meant that anyone using a write protect GPIO would effectively be write protected all the time. A future change will move the wp-gpio support to the core dw_mmc.c file. Now the exynos-specific code won't claim the GPIO but will just set the DW_MCI_QUIRK_NO_WRITE_PROTECT quirk if write protect won't be used. Signed-off-by: Doug Anderson diand...@chromium.org --- Changes in v2: - Nothing new in this patch drivers/mmc/host/dw_mmc-exynos.c | 12 ++-- 1 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/mmc/host/dw_mmc-exynos.c b/drivers/mmc/host/dw_mmc-exynos.c index 4d50da6..58cc03e 100644 --- a/drivers/mmc/host/dw_mmc-exynos.c +++ b/drivers/mmc/host/dw_mmc-exynos.c @@ -175,12 +175,12 @@ static int dw_mci_exynos_setup_bus(struct dw_mci *host, } } - gpio = of_get_named_gpio(slot_np, wp-gpios, 0); - if (gpio_is_valid(gpio)) { - if (devm_gpio_request(host-dev, gpio, dw-mci-wp)) - dev_info(host-dev, gpio [%d] request failed\n, - gpio); - } else { + /* + * If there are no write-protect GPIOs present then we assume no write + * protect. The mci_readl() in dw_mmc.c won't work since it's not + * hooked up on exynos. + */ + if (!of_find_property(slot_np, wp-gpios, NULL)) { dev_info(host-dev, wp gpio not available); host-pdata-quirks |= DW_MCI_QUIRK_NO_WRITE_PROTECT; } All card types need this quirk in case wp-gpio property is empty? I think wp-pin is valid for SD card, not eMMC/SDIO. Right. It is only checked right now by the SD code (mmc/core/sd.c). It doesn't particularly hurt to set it the quirk in other cases though and it seems nice not to add special cases. I could imagine someone extending the MMC code at some point to support write protect (via GPIO) for eMMC, so there's even a slight justification for avoiding the special case. Of course, I know origin code did it. How about removing whole checking routine? Instead, new definition for this quirk can be added into 'dw_mci_of_quirks'(dw_mmc.c) and dts file. On _exynos_ all SD cards need this quirk if there is no wp-gpio property. However this is not generally true for all users of dw_mmc. The DesignWare IP Block actually has a write protect input that can be read with mci_readl(slot-host, WRTPRT) but on exynos the DesignWare write protect line isn't exposed on any physical pins. That means that the only possible way to do write protect on exynos is using a GPIO. The above means that on exynos if the GPIO isn't defined we will assume no write protect. On other platforms if the GPIO isn't defined we'll assume that the mci_readl will work and we'll use that. If people would prefer it I can code up an alternate solution that doesn't touch any exynos code but that would introduce a new device tree binding. We could accomplish what's needed for exynos using a property like broken-internal-wp. Please let me know if you'd like me to submit a new patch with this solution or if you like the existing solution. Write protect is additional interface related with SD socket. WP switch appears in SD standard size card. In case EMMC/SDIO spec, there is no mentions about this WP pin. As you mentioned above, that's why 'ger_ro' is called only in sd path(mmc/core/sd.c). So, I meant that we don't need to consider WP pin status about non-SD type. Such as exynos5250, there is no exposed interface from host controller for write protection pin. In that case, if general gpio pin is connected like your board environment, we can define wp-gpio. Otherwise, 'broken-internal-wp' property will be good solution. Please feel free to modify. If you will do, I'll be happy. Thanks, Seungwon Jeon -- 1.7.7.3 -- To unsubscribe from this list: send the line unsubscribe linux-mmc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html -- To unsubscribe from this list: send the line unsubscribe linux-samsung-soc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
RE: [PATCH] ARM: Exynos: Remove unused non-dt support for dwmci controller
On Monday, November 26, 2012, Thomas Abraham thomas.abra...@linaro.org wrote: With device tree support enabled for dwmci controller, the unused non-dt support for dwmci controller can be removed. Signed-off-by: Thomas Abraham thomas.abra...@linaro.org --- arch/arm/mach-exynos/Makefile |1 - arch/arm/mach-exynos/dev-dwmci.c | 75 - arch/arm/mach-exynos/include/mach/dwmci.h | 20 3 files changed, 0 insertions(+), 96 deletions(-) delete mode 100644 arch/arm/mach-exynos/dev-dwmci.c delete mode 100644 arch/arm/mach-exynos/include/mach/dwmci.h Hi Thomas, The following parts are remained. Also, no used code. Could you check it? ./plat-samsung/include/plat/devs.h:126:extern struct platform_device exynos4_device_dwmci; ./Kconfig:111:config EXYNOS4_DEV_DWMCI Thanks, Seungwon Jeon diff --git a/arch/arm/mach-exynos/Makefile b/arch/arm/mach-exynos/Makefile index c12ed6a..b189881 100644 --- a/arch/arm/mach-exynos/Makefile +++ b/arch/arm/mach-exynos/Makefile @@ -50,7 +50,6 @@ obj-$(CONFIG_MACH_EXYNOS5_DT) += mach-exynos5-dt.o obj-y+= dev-uart.o obj-$(CONFIG_ARCH_EXYNOS4) += dev-audio.o obj-$(CONFIG_EXYNOS4_DEV_AHCI) += dev-ahci.o -obj-$(CONFIG_EXYNOS4_DEV_DWMCI) += dev-dwmci.o obj-$(CONFIG_EXYNOS_DEV_DMA) += dma.o obj-$(CONFIG_EXYNOS4_DEV_USB_OHCI) += dev-ohci.o obj-$(CONFIG_EXYNOS_DEV_SYSMMU) += dev-sysmmu.o diff --git a/arch/arm/mach-exynos/dev-dwmci.c b/arch/arm/mach-exynos/dev-dwmci.c deleted file mode 100644 index 7903501..000 --- a/arch/arm/mach-exynos/dev-dwmci.c +++ /dev/null @@ -1,75 +0,0 @@ -/* - * linux/arch/arm/mach-exynos4/dev-dwmci.c - * - * Copyright (c) 2011 Samsung Electronics Co., Ltd. - * http://www.samsung.com - * - * Platform device for Synopsys DesignWare Mobile Storage IP - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#include linux/kernel.h -#include linux/dma-mapping.h -#include linux/platform_device.h -#include linux/interrupt.h -#include linux/ioport.h -#include linux/mmc/dw_mmc.h - -#include plat/devs.h - -#include mach/map.h - -static int exynos4_dwmci_get_bus_wd(u32 slot_id) -{ - return 4; -} - -static int exynos4_dwmci_init(u32 slot_id, irq_handler_t handler, void *data) -{ - return 0; -} - -static struct resource exynos4_dwmci_resource[] = { - [0] = DEFINE_RES_MEM(EXYNOS4_PA_DWMCI, SZ_4K), - [1] = DEFINE_RES_IRQ(EXYNOS4_IRQ_DWMCI), -}; - -static struct dw_mci_board exynos4_dwci_pdata = { - .num_slots = 1, - .quirks = DW_MCI_QUIRK_BROKEN_CARD_DETECTION, - .bus_hz = 80 * 1000 * 1000, - .detect_delay_ms= 200, - .init = exynos4_dwmci_init, - .get_bus_wd = exynos4_dwmci_get_bus_wd, -}; - -static u64 exynos4_dwmci_dmamask = DMA_BIT_MASK(32); - -struct platform_device exynos4_device_dwmci = { - .name = dw_mmc, - .id = -1, - .num_resources = ARRAY_SIZE(exynos4_dwmci_resource), - .resource = exynos4_dwmci_resource, - .dev= { - .dma_mask = exynos4_dwmci_dmamask, - .coherent_dma_mask = DMA_BIT_MASK(32), - .platform_data = exynos4_dwci_pdata, - }, -}; - -void __init exynos4_dwmci_set_platdata(struct dw_mci_board *pd) -{ - struct dw_mci_board *npd; - - npd = s3c_set_platdata(pd, sizeof(struct dw_mci_board), - exynos4_device_dwmci); - - if (!npd-init) - npd-init = exynos4_dwmci_init; - if (!npd-get_bus_wd) - npd-get_bus_wd = exynos4_dwmci_get_bus_wd; -} diff --git a/arch/arm/mach-exynos/include/mach/dwmci.h b/arch/arm/mach-exynos/include/mach/dwmci.h deleted file mode 100644 index 7ce6574..000 --- a/arch/arm/mach-exynos/include/mach/dwmci.h +++ /dev/null @@ -1,20 +0,0 @@ -/* linux/arch/arm/mach-exynos4/include/mach/dwmci.h - * - * Copyright (c) 2011 Samsung Electronics Co., Ltd. - * http://www.samsung.com/ - * - * Synopsys DesignWare Mobile Storage for EXYNOS4210 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef __ASM_ARM_ARCH_DWMCI_H -#define __ASM_ARM_ARCH_DWMCI_H __FILE__ - -#include linux/mmc/dw_mmc.h - -extern void exynos4_dwmci_set_platdata(struct dw_mci_board *pd); - -#endif /* __ASM_ARM_ARCH_DWMCI_H */ -- 1.7.5.4
RE: [PATCH 2/2] mmc: dw_mmc: Handle wp-gpios from device tree
Hi, wp-gpios has been implemented in dw_mmc-exynos.c It can be reused for EXYNOS platform? We need to modify some though. Thanks, Seungwon Jeon On Thursday, November 22, 2012, Doug Anderson diand...@chromium.org wrote: On some SoCs (like exynos5250) you need to use an external GPIO for write protect. Add support for wp-gpios to the core dw_mmc driver since it could be useful across multiple SoCs. With this change I am able to make use of the write protect for the external SD slot on exynos5250-snow. Signed-off-by: Doug Anderson diand...@chromium.org --- drivers/mmc/host/dw_mmc.c | 35 +++ 1 files changed, 35 insertions(+), 0 deletions(-) diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index 5b41348..9c79870 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c @@ -34,6 +34,7 @@ #include linux/regulator/consumer.h #include linux/workqueue.h #include linux/of.h +#include linux/of_gpio.h #include dw_mmc.h @@ -74,6 +75,7 @@ struct idmac_desc { * struct dw_mci_slot - MMC slot state * @mmc: The mmc_host representing this slot. * @host: The MMC controller this slot is using. + * @wp_gpio: If gpio_is_valid() we'll use this to read write protect. * @ctype: Card type for this slot. * @mrq: mmc_request currently being processed or waiting to be * processed, or NULL when the slot is idle. @@ -88,6 +90,8 @@ struct dw_mci_slot { struct mmc_host *mmc; struct dw_mci *host; + int wp_gpio; + u32 ctype; struct mmc_request *mrq; @@ -832,6 +836,8 @@ static int dw_mci_get_ro(struct mmc_host *mmc) read_only = 0; else if (brd-get_ro) read_only = brd-get_ro(slot-id); + else if (gpio_is_valid(slot-wp_gpio)) + read_only = gpio_get_value(slot-wp_gpio); else read_only = mci_readl(slot-host, WRTPRT) (1 slot-id) ? 1 : 0; @@ -1802,6 +1808,29 @@ static u32 dw_mci_of_get_bus_wd(struct device *dev, u8 slot) as 1\n); return bus_wd; } + +/* find the write protect gpio for a given slot; or -1 if none specified */ +static u32 dw_mci_of_get_wp_gpio(struct device *dev, u8 slot) +{ + struct device_node *np = dw_mci_of_find_slot_node(dev, slot); + int gpio; + + if (!np) + return -1; + + gpio = of_get_named_gpio(np, wp-gpios, 0); + + /* Having a missing entry is valid; return silently */ + if (!gpio_is_valid(gpio)) + return -1; + + if (devm_gpio_request(dev, gpio, dw-mci-wp)) { + dev_warn(dev, gpio [%d] request failed\n, gpio); + return -1; + } + + return gpio; +} #else /* CONFIG_OF */ static u32 dw_mci_of_get_bus_wd(struct device *dev, u8 slot) { @@ -1811,6 +1840,10 @@ static struct device_node *dw_mci_of_find_slot_node(struct device *dev, u8 slot) { return NULL; } +static u32 dw_mci_of_get_wp_gpio(struct device *dev, u8 slot) +{ + return -1; +} #endif /* CONFIG_OF */ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id) @@ -1923,6 +1956,8 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id) else clear_bit(DW_MMC_CARD_PRESENT, slot-flags); + slot-wp_gpio = dw_mci_of_get_wp_gpio(host-dev, slot-id); + mmc_add_host(mmc); #if defined(CONFIG_DEBUG_FS) -- 1.7.7.3 -- To unsubscribe from this list: send the line unsubscribe linux-samsung-soc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
RE: [PATCH 2/2] mmc: dw_mmc: Handle wp-gpios from device tree
On Thursday, November 22, 2012, Doug Anderson diand...@chromium.org wrote: On Wed, Nov 21, 2012 at 5:42 PM, Seungwon Jeon tgih@samsung.com wrote: Hi, wp-gpios has been implemented in dw_mmc-exynos.c It can be reused for EXYNOS platform? We need to modify some though. Yup, I've seen that. Patch 1/2 (mmc: dw_mmc: exynos: Stop claiming wp-gpio) addressed that. For some reason I can't find that on LKML.org yet. Strange. :-/ I'll forward it on to you shortly. In any case: I found that the exynos code didn't actually work. It claimed the GPIO but didn't ever look at it. I have the beginnings of the code to implement this properly in the exynos code but I stopped working on it when I decided that other SoCs could also benefit from the code and it fit better in the general dw_mmc driver. If you disagree and would like me to cleanup the version of this patch that's just in the exynos driver and post that, I will. Just let me know. Yes, origin code of dw_mmc-exynos didn't work fine. We need to modify it. Anyway, some problem in mailing? I didn't get 1/2 of patch. In addition, it's not found in any mail-archive. After resolved, I can review. Thanks, Seungwon Jeon Thanks for the review! -Doug -- To unsubscribe from this list: send the line unsubscribe linux-samsung-soc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
RE: [PATCH 3/3] mmc: sdhci-s3c: Add clk_(enable/disable) in runtime suspend/resume
On Thursday, October 18, 2012, Heiko Stübner he...@sntech.de wrote: Hi, Am Donnerstag, 18. Oktober 2012, 04:04:42 schrieb Jaehoon Chung: Sorry, i didn't check this patch with s3c2416. (i didn't have the s3c2416 board.) If you have a problem, i think good that revert this patch for fixing your problem. Also, i will check and share the result. After looking a bit more through the code, I don't think the problem is 2416- specific but seems to be caused by the gpio card-detect code. sdhci_s3c_gpio_card_detect_thread calls sdhci_s3c_notify_change which in turn runs host-card_tasklet that seems to want to read stuff from the card. But this path seems to be missing a runtime-pm wakeup. I'm not yet sure what to add, especially, as tasklet_finish (called on some occasions from tasklet_card) already has a runtime_pm_put call, which would be unpaired in this code path. As there also could be other Samsung platforms affected that use the ext-gpio code, it's probably right to revert it for now. Or you see a easy fix :-) . Hi, I think clock is disabled during bus transaction. I'll send a patch. Could you test it? Thanks. Seungwon Jeon Heiko Best Regards, Jaehoon Chung On 10/17/2012 06:15 PM, Heiko Stübner wrote: Hi, Am Freitag, 14. September 2012, 11:08:51 schrieb Chander Kashyap: Perform clock disable/enable in runtime suspend/resume. Signed-off-by: Chander Kashyap chander.kash...@linaro.org It seems this patch breaks my S3C2416 based machine with 3.7-rc1. I'm not yet sure why, but the only response I get is loop of: mmc0: Timeout waiting for hardware interrupt. mmc0: Internal clock never stabilised. mmc0: Timeout waiting for hardware interrupt. mmc0: Internal clock never stabilised. This only happens on the hsmmc channel using the gpio-based card detect and even prevents the card from beeing fully detected. The other hsmmc channel using a permanent emmc seems to be working fine. And of course, when I revert this patch everything works fine again. I'll investigate further, but it'd be also ok if someone has a fix for this before me :-) . Heiko -- To unsubscribe from this list: send the line unsubscribe linux-mmc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html -- To unsubscribe from this list: send the line unsubscribe linux-mmc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html -- To unsubscribe from this list: send the line unsubscribe linux-samsung-soc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
RE: [PATCH v6 8/9] mmc: dw_mmc: add support for implementation specific callbacks
Monday, September 24, Chris Ball c...@laptop.org Hi, On Thu, Sep 20 2012, Thomas Abraham wrote: In non-Exynos platform, host-drv_data has NULL. Yes, sorry, I missed that. Chris, should I fix this and send the updated patch or shall I send a separate fix patch. A separate fix patch would be good, please. (I'd normally take an updated patch but Stephen Rothwell's asked for people to hold off rebasing now that -rc7 is out, which is reasonable.) Thomas, Is there any work for fix? Thanks, Seungwon Jeon Thanks, - Chris. -- Chris Ball c...@laptop.org http://printf.net/ One Laptop Per Child -- To unsubscribe from this list: send the line unsubscribe linux-mmc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html -- To unsubscribe from this list: send the line unsubscribe linux-samsung-soc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
RE: [PATCH v6 9/9] mmc: dw_mmc: add support for exynos specific implementation of dw-mshc
On Thursday, September 20, 2012, Thomas Abraham thomas.abra...@linaro.org wrote: On 19 September 2012 19:12, Seungwon Jeon tgih@samsung.com wrote: On Tuesday, September 18, 2012, Thomas Abraham thomas.abra...@linaro.org wrote: +int dw_mci_exynos_probe(struct platform_device *pdev) +{ + struct dw_mci_drv_data *drv_data; + const struct of_device_id *match; + + match = of_match_node(dw_mci_exynos_match, pdev-dev.of_node); + drv_data = match-data; In non-dt case, match has NULL. Needed to check pdev-dev.of_node Since all current users in mainline of this driver on Exynos platforms are device tree based, and since Exynos4 and Exynos5 have device tree support, I have mainly been adding device tree support here. Only for non-exynos portions of the code, I have ensured that both dt and legacy modes are supported. Yes. I know, then dw_mmc-exynos.c should have a dependency of CONFIG_OF? It needs to prevent kernel panic at least. Thanks, Seungwon Jeon Thanks, Seungwon Jeon Thanks, Thomas. [...] -- To unsubscribe from this list: send the line unsubscribe linux-mmc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html -- To unsubscribe from this list: send the line unsubscribe linux-samsung-soc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
RE: [PATCH v6 6/9] mmc: dw_mmc: add device tree support
On Thursday, September 20, 2012, Thomas Abraham thomas.abra...@linaro.org wrote: On 19 September 2012 19:09, Seungwon Jeon tgih@samsung.com wrote: On Tuesday, September 18, 2012, Thomas Abraham thomas.abra...@linaro.org wrote: +#ifdef CONFIG_OF +/* given a slot id, find out the device node representing that slot */ +static struct device_node *dw_mci_of_find_slot_node(struct device *dev, u8 slot) +{ + struct device_node *np; + const __be32 *addr; + int len; + + if (!dev || !dev-of_node) + return NULL; + + for_each_child_of_node(dev-of_node, np) { + addr = of_get_property(np, reg, len); + if (!addr || (len sizeof(int))) + continue; + if (be32_to_cpup(addr) == slot) + return np; + } + return NULL; +} + +/* find out bus-width for a given slot */ +static u32 dw_mci_of_get_bus_wd(struct device *dev, u8 slot) +{ + struct device_node *np = dw_mci_of_find_slot_node(dev, slot); + u32 bus_wd = 1; + + if (!np) + return 1; + + if (of_property_read_u32(np, bus-width, bus_wd)) + dev_err(dev, bus-width property not found, assuming width + as 1\n); + return bus_wd; +} +#else /* CONFIG_OF */ +static u32 dw_mci_of_get_bus_wd(struct device *dev, u8 slot) +{ + return 1; +} +static struct device_node *dw_mci_of_find_slot_node(struct device *dev, u8 slot) +{ + return NULL; +} +#endif /* CONFIG_OF */ + static int dw_mci_init_slot(struct dw_mci *host, unsigned int id) { struct mmc_host *mmc; struct dw_mci_slot *slot; + u8 bus_width; mmc = mmc_alloc_host(sizeof(struct dw_mci_slot), host-dev); if (!mmc) @@ -1782,6 +1830,7 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id) slot-id = id; slot-mmc = mmc; slot-host = host; + host-slot[id] = slot; mmc-ops = dw_mci_ops; mmc-f_min = DIV_ROUND_UP(host-bus_hz, 510); @@ -1806,8 +1855,18 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id) mmc-caps2 = host-pdata-caps2; if (host-pdata-get_bus_wd) - if (host-pdata-get_bus_wd(slot-id) = 4) - mmc-caps |= MMC_CAP_4_BIT_DATA; + bus_width = host-pdata-get_bus_wd(slot-id); + else if (host-dev-of_node) + bus_width = dw_mci_of_get_bus_wd(host-dev, slot-id); + else + bus_width = 1; + + switch (bus_width) { + case 8: + mmc-caps |= MMC_CAP_8_BIT_DATA; + case 4: + mmc-caps |= MMC_CAP_4_BIT_DATA; + } if (host-pdata-quirks DW_MCI_QUIRK_HIGHSPEED) mmc-caps |= MMC_CAP_SD_HIGHSPEED | MMC_CAP_MMC_HIGHSPEED; @@ -1852,7 +1911,6 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id) else clear_bit(DW_MMC_CARD_PRESENT, slot-flags); - host-slot[id] = slot; mmc_add_host(mmc); #if defined(CONFIG_DEBUG_FS) @@ -1944,16 +2002,74 @@ static bool mci_wait_reset(struct device *dev, struct dw_mci *host) return false; } The following CONFIG_OF block can be put together in upper CONFIG_OF . The placement of device tree related code is considering the logical structure and flow of the code. So maybe we can just retain the below code here for now. +#ifdef CONFIG_OF +static struct dw_mci_of_quirks { + char *quirk; + int id; +} of_quirks[] = { + { + .quirk = supports-highspeed, + .id = DW_MCI_QUIRK_HIGHSPEED, + }, { + .quirk = broken-cd, + .id = DW_MCI_QUIRK_BROKEN_CARD_DETECTION, + }, +}; + +static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host) +{ + struct dw_mci_board *pdata; + struct device *dev = host-dev; + struct device_node *np = dev-of_node; + int idx; + + pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); + if (!pdata) { + dev_err(dev, could not allocate memory for pdata\n); + return ERR_PTR(-ENOMEM); + } + + /* find out number of slots supported */ + if (of_property_read_u32(dev-of_node, num-slots, + pdata-num_slots)) { + dev_info(dev, num-slots property not found, + assuming 1 slot is available\n); + pdata-num_slots = 1; + } + + /* get quirks */ + for (idx = 0; idx ARRAY_SIZE(of_quirks); idx++) + if (of_get_property(np, of_quirks[idx].quirk, NULL)) + pdata-quirks |= of_quirks[idx].id; + + if (of_property_read_u32(np, fifo-depth, pdata-fifo_depth)) + dev_info(dev, fifo-depth
RE: [PATCH v5 9/9] mmc: dw_mmc: add support for exynos specific implementation of dw-mshc
On Friday, September 07, 2012, Thomas Abraham thomas.abra...@linaro.org wrote: Hi Seungwon, Thanks for reviewing the patch. On 5 September 2012 16:13, Seungwon Jeon tgih@samsung.com wrote: On Wednesday, September 05, 2012, Thomas Abraham thomas.abra...@linaro.org wrote: Version 6 is right? Samsung Exynos SoC's extend the dw-mshc controller for additional clock and bus control. Add support for these extensions and include provide device tree based discovery suppory as well. Signed-off-by: Thomas Abraham thomas.abra...@linaro.org Acked-by: Will Newton will.new...@imgtec.com --- .../devicetree/bindings/mmc/exynos-dw-mshc.txt | 86 +++ drivers/mmc/host/Kconfig |9 + drivers/mmc/host/Makefile |1 + drivers/mmc/host/dw_mmc-exynos.c | 253 4 files changed, 349 insertions(+), 0 deletions(-) create mode 100644 Documentation/devicetree/bindings/mmc/exynos-dw-mshc.txt create mode 100644 drivers/mmc/host/dw_mmc-exynos.c diff --git a/Documentation/devicetree/bindings/mmc/exynos-dw-mshc.txt b/Documentation/devicetree/bindings/mmc/exynos-dw-mshc.txt new file mode 100644 index 000..323a891 --- /dev/null +++ b/Documentation/devicetree/bindings/mmc/exynos-dw-mshc.txt @@ -0,0 +1,86 @@ +* Samsung Exynos specific extensions to the Synopsis Designware Mobile + Storage Host Controller + +The Synopsis designware mobile storage host controller is used to interface +a SoC with storage medium such as eMMC or SD/MMC cards. This file documents +differences between the core Synopsis dw mshc controller properties described +by synposis-dw-mshc.txt and the properties used by the Samsung Exynos specific +extensions to the Synopsis Designware Mobile Storage Host Controller. + +Required Properties: + +* compatible: should be + - samsung,exynos4210-dw-mshc: for controllers with Samsung Exynos4210 + specific extentions. + - samsung,exynos4412-dw-mshc: for controllers with Samsung Exynos4412 + specific extentions. + - samsung,exynos5250-dw-mshc: for controllers with Samsung Exynos5250 + specific extentions. + +* samsung,dw-mshc-ciu-div: Specifies the divider value for the card interface + unit (ciu) clock. This property is applicable only for Exynos5 SoC's and + ignored for Exynos4 SoC's. The valid range of divider value is 0 to 7. + +* samsung,dw-mshc-sdr-timing: Specifies the value of CIU clock phase shift value + in transmit mode and CIU clock phase shift value in receive mode for single + data rate mode operation. Refer notes below for the order of the cells and the + valid values. + +* samsung,dw-mshc-ddr-timing: Specifies the value of CUI clock phase shift value + in transmit mode and CIU clock phase shift value in receive mode for double + data rate mode operation. Refer notes below for the order of the cells and the + valid values. + + Notes for the sdr-timing and ddr-timing values: + +The order of the cells should be + - First Cell: CIU clock phase shift value for tx mode. + - Second Cell: CIU clock phase shift value for rx mode. + +Valid values for SDR and DDR CIU clock timing for Exynos5250: + - valid value for tx phase shift and rx phase shift is 0 to 7. + - when CIU clock divider value is set to 3, all possible 8 phase shift +values can be used. + - if CIU clock divider value is 0 (that is divide by 1), both tx and rx +phase shift clocks should be 0. + +Required properties for a slot: + +* gpios: specifies a list of gpios used for command, clock and data bus. The + first gpio is the command line and the second gpio is the clock line. The + rest of the gpios (depending on the bus-width property) are the data lines in + no particular order. The format of the gpio specifier depends on the gpio + controller. + +Example: + + The MSHC controller node can be split into two portions, SoC specific and + board specific portions as listed below. + + dwmmc0@1220 { + compatible = samsung,exynos5250-dw-mshc; + reg = 0x1220 0x1000; + interrupts = 0 75 0; + #address-cells = 1; + #size-cells = 0; + }; + + dwmmc0@1220 { + num-slots = 1; + supports-highspeed; + broken-cd; + fifo-depth = 0x80; + card-detect-delay = 200; + samsung,dw-mshc-sdr-timing = 2 3 3; + samsung,dw-mshc-ddr-timing = 1 2 3; Third filed is still useful? No, it is not used anymore. Thanks for pointing this out. + + slot@0 { + reg = 0; + bus-width = 8
RE: [PATCH v5 9/9] mmc: dw_mmc: add support for exynos specific implementation of dw-mshc
) + host-bus_hz /= EXYNOS4210_FIXED_CIU_CLK_DIV; + + return 0; Here, returning is any meaning? There seems to be no error case. +} + +static void dw_mci_exynos_prepare_command(struct dw_mci *host, u32 *cmdr) +{ + /* + * Exynos4412 and Exynos5250 extends the use of CMD register with the + * use of bit 29 (which is reserved on standard MSHC controllers) for + * optionally bypassing the HOLD register for command and data. The + * HOLD register should be bypassed in case there is no phase shift + * applied on CMD/DATA that is sent to the card. + */ + if (SDMMC_CLKSEL_GET_DRV_WD3(mci_readl(host, CLKSEL))) + *cmdr |= SDMMC_CMD_USE_HOLD_REG; +} + +static void dw_mci_exynos_set_ios(struct dw_mci *host, struct mmc_ios *ios) +{ + struct dw_mci_exynos_priv_data *priv = host-priv; + + if (ios-timing == MMC_TIMING_UHS_DDR50) + mci_writel(host, CLKSEL, priv-ddr_timing); + else + mci_writel(host, CLKSEL, priv-sdr_timing); +} + +static int dw_mci_exynos_parse_dt(struct dw_mci *host) +{ + struct dw_mci_exynos_priv_data *priv = host-priv; + struct device_node *np = host-dev-of_node; + u32 timing[3]; u32 timing[2] is enough. Thanks, Seungwon Jeon + u32 div = 0; + int ret; + + of_property_read_u32(np, samsung,dw-mshc-ciu-div, div); + priv-ciu_div = div; + + ret = of_property_read_u32_array(np, + samsung,dw-mshc-sdr-timing, timing, 2); + if (ret) + return ret; + + priv-sdr_timing = SDMMC_CLKSEL_TIMING(timing[0], timing[1], div); + + ret = of_property_read_u32_array(np, + samsung,dw-mshc-ddr-timing, timing, 2); + if (ret) + return ret; + + priv-ddr_timing = SDMMC_CLKSEL_TIMING(timing[0], timing[1], div); + return 0; +} + +static int dw_mci_exynos_setup_bus(struct dw_mci *host, + struct device_node *slot_np, u8 bus_width) +{ + int idx, gpio, ret; + + if (!slot_np) + return -EINVAL; + + /* cmd + clock + bus-width pins */ + for (idx = 0; idx NUM_PINS(bus_width); idx++) { + gpio = of_get_gpio(slot_np, idx); + if (!gpio_is_valid(gpio)) { + dev_err(host-dev, invalid gpio: %d\n, gpio); + return -EINVAL; + } + + ret = devm_gpio_request(host-dev, gpio, dw-mci-bus); + if (ret) { + dev_err(host-dev, gpio [%d] request failed\n, gpio); + return -EBUSY; + } + } + + gpio = of_get_named_gpio(slot_np, wp-gpios, 0); + if (gpio_is_valid(gpio)) { + if (devm_gpio_request(host-dev, gpio, dw-mci-wp)) + dev_info(host-dev, gpio [%d] request failed\n, + gpio); + } else { + dev_info(host-dev, wp gpio not available); + host-pdata-quirks |= DW_MCI_QUIRK_NO_WRITE_PROTECT; + } + + if (host-pdata-quirks DW_MCI_QUIRK_BROKEN_CARD_DETECTION) + return 0; + + gpio = of_get_named_gpio(slot_np, samsung,cd-pinmux-gpio, 0); + if (gpio_is_valid(gpio)) { + if (devm_gpio_request(host-dev, gpio, dw-mci-cd)) + dev_err(host-dev, gpio [%d] request failed\n, gpio); + } else { + dev_info(host-dev, cd gpio not available); + } + + return 0; +} + +/* Exynos5250 controller specific capabilities */ +static unsigned long exynos5250_dwmmc_caps[4] = { + MMC_CAP_UHS_DDR50 | MMC_CAP_1_8V_DDR | + MMC_CAP_8_BIT_DATA | MMC_CAP_CMD23, + MMC_CAP_CMD23, + MMC_CAP_CMD23, + MMC_CAP_CMD23, +}; + +static struct dw_mci_drv_data exynos5250_drv_data = { + .caps = exynos5250_dwmmc_caps, + .init = dw_mci_exynos_priv_init, + .setup_clock= dw_mci_exynos_setup_clock, + .prepare_command= dw_mci_exynos_prepare_command, + .set_ios= dw_mci_exynos_set_ios, + .parse_dt = dw_mci_exynos_parse_dt, + .setup_bus = dw_mci_exynos_setup_bus, +}; + +static const struct of_device_id dw_mci_exynos_match[] = { + { .compatible = samsung,exynos5250-dw-mshc, + .data = (void *)exynos5250_drv_data, }, + {}, +}; +MODULE_DEVICE_TABLE(of, dw_mci_pltfm_match); + +int dw_mci_exynos_probe(struct platform_device *pdev) +{ + struct dw_mci_drv_data *drv_data; + const struct of_device_id *match; + + match = of_match_node(dw_mci_exynos_match, pdev-dev.of_node); + drv_data = match-data; + return dw_mci_pltfm_register(pdev, drv_data); +} + +static struct platform_driver dw_mci_exynos_pltfm_driver = { + .probe = dw_mci_exynos_probe, + .remove = __exit_p(dw_mci_pltfm_remove
RE: [PATCH v4 3/3] ARM: dts: Add nodes for dw_mmc controllers for Samsung Exynos5250 platforms
On Wednesday, September 05, 2012, Thomas Abraham thomas.abra...@linaro.org wrote: Add device nodes for the four instances of dw_mmc controllers in Exynos5250 and enable instance 0 and 2 for the smdk5250 board. Signed-off-by: Thomas Abraham thomas.abra...@linaro.org --- arch/arm/boot/dts/exynos5250-smdk5250.dts | 57 + arch/arm/boot/dts/exynos5250.dtsi | 32 2 files changed, 89 insertions(+), 0 deletions(-) diff --git a/arch/arm/boot/dts/exynos5250-smdk5250.dts b/arch/arm/boot/dts/exynos5250-smdk5250.dts index 8a5e348..ae1cffe 100644 --- a/arch/arm/boot/dts/exynos5250-smdk5250.dts +++ b/arch/arm/boot/dts/exynos5250-smdk5250.dts @@ -16,6 +16,13 @@ model = SAMSUNG SMDK5250 board based on EXYNOS5250; compatible = samsung,smdk5250, samsung,exynos5250; + aliases { + mshc0 = dwmmc_0; + mshc1 = dwmmc_1; + mshc2 = dwmmc_2; + mshc3 = dwmmc_3; + }; + memory { reg = 0x4000 0x8000; }; @@ -72,6 +79,56 @@ status = disabled; }; + dwmmc_0: dwmmc0@1220 { + num-slots = 1; + supports-highspeed; + broken-cd; + fifo-depth = 0x80; + card-detect-delay = 200; + samsung,dw-mshc-ciu-div = 3; + samsung,dw-mshc-sdr-timing = 2 3 3; + samsung,dw-mshc-ddr-timing = 1 2 3; As adding dw-mshc-ciu-div, third field of dw-mshc-ddr-timing can be removed. Thanks, Seungwon Jeon + + slot@0 { + reg = 0; + bus-width = 8; + gpios = gpc0 0 2 0 3, gpc0 1 2 0 3, + gpc1 0 2 3 3, gpc1 1 2 3 3, + gpc1 2 2 3 3, gpc1 3 2 3 3, + gpc0 3 2 3 3, gpc0 4 2 3 3, + gpc0 5 2 3 3, gpc0 6 2 3 3; + }; + }; + + dwmmc_1: dwmmc1@1221 { + status = disabled; + }; + + dwmmc_2: dwmmc2@1222 { + num-slots = 1; + supports-highspeed; + fifo-depth = 0x80; + card-detect-delay = 200; + samsung,dw-mshc-ciu-div = 3; + samsung,dw-mshc-sdr-timing = 2 3 3; + samsung,dw-mshc-ddr-timing = 1 2 3; + + slot@0 { + reg = 0; + bus-width = 4; + samsung,cd-pinmux-gpio = gpc3 2 2 3 3; + gpios = gpc3 0 2 0 3, gpc3 1 2 0 3, + gpc3 3 2 3 3, gpc3 4 2 3 3, + gpc3 5 2 3 3, gpc3 6 2 3 3, + gpc4 3 3 3 3, gpc4 3 3 3 3, + gpc4 5 3 3 3, gpc4 6 3 3 3; + }; + }; + + dwmmc_3: dwmmc3@1223 { + status = disabled; + }; + spi_0: spi@12d2 { status = disabled; }; diff --git a/arch/arm/boot/dts/exynos5250.dtsi b/arch/arm/boot/dts/exynos5250.dtsi index 004aaa8..f69e389 100644 --- a/arch/arm/boot/dts/exynos5250.dtsi +++ b/arch/arm/boot/dts/exynos5250.dtsi @@ -182,6 +182,38 @@ #size-cells = 0; }; + dwmmc0@1220 { + compatible = samsung,exynos5250-dw-mshc; + reg = 0x1220 0x1000; + interrupts = 0 75 0; + #address-cells = 1; + #size-cells = 0; + }; + + dwmmc1@1221 { + compatible = samsung,exynos5250-dw-mshc; + reg = 0x1221 0x1000; + interrupts = 0 76 0; + #address-cells = 1; + #size-cells = 0; + }; + + dwmmc2@1222 { + compatible = samsung,exynos5250-dw-mshc; + reg = 0x1222 0x1000; + interrupts = 0 77 0; + #address-cells = 1; + #size-cells = 0; + }; + + dwmmc3@1223 { + compatible = samsung,exynos5250-dw-mshc; + reg = 0x1223 0x1000; + interrupts = 0 78 0; + #address-cells = 1; + #size-cells = 0; + }; + amba { #address-cells = 1; #size-cells = 1; -- 1.6.6.rc2 -- To unsubscribe from this list: send the line unsubscribe linux-mmc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html -- To unsubscribe from this list: send the line unsubscribe linux-samsung-soc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
RE: [PATCH v4 9/9] mmc: dw_mmc: add support for exynos specific implementation of dw-mshc
-ctrl_type == DW_MCI_TYPE_EXYNOS5250) + drv = SDMMC_CLKSEL_GET_DRV_WD3(mci_readl(host, CLKSEL)); + else + return; + if (drv) + *cmdr |= SDMMC_CMD_USE_HOLD_REG; +} + +static void dw_mci_exynos_set_ios(struct dw_mci *host, struct mmc_ios *ios) +{ + struct dw_mci_exynos_priv_data *priv = host-priv; + + if (ios-timing == MMC_TIMING_UHS_DDR50) + mci_writel(host, CLKSEL, priv-ddr_timing); + else + mci_writel(host, CLKSEL, priv-sdr_timing); + + host-bus_hz = clk_get_rate(host-ciu_clk); + if (priv-ctrl_type == DW_MCI_TYPE_EXYNOS5250) + host-bus_hz /= SDMMC_CLKSEL_GET_DIVRATIO( + mci_readl(host, CLKSEL)); bus_hz should be recalculated for exynoxs4 as well. Could you check the previous mailing? +} + +static int dw_mci_exynos_parse_dt(struct dw_mci *host) +{ + struct dw_mci_exynos_priv_data *priv = host-priv; + u32 timing[3]; + + if (of_property_read_u32_array(host-dev-of_node, + samsung,dw-mshc-sdr-timing, timing, 3)) + priv-sdr_timing = DW_MCI_DEF_SDR_TIMING; + else + priv-sdr_timing = SDMMC_CLKSEL_TIMING(timing[0], + timing[1], timing[2]); + + if (of_property_read_u32_array(host-dev-of_node, + samsung,dw-mshc-ddr-timing, timing, 3)) + priv-ddr_timing = DW_MCI_DEF_DDR_TIMING; + else + priv-ddr_timing = SDMMC_CLKSEL_TIMING(timing[0], + timing[1], timing[2]); + return 0; DW_MCI_DEF_SDR_TIMING and DW_MCI_DEF_DDR_TIMING are board-specific timing values. So, these values can't be used commonly. It has been already discussed. If this property is empty, returning error with message will be fine. Currently just 0 is always returned. Thanks, Seungwon Jeon +} + +static int dw_mci_exynos_setup_bus(struct dw_mci *host, + struct device_node *slot_np, u8 bus_width) +{ + int idx, gpio, ret; + + if (!slot_np) + return -EINVAL; + + /* cmd + clock + bus-width pins */ + for (idx = 0; idx NUM_PINS(bus_width); idx++) { + gpio = of_get_gpio(slot_np, idx); + if (!gpio_is_valid(gpio)) { + dev_err(host-dev, invalid gpio: %d\n, gpio); + return -EINVAL; + } + + ret = devm_gpio_request(host-dev, gpio, dw-mci-bus); + if (ret) { + dev_err(host-dev, gpio [%d] request failed\n, gpio); + return -EBUSY; + } + } + + gpio = of_get_named_gpio(slot_np, wp-gpios, 0); + if (gpio_is_valid(gpio)) { + if (devm_gpio_request(host-dev, gpio, dw-mci-wp)) + dev_info(host-dev, gpio [%d] request failed\n, + gpio); + } else { + dev_info(host-dev, wp gpio not available); + host-pdata-quirks |= DW_MCI_QUIRK_NO_WRITE_PROTECT; + } + + if (host-pdata-quirks DW_MCI_QUIRK_BROKEN_CARD_DETECTION) + return 0; + + gpio = of_get_named_gpio(slot_np, samsung,cd-pinmux-gpio, 0); + if (gpio_is_valid(gpio)) { + if (devm_gpio_request(host-dev, gpio, dw-mci-cd)) + dev_err(host-dev, gpio [%d] request failed\n, gpio); + } else { + dev_info(host-dev, cd gpio not available); + } + + return 0; +} + +/* Exynos5250 controller specific capabilities */ +static unsigned long exynos5250_dwmmc_caps[4] = { + MMC_CAP_UHS_DDR50 | MMC_CAP_1_8V_DDR | + MMC_CAP_8_BIT_DATA | MMC_CAP_CMD23, + MMC_CAP_CMD23, + MMC_CAP_CMD23, + MMC_CAP_CMD23, +}; + +static struct dw_mci_drv_data exynos5250_drv_data = { + .caps = exynos5250_dwmmc_caps, + .init = dw_mci_exynos_priv_init, + .prepare_command= dw_mci_exynos_prepare_command, + .set_ios= dw_mci_exynos_set_ios, + .parse_dt = dw_mci_exynos_parse_dt, + .setup_bus = dw_mci_exynos_setup_bus, +}; + +static const struct of_device_id dw_mci_exynos_match[] = { + { .compatible = samsung,exynos5250-dw-mshc, + .data = (void *)exynos5250_drv_data, }, + {}, +}; +MODULE_DEVICE_TABLE(of, dw_mci_pltfm_match); + +int dw_mci_exynos_probe(struct platform_device *pdev) +{ + struct dw_mci_drv_data *drv_data; + const struct of_device_id *match; + + match = of_match_node(dw_mci_exynos_match, pdev-dev.of_node); + drv_data = match-data; + return dw_mci_pltfm_register(pdev, drv_data); +} + +static struct platform_driver dw_mci_exynos_pltfm_driver = { + .probe = dw_mci_exynos_probe, + .remove = __exit_p(dw_mci_pltfm_remove
RE: [PATCH v4 4/9] mmc: dw_mmc: lookup for optional biu and ciu clocks
On Sunday, August 26, 2012 Thomas Abraham thomas.abra...@linaro.org wrote: Some platforms allow for clock gating and control of bus interface unit clock and card interface unit clock. Add support for clock lookup of optional biu and ciu clocks for clock gating and clock speed determination. Signed-off-by: Abhilash Kesavan a.kesa...@samsung.com Signed-off-by: Thomas Abraham thomas.abra...@linaro.org --- drivers/mmc/host/dw_mmc.c | 42 +++--- include/linux/mmc/dw_mmc.h |4 2 files changed, 43 insertions(+), 3 deletions(-) diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index cd58063..679473c 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c @@ -1953,18 +1953,38 @@ int dw_mci_probe(struct dw_mci *host) return -ENODEV; } - if (!host-pdata-bus_hz) { + host-biu_clk = clk_get(host-dev, biu); + if (IS_ERR(host-biu_clk)) + dev_dbg(host-dev, biu clock not available\n); + else + clk_prepare_enable(host-biu_clk); + + host-ciu_clk = clk_get(host-dev, ciu); + if (IS_ERR(host-ciu_clk)) + dev_dbg(host-dev, ciu clock not available\n); + else + clk_prepare_enable(host-ciu_clk); + + if (IS_ERR(host-ciu_clk)) + host-bus_hz = host-pdata-bus_hz; + else + host-bus_hz = clk_get_rate(host-ciu_clk); I have remained comment in [PATCH 3/9] mmc: dw_mmc: lookup for optional biu and ciu clocks Could I get your opinion? Thanks, Seungwon Jeon + + if (!host-bus_hz) { dev_err(host-dev, Platform data must supply bus speed\n); - return -ENODEV; + ret = -ENODEV; + goto err_clk; } - host-bus_hz = host-pdata-bus_hz; host-quirks = host-pdata-quirks; spin_lock_init(host-lock); INIT_LIST_HEAD(host-queue); + host-dma_ops = host-pdata-dma_ops; + dw_mci_init_dma(host); + /* * Get the host data width - this assumes that HCON has been set with * the correct values. @@ -2109,6 +2129,16 @@ err_dmaunmap: regulator_disable(host-vmmc); regulator_put(host-vmmc); } + +err_clk: + if (!IS_ERR(host-ciu_clk)) { + clk_disable_unprepare(host-ciu_clk); + clk_put(host-ciu_clk); + } + if (!IS_ERR(host-biu_clk)) { + clk_disable_unprepare(host-biu_clk); + clk_put(host-biu_clk); + } return ret; } EXPORT_SYMBOL(dw_mci_probe); @@ -2142,6 +2172,12 @@ void dw_mci_remove(struct dw_mci *host) regulator_put(host-vmmc); } + if (!IS_ERR(host-ciu_clk)) + clk_disable_unprepare(host-ciu_clk); + if (!IS_ERR(host-biu_clk)) + clk_disable_unprepare(host-biu_clk); + clk_put(host-ciu_clk); + clk_put(host-biu_clk); } EXPORT_SYMBOL(dw_mci_remove); diff --git a/include/linux/mmc/dw_mmc.h b/include/linux/mmc/dw_mmc.h index a37a573..787ad56 100644 --- a/include/linux/mmc/dw_mmc.h +++ b/include/linux/mmc/dw_mmc.h @@ -78,6 +78,8 @@ struct mmc_data; * @data_offset: Set the offset of DATA register according to VERID. * @dev: Device associated with the MMC controller. * @pdata: Platform data associated with the MMC controller. + * @biu_clk: Pointer to bus interface unit clock instance. + * @ciu_clk: Pointer to card interface unit clock instance. * @slot: Slots sharing this MMC controller. * @fifo_depth: depth of FIFO. * @data_shift: log2 of FIFO item size. @@ -158,6 +160,8 @@ struct dw_mci { u16 data_offset; struct device *dev; struct dw_mci_board *pdata; + struct clk *biu_clk; + struct clk *ciu_clk; struct dw_mci_slot *slot[MAX_MCI_SLOTS]; /* FIFO push and pull */ -- 1.6.6.rc2 -- To unsubscribe from this list: send the line unsubscribe linux-samsung-soc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
RE: [PATCH v4 9/9] mmc: dw_mmc: add support for exynos specific implementation of dw-mshc
On Tuesday, August 28, 2012 Thomas Abraham thomas.abra...@linaro.org wrote: Hi Seungwon, On 28 August 2012 12:36, Seungwon Jeon tgih@samsung.com wrote: Hi Thomas, Thank you for your effort. Some reviews seems like to be omitted. Please check more. On Sunday, August 26, 2012 Thomas Abraham thomas.abra...@linaro.org wrote: Samsung Exynos SoC's extend the dw-mshc controller for additional clock and bus control. Add support for these extensions and include provide device tree based discovery suppory as well. [...] +static struct dw_mci_exynos_compatible { + char*compatible; + enum dw_mci_exynos_type ctrl_type; +} exynos_compat[] = { + { + .compatible = samsung,exynos4210-dw-mshc, + .ctrl_type = DW_MCI_TYPE_EXYNOS4210, + }, { + .compatible = samsung,exynos4210-dw-mshc, typo? exynos4412-dw-mshc is expected. Yes, that was a typo. I will fix it. [...] +static void dw_mci_exynos_prepare_command(struct dw_mci *host, u32 *cmdr) +{ + struct dw_mci_exynos_priv_data *priv = host-priv; + u8 drv; + + /* + * Exynos4412 and Exynos5250 extends the use of CMD register with the + * use of bit 29 (which is reserved on standard MSHC controllers) for + * optionally bypassing the HOLD register for command and data. The + * HOLD register should be bypassed in case there is no phase shift + * applied on CMD/DATA that is sent to the card. + */ + if (priv-ctrl_type == DW_MCI_TYPE_EXYNOS4412) + drv = SDMMC_CLKSEL_GET_DRV_WD2(mci_readl(host, CLKSEL)); As it has been mentioned previously, only exynos4210 uses 2-bit. So SDMMC_CLKSEL_GET_DRV_WD3 will be right in exynos4412. In the Exynos4412 user manual that I referred, the SelClk_Drv and SelClk_Sample bit fields of the CLKSEL register are 2 bits wide. Could you please confirm that these two bit-fields are in fact 3 bits wide? I think you are referring old manual. 3-bit is right. I hope you find this. + else if (priv-ctrl_type == DW_MCI_TYPE_EXYNOS5250) + drv = SDMMC_CLKSEL_GET_DRV_WD3(mci_readl(host, CLKSEL)); + else + return; + if (drv) + *cmdr |= SDMMC_CMD_USE_HOLD_REG; +} + +static void dw_mci_exynos_set_ios(struct dw_mci *host, struct mmc_ios *ios) +{ + struct dw_mci_exynos_priv_data *priv = host-priv; + + if (ios-timing == MMC_TIMING_UHS_DDR50) + mci_writel(host, CLKSEL, priv-ddr_timing); + else + mci_writel(host, CLKSEL, priv-sdr_timing); + + host-bus_hz = clk_get_rate(host-ciu_clk); + if (priv-ctrl_type == DW_MCI_TYPE_EXYNOS5250) + host-bus_hz /= SDMMC_CLKSEL_GET_DIVRATIO( + mci_readl(host, CLKSEL)); bus_hz should be recalculated for exynoxs4 as well. Could you check the previous mailing? Exynos4 does not have the additional clock divisor, as in Exynos5250. Could you please explain why the bus_hz clock should be divided in Exynos4? Yes, clock divisor is used in Exynos5250. In case of Exynos4 SoC's, divider value(DIVRATIO) isn't exposed to register. But SDCLKIN is divided by fixed divider value internally. As mentioned previously, divider is used like below. Exynos4210 : 2 Exynos4X12 : 4 +} + +static int dw_mci_exynos_parse_dt(struct dw_mci *host) +{ + struct dw_mci_exynos_priv_data *priv = host-priv; + u32 timing[3]; + + if (of_property_read_u32_array(host-dev-of_node, + samsung,dw-mshc-sdr-timing, timing, 3)) + priv-sdr_timing = DW_MCI_DEF_SDR_TIMING; + else + priv-sdr_timing = SDMMC_CLKSEL_TIMING(timing[0], + timing[1], timing[2]); + + if (of_property_read_u32_array(host-dev-of_node, + samsung,dw-mshc-ddr-timing, timing, 3)) + priv-ddr_timing = DW_MCI_DEF_DDR_TIMING; + else + priv-ddr_timing = SDMMC_CLKSEL_TIMING(timing[0], + timing[1], timing[2]); + return 0; DW_MCI_DEF_SDR_TIMING and DW_MCI_DEF_DDR_TIMING are board-specific timing values. So, these values can't be used commonly. It has been already discussed. If this property is empty, returning error with message will be fine. Currently just 0 is always returned. Yes, you had mentioned this previously. But these are only default values. In case, a board cannot work with these default values, the board's dtsi file should provide the correct values by using these bindings. What is your opinion on this, please let me know. Is there any basis for these value which you chose? If these can be acceptable for the most part, we can consider it for default value. But it depends on host of SOC and target board. Thanks, Seungwon Jeon
RE: [PATCH v3 6/6] mmc: dw_mmc: add samsung exynos5250 specific extentions
July 23, 2012, Thomas Abraham thomas.abra...@linaro.org wrote: On 20 July 2012 16:08, Seungwon Jeon tgih@samsung.com wrote: July 20, 2012, Thomas Abraham thomas.abra...@linaro.org wrote: On 19 July 2012 09:21, Seungwon Jeon tgih@samsung.com wrote: [...] +static unsigned long exynos5250_dwmmc_caps[4] = { + MMC_CAP_UHS_DDR50 | MMC_CAP_1_8V_DDR | + MMC_CAP_8_BIT_DATA | MMC_CAP_CMD23, + MMC_CAP_CMD23, + MMC_CAP_CMD23, + MMC_CAP_CMD23, +}; + Kyungmin Park has already pointed . It's not still proper place for board specific caps. If I'm incorrect, please let me know. And why MMC_CAP_CMD23 is default caps for all channel of hosts? The cap listed above are specifying controller capabilities for dw-mmc controllers on Exynos5 SoC. They are not board specific caps. All the Exynos5 dw-mmc controllers can support MMC_CAP_CMD23 cap and hence, it has been listed for all the controllers. Please let me know if you feel there is any change required here. MMC_CAP_8_BIT_DATA could be dependent on board. A controller can have the MMC_CAP_8_BIT_DATA capability but the board will decide the bus-width. The bus-width is specified in the dts files of each board (or platform data). The bus-width for data transfer is then decided by the MMC core code based on the caps and the bus-width information. So MMC_CAP_8_BIT_DATA can be specified irrespective of whether the board supports 8-bit or not. I agree about MMC_CAP_CMD23. Additionally, MMC_CAP_CMD23 is applied for dw-mmc host driver without regard to Exynos5. The caps listed in exynos5250_dwmmc_caps is applicable only for Exynos5 SoC's. Could you please let me know if there is anything incorrect here. I mean that MMC_CAP_CMD23 is a capability which is implemented in driver without dependency of SOC. So, other soc also includes MMC_CAP_CMD23. It'd rather make a default caps than list in specific soc, considering the other soc. [...] + if (slot-host-drv_data-ctrl_type == DW_MCI_TYPE_EXYNOS5250) { + slot-host-bus_hz = clk_get_rate(slot-host-ciu_clk); + slot-host-bus_hz /= SDMMC_CLKSEL_GET_DIVRATIO( + mci_readl(slot-host, CLKSEL)); + } As you know, CLKSEL is specific for Samsung soc. 0x09C(CLKSEL) is reserved area in Synopsys memory map. In case of non-samsung-soc, we cannot ensure this usage. In previous version, I have suggested separating the variant into another file. There is a check for type of SoC before using 0x9C as CLKSEL register. Do you mean checking DW_MCI_TYPE_EXYNOS5250? But Above two case(ddr_timing/sdr_timing), CLKSEL can be accessed on other soc's. The tests have only been completed on Exynos5250. I do not have boards for other Samsung SoC's which have a dw_mmc port connected and used on the board. When we have other platforms tested with this patchset, we can extend the 'if' check in the above code for other SoC's. My meaning seem to be passed incorrectly. + if (ios-timing == MMC_TIMING_UHS_DDR50) { regs |= (0x1 slot-id) 16; - else + mci_writel(slot-host, CLKSEL, slot-host-ddr_timing); What is the execution for non-samsung soc? CLKSEL register is valid only for Exynos. dw_mci_set_ios shoud be aware of this. + } else { regs = ~(0x1 slot-id) 16; + mci_writel(slot-host, CLKSEL, slot-host-sdr_timing); This line is same. + } + Other implementations of dw-mmc might define custom register at 0x9C Even so, register field can be different with Samsung soc. Yes, with the correct checks for the type of SoC, differences in the usage of 0x9C register can be handled. but this will code will not execute on other SoC's and will not break anything on other implementations. Regarding spliting this Exynos specific code into another file, I prefer not to do it for now. Spliting the code means adding new definitions of callback functions which I am not sure is really required. The present code is fairly simple one. Yes, callback functions might be needed to accommodate various implementation of host controller. It would be better to prepare this for other variant next. Ok. I will relook at these patches and check if we really need split these changes into a separate exynos specific file. If I again feel that such a split is not required, I will reply back to you with justification. [...] + if (of_property_read_u32_array(dev-of_node, + samsung,dw-mshc-sdr-timing, timing, 3)) + host-sdr_timing = DW_MCI_DEF_SDR_TIMING; Host of non-samsung will reach here. host-sdr_timing is needed for this host? host-ddr_timing is the same. Yes, but non-samsung hosts will not have have this property into their dts file. So the code within the condition will not execute
RE: [PATCH V2] mmc: dwmmc: Add quirk for broken Hardware Config
Hi Girish, July 23, 2012, Girish K S girish.shivananja...@linaro.org wrote: In some Soc'S that integrate Designware mmc host controllers, the HCON register is broken. The hardware configuration is not updated. One specific usecase is the IDMAC. In Exysons5 SoC there exist a internal DMA, but the HCON register's DMA_INTERFACE field is not set to indicate its existance. This quirk can be used in such case to force the existance broken HCON field. changes in v2: -moved the implementation to quirk framework as per venkat's review comment. changes in v1: -modified the caps2 field access per controller index.Reported by Jaehoon Chung jh80.ch...@samsung.com. -replaced the pointer to device with the pointer to platform device in struct dw_mci. Change related to adding pointer of platform_device is needed in this patch seriously? I guess that the purpose is to get id of platform_device in case of non-dt. Although a lot of replace is done throughout dw_mmc, actual usage is only in dw_get_platform_device_id. You can split it into another patch if this change is needed, or it's good to use other way. For example, to_platform_device macro is useful to get pointer of platform_device. Best regards, Seungwon Jeon -updated driver data for all 4 mmc controllers of exynos5 SoC. -added non device-tree support for ctrl_id access. Signed-off-by: Girish K S girish.shivananja...@linaro.org --- drivers/mmc/host/dw_mmc-pltfm.c | 10 +++- drivers/mmc/host/dw_mmc.c | 151 --- drivers/mmc/host/dw_mmc.h |1 + include/linux/mmc/dw_mmc.h |4 +- 4 files changed, 107 insertions(+), 59 deletions(-) diff --git a/drivers/mmc/host/dw_mmc-pltfm.c b/drivers/mmc/host/dw_mmc-pltfm.c index 900f412..7d31e90 100644 --- a/drivers/mmc/host/dw_mmc-pltfm.c +++ b/drivers/mmc/host/dw_mmc-pltfm.c @@ -35,9 +35,17 @@ static unsigned long exynos5250_dwmmc_caps[4] = { MMC_CAP_CMD23, }; +static unsigned long exynos5250_dwmmc_quirks[4] = { + DW_MCI_QUIRK_NO_HCON_DMA_INFO, + DW_MCI_QUIRK_NO_HCON_DMA_INFO, + DW_MCI_QUIRK_NO_HCON_DMA_INFO, + DW_MCI_QUIRK_NO_HCON_DMA_INFO, +}; + static struct dw_mci_drv_data exynos5250_drv_data = { .ctrl_type = DW_MCI_TYPE_EXYNOS5250, .caps = exynos5250_dwmmc_caps, + .quirks = exynos5250_dwmmc_quirks, }; static const struct of_device_id dw_mci_pltfm_match[] = { @@ -74,7 +82,7 @@ static int dw_mci_pltfm_probe(struct platform_device *pdev) goto err_free; } - host-dev = pdev-dev; + host-pdev = pdev; host-irq_flags = 0; host-pdata = pdev-dev.platform_data; ret = -ENOMEM; diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index 000da16..b32e200 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c @@ -283,8 +283,10 @@ static u32 dw_mci_prepare_command(struct mmc_host *mmc, struct mmc_command *cmd) static void dw_mci_start_command(struct dw_mci *host, struct mmc_command *cmd, u32 cmd_flags) { + struct device *dev = host-pdev-dev; + host-cmd = cmd; - dev_vdbg(host-dev, + dev_vdbg(dev, start command: ARGR=0x%08x CMDR=0x%08x\n, cmd-arg, cmd_flags); @@ -323,10 +325,11 @@ static int dw_mci_get_dma_dir(struct mmc_data *data) static void dw_mci_dma_cleanup(struct dw_mci *host) { struct mmc_data *data = host-data; + struct device *dev = host-pdev-dev; if (data) if (!data-host_cookie) - dma_unmap_sg(host-dev, + dma_unmap_sg(dev, data-sg, data-sg_len, dw_mci_get_dma_dir(data)); @@ -351,8 +354,9 @@ static void dw_mci_idmac_stop_dma(struct dw_mci *host) static void dw_mci_idmac_complete_dma(struct dw_mci *host) { struct mmc_data *data = host-data; + struct device *dev = host-pdev-dev; - dev_vdbg(host-dev, DMA complete\n); + dev_vdbg(dev, DMA complete\n); host-dma_ops-cleanup(host); @@ -420,10 +424,27 @@ static void dw_mci_idmac_start_dma(struct dw_mci *host, unsigned int sg_len) mci_writel(host, PLDMND, 1); } +static int dw_get_platform_device_id(struct dw_mci *host) +{ + int ctrl_id; + struct device *dev = host-pdev-dev; + + if (dev-of_node) + ctrl_id = of_alias_get_id(dev-of_node, mshc); + else + ctrl_id = host-pdev-id; + + if (ctrl_id 0) + ctrl_id = 0; + + return ctrl_id; +} + static int dw_mci_idmac_init(struct dw_mci *host) { struct idmac_desc *p; int i, dma_support; + struct device *dev = host-pdev-dev; /* Number of descriptors in the ring buffer */ host-ring_size
RE: [PATCH 3/9] mmc: dw_mmc: lookup for optional biu and ciu clocks
July 17, 2012, Thomas Abraham thomas.abra...@linaro.org wrote: Some platforms allow for clock gating and control of bus interface unit clock and card interface unit clock. Add support for clock lookup of optional biu and ciu clocks for clock gating and clock speed determination. Signed-off-by: Abhilash Kesavan a.kesa...@samsung.com Signed-off-by: Thomas Abraham thomas.abra...@linaro.org --- drivers/mmc/host/dw_mmc.c | 39 --- include/linux/mmc/dw_mmc.h |4 2 files changed, 40 insertions(+), 3 deletions(-) diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index cd58063..ebd22d8 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c @@ -1953,13 +1953,30 @@ int dw_mci_probe(struct dw_mci *host) return -ENODEV; } - if (!host-pdata-bus_hz) { + host-biu_clk = clk_get(host-dev, biu); + if (IS_ERR(host-biu_clk)) + dev_dbg(host-dev, biu clock not available\n); + else + clk_prepare_enable(host-biu_clk); + + host-ciu_clk = clk_get(host-dev, ciu); + if (IS_ERR(host-ciu_clk)) + dev_dbg(host-dev, ciu clock not available\n); + else + clk_prepare_enable(host-ciu_clk); + + if (IS_ERR(host-ciu_clk)) + host-bus_hz = host-pdata-bus_hz; + else + host-bus_hz = clk_get_rate(host-ciu_clk); I have posted similar patch some time back. bus_hz represents input rate for cclk_in of mshc. Host of samsung soc doesn't use input clock from system directly. As you have introduced CLKSEL in your another patch, input clock can be changed prior to cclk_in. For non-samsung host, we don't need to consider this with generic way? Thanks, Seungwon Jeon + + if (!host-bus_hz) { dev_err(host-dev, Platform data must supply bus speed\n); - return -ENODEV; + ret = -ENODEV; + goto err_clk; } - host-bus_hz = host-pdata-bus_hz; host-quirks = host-pdata-quirks; spin_lock_init(host-lock); @@ -2109,6 +2126,16 @@ err_dmaunmap: regulator_disable(host-vmmc); regulator_put(host-vmmc); } + +err_clk: + if (!IS_ERR(host-ciu_clk)) { + clk_disable_unprepare(host-ciu_clk); + clk_put(host-ciu_clk); + } + if (!IS_ERR(host-biu_clk)) { + clk_disable_unprepare(host-biu_clk); + clk_put(host-biu_clk); + } return ret; } EXPORT_SYMBOL(dw_mci_probe); @@ -2142,6 +2169,12 @@ void dw_mci_remove(struct dw_mci *host) regulator_put(host-vmmc); } + if (!IS_ERR(host-ciu_clk)) + clk_disable_unprepare(host-ciu_clk); + if (!IS_ERR(host-biu_clk)) + clk_disable_unprepare(host-biu_clk); + clk_put(host-ciu_clk); + clk_put(host-biu_clk); } EXPORT_SYMBOL(dw_mci_remove); diff --git a/include/linux/mmc/dw_mmc.h b/include/linux/mmc/dw_mmc.h index a37a573..787ad56 100644 --- a/include/linux/mmc/dw_mmc.h +++ b/include/linux/mmc/dw_mmc.h @@ -78,6 +78,8 @@ struct mmc_data; * @data_offset: Set the offset of DATA register according to VERID. * @dev: Device associated with the MMC controller. * @pdata: Platform data associated with the MMC controller. + * @biu_clk: Pointer to bus interface unit clock instance. + * @ciu_clk: Pointer to card interface unit clock instance. * @slot: Slots sharing this MMC controller. * @fifo_depth: depth of FIFO. * @data_shift: log2 of FIFO item size. @@ -158,6 +160,8 @@ struct dw_mci { u16 data_offset; struct device *dev; struct dw_mci_board *pdata; + struct clk *biu_clk; + struct clk *ciu_clk; struct dw_mci_slot *slot[MAX_MCI_SLOTS]; /* FIFO push and pull */ -- 1.6.6.rc2 -- To unsubscribe from this list: send the line unsubscribe linux-mmc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html -- To unsubscribe from this list: send the line unsubscribe linux-samsung-soc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
RE: [PATCH v3 6/6] mmc: dw_mmc: add samsung exynos5250 specific extentions
is the basis for these timing? These values is board-specific. +#define SDMMC_CLKSEL_CCLK_SAMPLE(x) (((x) 3) 0) +#define SDMMC_CLKSEL_CCLK_DRIVE(x) (((x) 3) 16) +#define SDMMC_CLKSEL_CCLK_DIVIDER(x) (((x) 3) 24) If it's for exynos5, it will be 7 not 3. +#define SDMMC_CLKSEL_TIMING(x, y, z) (SDMMC_CLKSEL_CCLK_SAMPLE(x) | \ + SDMMC_CLKSEL_CCLK_DRIVE(y) |\ + SDMMC_CLKSEL_CCLK_DIVIDER(z)) +#define SDMMC_CLKSEL_GET_DIVRATIO(x) x) 24) 0x7) + 1) +#define SDMMC_CLKSEL_GET_SELCLK_DRV(x) (((x) 16) 0x7) + Is this patch considered only for exynos5250? In case of exynos4210, the number of bits is different. If upper macros is backward-compatible, it would be better. Best regards, Seungwon Jeon /* Register access macros */ #define mci_readl(dev, reg) \ __raw_readl((dev)-regs + SDMMC_##reg) @@ -184,6 +197,7 @@ extern int dw_mci_resume(struct dw_mci *host); /* Variations in the dw_mci controller */ #define DW_MCI_TYPE_SYNOPSIS 0 +#define DW_MCI_TYPE_EXYNOS5250 1 /* Samsung Exynos5250 Extensions */ /* dw_mci platform driver data */ struct dw_mci_drv_data { diff --git a/include/linux/mmc/dw_mmc.h b/include/linux/mmc/dw_mmc.h index ae45e4f..32c778f 100644 --- a/include/linux/mmc/dw_mmc.h +++ b/include/linux/mmc/dw_mmc.h @@ -82,6 +82,8 @@ struct mmc_data; * @biu_clk: Pointer to bus interface unit clock instance. * @ciu_clk: Pointer to card interface unit clock instance. * @slot: Slots sharing this MMC controller. + * @sdr_timing: Clock phase shifting for driving and sampling in sdr mode + * @ddr_timing: Clock phase shifting for driving and sampling in ddr mode * @fifo_depth: depth of FIFO. * @data_shift: log2 of FIFO item size. * @part_buf_start: Start index in part_buf. @@ -166,6 +168,10 @@ struct dw_mci { struct clk *ciu_clk; struct dw_mci_slot *slot[MAX_MCI_SLOTS]; + /* Phase Shift Value (for exynos5250 variant) */ + u32 sdr_timing; + u32 ddr_timing; + /* FIFO push and pull */ int fifo_depth; int data_shift; -- 1.6.6.rc2 -- To unsubscribe from this list: send the line unsubscribe linux-mmc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html -- To unsubscribe from this list: send the line unsubscribe linux-samsung-soc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
RE: [PATCH v2 6/6] mmc: dw_mmc: add samsung exynos5250 specific extentions
Hi Thomas Abraham, How about separating the variant for Samsung Exynos. Like dw_mmc-exynos.c Thanks, Seungwon Jeon. Thomas Abraham wrote: The instantiation of the Synopsis Designware controller on Exynos5250 include extension for SDR and DDR specific tx/rx phase shift timing and CIU internal divider. In addition to that, the option to skip the command hold stage is also introduced. Add support for these Exynos5250 specfic extenstions. Signed-off-by: Abhilash Kesavan a.kesa...@samsung.com Signed-off-by: Thomas Abraham thomas.abra...@linaro.org --- .../devicetree/bindings/mmc/synposis-dw-mshc.txt | 33 - drivers/mmc/host/dw_mmc-pltfm.c| 15 +++ drivers/mmc/host/dw_mmc.c | 40 +++- drivers/mmc/host/dw_mmc.h | 14 +++ include/linux/mmc/dw_mmc.h |6 +++ 5 files changed, 105 insertions(+), 3 deletions(-) diff --git a/Documentation/devicetree/bindings/mmc/synposis-dw-mshc.txt b/Documentation/devicetree/bindings/mmc/synposis-dw-mshc.txt index 3acd6c9..99b166e 100644 --- a/Documentation/devicetree/bindings/mmc/synposis-dw-mshc.txt +++ b/Documentation/devicetree/bindings/mmc/synposis-dw-mshc.txt @@ -7,6 +7,8 @@ Required Properties: * compatible: should be one of the following - snps,dw-mshc: for controllers compliant with synopsis dw-mshc. + - samsung,exynos5250-dw-mshc: for controllers with Samsung + Exynos5250 specific extentions. * reg: physical base address of the dw-mshc controller and size of its memory region. @@ -74,13 +76,40 @@ Aliases: the following format 'mshc{n}' where n is a unique number for the alias. +Samsung Exynos5250 specific properties: + +* samsung,dw-mshc-sdr-timing: Specifies the value of CUI clock divider, CIU + clock phase shift value in transmit mode and CIU clock phase shift value in + receive mode for single data rate mode operation. Refer notes of the valid + values below. + +* samsung,dw-mshc-ddr-timing: Specifies the value of CUI clock divider, CIU + clock phase shift value in transmit mode and CIU clock phase shift value in + receive mode for double data rate mode operation. Refer notes of the valid + values below. The order of the cells should be + +- First Cell:CIU clock divider value. +- Second Cell: CIU clock phase shift value for tx mode. +- Third Cell:CIU clock phase shift value for rx mode. + + Valid values for SDR and DDR CIU clock timing: + +- valid values for CIU clock divider, tx phase shift and rx phase shift + is 0 to 7. + +- When CIU clock divider value is set to 3, all possible 8 phase shift + values can be used. + +- If CIU clock divider value is 0 (that is divide by 1), both tx and rx + phase shift clocks should be 0. + Example: The MSHC controller node can be split into two portions, SoC specific and board specific portions as listed below. dwmmc0@1220 { - compatible = snps,dw-mshc; + compatible = samsung,exynos5250-dw-mshc; reg = 0x1220 0x1000; interrupts = 0 75 0; #address-cells = 1; @@ -94,6 +123,8 @@ Example: no-write-protect; fifo-depth = 0x80; card-detect-delay = 200; + samsung,dw-mshc-sdr-timing = 2 3 3; + samsung,dw-mshc-ddr-timing = 1 2 3; slot@0 { reg = 0; diff --git a/drivers/mmc/host/dw_mmc-pltfm.c b/drivers/mmc/host/dw_mmc-pltfm.c index 8d24f6d..900f412 100644 --- a/drivers/mmc/host/dw_mmc-pltfm.c +++ b/drivers/mmc/host/dw_mmc-pltfm.c @@ -27,9 +27,24 @@ static struct dw_mci_drv_data synopsis_drv_data = { .ctrl_type = DW_MCI_TYPE_SYNOPSIS, }; +static unsigned long exynos5250_dwmmc_caps[4] = { + MMC_CAP_UHS_DDR50 | MMC_CAP_1_8V_DDR | + MMC_CAP_8_BIT_DATA | MMC_CAP_CMD23, + MMC_CAP_CMD23, + MMC_CAP_CMD23, + MMC_CAP_CMD23, +}; + +static struct dw_mci_drv_data exynos5250_drv_data = { + .ctrl_type = DW_MCI_TYPE_EXYNOS5250, + .caps = exynos5250_dwmmc_caps, +}; + static const struct of_device_id dw_mci_pltfm_match[] = { { .compatible = snps,dw-mshc, .data = (void *)synopsis_drv_data, }, + { .compatible = samsung,exynos5250-dw-mshc, + .data = (void *)exynos5250_drv_data, }, {}, }; MODULE_DEVICE_TABLE(of, dw_mci_pltfm_match); diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index 0317287..58bab5b 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c @@ -236,6 +236,7 @@ static void dw_mci_set_timeout(struct dw_mci *host) static u32 dw_mci_prepare_command(struct mmc_host *mmc, struct mmc_command *cmd) { struct mmc_data *data; + struct dw_mci_slot *slot
RE: [PATCH v2 1/4] mmc: sdhci-s3c: use the sdhci-pltfm for Samsung-SoC
Jaehoon Chung jh80.ch...@samsung.com wrote: On 02/29/2012 03:33 PM, Seungwon Jeon wrote: Hi Jaehoon, Thank you for the patch. Could you check comments below? Jaehoon Chung jh80.ch...@samsung.com wrote: This patch is change to use the sdhci-pltfm.c Signed-off-by: Jaehoon Chung jh80.ch...@samsung.com Signed-off-by: Kyungmin Park kyungmin.p...@samsung.com --- drivers/mmc/host/Kconfig | 20 ++-- drivers/mmc/host/sdhci-s3c.c | 254 ++ 2 files changed, 95 insertions(+), 179 deletions(-) diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig index 0c9b3b1..21ea0ba 100644 --- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig @@ -169,6 +169,8 @@ config MMC_SDHCI_TEGRA config MMC_SDHCI_S3C tristate SDHCI support on Samsung S3C SoC depends on MMC_SDHCI PLAT_SAMSUNG + depends on MMC_SDHCI_PLTFM + select MMC_SDHCI_IO_ACCESSORS help This selects the Secure Digital Host Controller Interface (SDHCI) often referrered to as the HSMMC block in some of the Samsung S3C @@ -181,6 +183,14 @@ config MMC_SDHCI_S3C If unsure, say N. +config MMC_SDHCI_S3C_DMA + bool DMA support on S3C SDHCI + depends on MMC_SDHCI_S3C EXPERIMENTAL + help +Enable DMA support on the Samsung S3C SDHCI glue. The DMA +has proved to be problematic if the controller encounters +certain errors, and thus should be treated with care. + config MMC_SDHCI_PXAV3 tristate Marvell MMP2 SD Host Controller support (PXAV3) depends on CLKDEV_LOOKUP @@ -219,16 +229,6 @@ config MMC_SDHCI_SPEAR If unsure, say N. -config MMC_SDHCI_S3C_DMA - bool DMA support on S3C SDHCI - depends on MMC_SDHCI_S3C EXPERIMENTAL - help -Enable DMA support on the Samsung S3C SDHCI glue. The DMA -has proved to be problematic if the controller encounters -certain errors, and thus should be treated with care. - -YMMV. - config MMC_OMAP tristate TI OMAP Multimedia Card Interface support depends on ARCH_OMAP diff --git a/drivers/mmc/host/sdhci-s3c.c b/drivers/mmc/host/sdhci-s3c.c index 3bf509b..0778c38 100644 --- a/drivers/mmc/host/sdhci-s3c.c +++ b/drivers/mmc/host/sdhci-s3c.c @@ -28,6 +28,7 @@ #include plat/sdhci.h #include plat/regs-sdhci.h +#include sdhci-pltfm.h #include sdhci.h #define MAX_BUS_CLK (4) @@ -46,9 +47,7 @@ * @clk_bus: The clocks that are available for the SD/MMC bus clock. */ struct sdhci_s3c { - struct sdhci_host *host; struct platform_device *pdev; - struct resource *ioarea; struct s3c_sdhci_platdata *pdata; unsigned intcur_clk; int ext_cd_irq; @@ -71,11 +70,6 @@ struct sdhci_s3c_drv_data { unsigned intsdhci_quirks; }; -static inline struct sdhci_s3c *to_s3c(struct sdhci_host *host) -{ - return sdhci_priv(host); -} - /** * get_curclk - convert ctrl2 register to clock source number * @ctrl2: Control2 register value. @@ -90,7 +84,8 @@ static u32 get_curclk(u32 ctrl2) static void sdhci_s3c_check_sclk(struct sdhci_host *host) { - struct sdhci_s3c *ourhost = to_s3c(host); + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); + struct sdhci_s3c *ourhost = pltfm_host-priv; u32 tmp = readl(host-ioaddr + S3C_SDHCI_CONTROL2); if (get_curclk(tmp) != ourhost-cur_clk) { @@ -110,7 +105,8 @@ static void sdhci_s3c_check_sclk(struct sdhci_host *host) */ static unsigned int sdhci_s3c_get_max_clk(struct sdhci_host *host) { - struct sdhci_s3c *ourhost = to_s3c(host); + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); + struct sdhci_s3c *ourhost = pltfm_host-priv; struct clk *busclk; unsigned int rate, max; int clk; @@ -138,11 +134,13 @@ static unsigned int sdhci_s3c_get_max_clk(struct sdhci_host *host) * @src: The source clock index. * @wanted: The clock frequency wanted. */ -static unsigned int sdhci_s3c_consider_clock(struct sdhci_s3c *ourhost, +static unsigned int sdhci_s3c_consider_clock(struct sdhci_host *host, unsigned int src, unsigned int wanted) { unsigned long rate; + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); + struct sdhci_s3c *ourhost = pltfm_host-priv; struct clk *clksrc = ourhost-clk_bus[src]; int div; @@ -153,7 +151,7 @@ static unsigned int sdhci_s3c_consider_clock(struct sdhci_s3c *ourhost, * If controller uses a non-standard clock division, find the best clock * speed possible with selected clock source and skip the division. */ - if (ourhost-host-quirks SDHCI_QUIRK_NONSTANDARD_CLOCK) { + if (host-quirks SDHCI_QUIRK_NONSTANDARD_CLOCK) { rate = clk_round_rate(clksrc, wanted
RE: [PATCH v2 1/4] mmc: sdhci-s3c: use the sdhci-pltfm for Samsung-SoC
Jaehoon Chung jh80.ch...@samsung.com wrote: On 03/02/2012 11:15 AM, Seungwon Jeon wrote: Jaehoon Chung jh80.ch...@samsung.com wrote: On 02/29/2012 03:33 PM, Seungwon Jeon wrote: Hi Jaehoon, Thank you for the patch. Could you check comments below? Jaehoon Chung jh80.ch...@samsung.com wrote: This patch is change to use the sdhci-pltfm.c Signed-off-by: Jaehoon Chung jh80.ch...@samsung.com Signed-off-by: Kyungmin Park kyungmin.p...@samsung.com --- drivers/mmc/host/Kconfig | 20 ++-- drivers/mmc/host/sdhci-s3c.c | 254 ++ 2 files changed, 95 insertions(+), 179 deletions(-) diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig index 0c9b3b1..21ea0ba 100644 --- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig @@ -169,6 +169,8 @@ config MMC_SDHCI_TEGRA config MMC_SDHCI_S3C tristate SDHCI support on Samsung S3C SoC depends on MMC_SDHCI PLAT_SAMSUNG +depends on MMC_SDHCI_PLTFM +select MMC_SDHCI_IO_ACCESSORS help This selects the Secure Digital Host Controller Interface (SDHCI) often referrered to as the HSMMC block in some of the Samsung S3C @@ -181,6 +183,14 @@ config MMC_SDHCI_S3C If unsure, say N. +config MMC_SDHCI_S3C_DMA +bool DMA support on S3C SDHCI +depends on MMC_SDHCI_S3C EXPERIMENTAL +help + Enable DMA support on the Samsung S3C SDHCI glue. The DMA + has proved to be problematic if the controller encounters + certain errors, and thus should be treated with care. + config MMC_SDHCI_PXAV3 tristate Marvell MMP2 SD Host Controller support (PXAV3) depends on CLKDEV_LOOKUP @@ -219,16 +229,6 @@ config MMC_SDHCI_SPEAR If unsure, say N. -config MMC_SDHCI_S3C_DMA -bool DMA support on S3C SDHCI -depends on MMC_SDHCI_S3C EXPERIMENTAL -help - Enable DMA support on the Samsung S3C SDHCI glue. The DMA - has proved to be problematic if the controller encounters - certain errors, and thus should be treated with care. - - YMMV. - config MMC_OMAP tristate TI OMAP Multimedia Card Interface support depends on ARCH_OMAP diff --git a/drivers/mmc/host/sdhci-s3c.c b/drivers/mmc/host/sdhci-s3c.c index 3bf509b..0778c38 100644 --- a/drivers/mmc/host/sdhci-s3c.c +++ b/drivers/mmc/host/sdhci-s3c.c @@ -28,6 +28,7 @@ #include plat/sdhci.h #include plat/regs-sdhci.h +#include sdhci-pltfm.h #include sdhci.h #define MAX_BUS_CLK (4) @@ -46,9 +47,7 @@ * @clk_bus: The clocks that are available for the SD/MMC bus clock. */ struct sdhci_s3c { -struct sdhci_host *host; struct platform_device *pdev; -struct resource *ioarea; struct s3c_sdhci_platdata *pdata; unsigned intcur_clk; int ext_cd_irq; @@ -71,11 +70,6 @@ struct sdhci_s3c_drv_data { unsigned intsdhci_quirks; }; -static inline struct sdhci_s3c *to_s3c(struct sdhci_host *host) -{ -return sdhci_priv(host); -} - /** * get_curclk - convert ctrl2 register to clock source number * @ctrl2: Control2 register value. @@ -90,7 +84,8 @@ static u32 get_curclk(u32 ctrl2) static void sdhci_s3c_check_sclk(struct sdhci_host *host) { -struct sdhci_s3c *ourhost = to_s3c(host); +struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); +struct sdhci_s3c *ourhost = pltfm_host-priv; u32 tmp = readl(host-ioaddr + S3C_SDHCI_CONTROL2); if (get_curclk(tmp) != ourhost-cur_clk) { @@ -110,7 +105,8 @@ static void sdhci_s3c_check_sclk(struct sdhci_host *host) */ static unsigned int sdhci_s3c_get_max_clk(struct sdhci_host *host) { -struct sdhci_s3c *ourhost = to_s3c(host); +struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); +struct sdhci_s3c *ourhost = pltfm_host-priv; struct clk *busclk; unsigned int rate, max; int clk; @@ -138,11 +134,13 @@ static unsigned int sdhci_s3c_get_max_clk(struct sdhci_host *host) * @src: The source clock index. * @wanted: The clock frequency wanted. */ -static unsigned int sdhci_s3c_consider_clock(struct sdhci_s3c *ourhost, +static unsigned int sdhci_s3c_consider_clock(struct sdhci_host *host, unsigned int src, unsigned int wanted) { unsigned long rate; +struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); +struct sdhci_s3c *ourhost = pltfm_host-priv; struct clk *clksrc = ourhost-clk_bus[src]; int div; @@ -153,7 +151,7 @@ static
RE: [PATCH v2 1/4] mmc: sdhci-s3c: use the sdhci-pltfm for Samsung-SoC
(pdev, 0); - if (irq 0) { - dev_err(dev, no irq specified\n); - return irq; - } - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - dev_err(dev, no memory specified\n); - return -ENOENT; - } - - host = sdhci_alloc_host(dev, sizeof(struct sdhci_s3c)); + host = sdhci_pltfm_init(pdev, pltfm_pdata); if (IS_ERR(host)) { dev_err(dev, sdhci_alloc_host() failed\n); return PTR_ERR(host); } - sc = sdhci_priv(host); - pdata = devm_kzalloc(pdev-dev, sizeof(*pdata), GFP_KERNEL); - if (!pdata) { + sc = devm_kzalloc(dev, sizeof(struct sdhci_s3c), GFP_KERNEL); + if (!sc) { ret = -ENOMEM; - goto err_pdata; + goto err_alloc_host; } + pltfm_host = sdhci_priv(host); + pltfm_host-priv = sc; + if (pdev-dev.of_node) { - ret = sdhci_s3c_parse_dt(pdev-dev, host, pdata); + ret = sdhci_s3c_parse_dt(pdev-dev, host, sc-pdata); if (ret) - goto err_pdata; + goto err_alloc_host; } else { - memcpy(pdata, pdev-dev.platform_data, sizeof(*pdata)); + memcpy(sc-pdata, pdev-dev.platform_data, sizeof(sc-pdata)); sc-ext_cd_gpio = -1; /* invalid gpio number */ } drv_data = sdhci_s3c_get_driver_data(pdev); + if (drv_data) + host-quirks |= drv_data-sdhci_quirks; - sc-host = host; sc-pdev = pdev; - sc-pdata = pdata; - - platform_set_drvdata(pdev, host); sc-clk_io = clk_get(dev, hsmmc); if (IS_ERR(sc-clk_io)) { @@ -602,9 +599,8 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev) snprintf(name, 14, mmc_busclk.%d, ptr); clk = clk_get(dev, name); - if (IS_ERR(clk)) { + if (IS_ERR(clk)) continue; - } clks++; sc-clk_bus[ptr] = clk; @@ -613,7 +609,10 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev) * save current clock index to know which clock bus * is used later in overriding functions. */ - sc-cur_clk = ptr; + if (host-quirks SDHCI_QUIRK_NONSTANDARD_CLOCK) + pltfm_host-clk = clk; + else We need to keep below? According to two commits, this seems to be relevant to SDHCI_QUIRK_NONSTANDARD_CLOCK. mmc: sdhci-s3c: Support controllers with no internal clock divider(253e0a7c3dc4b) mmc: sdhci-s3c: Remove usage of clk_type member in platform data(b77d777eeb0a086) Thanks, Seungwon Jeon. + sc-cur_clk = ptr; clk_enable(clk); @@ -627,63 +626,25 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev) goto err_no_busclks; } - sc-ioarea = request_mem_region(res-start, resource_size(res), - mmc_hostname(host-mmc)); - if (!sc-ioarea) { - dev_err(dev, failed to reserve register area\n); - ret = -ENXIO; - goto err_req_regs; - } - - host-ioaddr = ioremap_nocache(res-start, resource_size(res)); - if (!host-ioaddr) { - dev_err(dev, failed to map registers\n); - ret = -ENXIO; - goto err_req_regs; - } - /* Ensure we have minimal gpio selected CMD/CLK/Detect */ - if (pdata-cfg_gpio) - pdata-cfg_gpio(pdev, pdata-max_width); - - host-hw_name = samsung-hsmmc; - host-ops = sdhci_s3c_ops; - host-quirks = 0; - host-irq = irq; - - /* Setup quirks for the controller */ - host-quirks |= SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC; - host-quirks |= SDHCI_QUIRK_NO_HISPD_BIT; - if (drv_data) - host-quirks |= drv_data-sdhci_quirks; + if (sc-pdata-cfg_gpio) + sc-pdata-cfg_gpio(pdev, sc-pdata-max_width); #ifndef CONFIG_MMC_SDHCI_S3C_DMA - /* we currently see overruns on errors, so disable the SDMA * support as well. */ host-quirks |= SDHCI_QUIRK_BROKEN_DMA; #endif /* CONFIG_MMC_SDHCI_S3C_DMA */ - /* It seems we do not get an DATA transfer complete on non-busy - * transfers, not sure if this is a problem with this specific - * SDHCI block, or a missing configuration that needs to be set. */ - host-quirks |= SDHCI_QUIRK_NO_BUSY_IRQ; - - /* This host supports the Auto CMD12 */ - host-quirks |= SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12; - - /* Samsung SoCs need BROKEN_ADMA_ZEROLEN_DESC */ - host-quirks |= SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC; - - if (pdata-cd_type == S3C_SDHCI_CD_NONE || - pdata-cd_type == S3C_SDHCI_CD_PERMANENT) + if (sc-pdata-cd_type == S3C_SDHCI_CD_NONE
[PATCH v2 0/2] mmc: core: Fix cache control for eMMC4.5
This patch-set fixed the cache control for eMMC4.5 Changes in v2: - clear the cache_ctrl flag for a failure(enabling cache) Seungwon Jeon (2): mmc: core: Separate the timeout value for cache-ctrl mmc: core: Add claiming a host during mmc_cache_ctrl drivers/mmc/core/core.c | 29 +++-- drivers/mmc/core/mmc.c | 13 +++-- 2 files changed, 30 insertions(+), 12 deletions(-) Best regards, Seungwon Jeon. -- 1.7.2.3 -- To unsubscribe from this list: send the line unsubscribe linux-samsung-soc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 1/2] mmc: core: Separate the timeout value for cache-ctrl
Turning the cache off implies flushing cache which doesn't define maximum timeout unlike cache-on. This patch will apply the generic CMD6 timeout only for cache-on. Additionally the kernel message is added for checking failure case of cache-on. Signed-off-by: Seungwon Jeon tgih@samsung.com --- Changes in v2: - clear the cache_ctrl flag for a failure(enabling cache) drivers/mmc/core/core.c | 21 - drivers/mmc/core/mmc.c | 13 +++-- 2 files changed, 23 insertions(+), 11 deletions(-) diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index a2aa860..b96b5ae 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -2315,6 +2315,7 @@ EXPORT_SYMBOL(mmc_flush_cache); int mmc_cache_ctrl(struct mmc_host *host, u8 enable) { struct mmc_card *card = host-card; + unsigned int timeout; int err = 0; if (!(host-caps2 MMC_CAP2_CACHE_CTRL) || @@ -2325,16 +2326,18 @@ int mmc_cache_ctrl(struct mmc_host *host, u8 enable) (card-ext_csd.cache_size 0)) { enable = !!enable; - if (card-ext_csd.cache_ctrl ^ enable) + if (card-ext_csd.cache_ctrl ^ enable) { + timeout = enable ? card-ext_csd.generic_cmd6_time : 0; err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, - EXT_CSD_CACHE_CTRL, enable, 0); - if (err) - pr_err(%s: cache %s error %d\n, - mmc_hostname(card-host), - enable ? on : off, - err); - else - card-ext_csd.cache_ctrl = enable; + EXT_CSD_CACHE_CTRL, enable, timeout); + if (err) + pr_err(%s: cache %s error %d\n, + mmc_hostname(card-host), + enable ? on : off, + err); + else + card-ext_csd.cache_ctrl = enable; + } } return err; diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index 006e932..71cb810 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c @@ -1077,14 +1077,23 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, if ((host-caps2 MMC_CAP2_CACHE_CTRL) card-ext_csd.cache_size 0) { err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, - EXT_CSD_CACHE_CTRL, 1, 0); + EXT_CSD_CACHE_CTRL, 1, + card-ext_csd.generic_cmd6_time); if (err err != -EBADMSG) goto free_card; /* * Only if no error, cache is turned on successfully. */ - card-ext_csd.cache_ctrl = err ? 0 : 1; + if (err) { + pr_warning(%s: Cache is supported, + but failed to turn on (%d)\n, + mmc_hostname(card-host), err); + card-ext_csd.cache_ctrl = 0; + err = 0; + } else { + card-ext_csd.cache_ctrl = 1; + } } if (!oldcard) -- 1.7.0.4 -- To unsubscribe from this list: send the line unsubscribe linux-samsung-soc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 2/2] mmc: core: Add claiming a host during mmc_cache_ctrl
While calling mmc_cache_ctrl() a host is not claimed. This patch adds the mmc_try_claim_host() for quick response in suspend. Signed-off-by: Seungwon Jeon tgih@samsung.com --- drivers/mmc/core/core.c |8 +++- 1 files changed, 7 insertions(+), 1 deletions(-) diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 83ac6e6..efdbf9d 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -2359,7 +2359,13 @@ int mmc_suspend_host(struct mmc_host *host) cancel_delayed_work(host-disable); cancel_delayed_work(host-detect); mmc_flush_scheduled_work(); - err = mmc_cache_ctrl(host, 0); + if (mmc_try_claim_host(host)) { + err = mmc_cache_ctrl(host, 0); + mmc_do_release_host(host); + } else { + err = -EBUSY; + } + if (err) goto out; -- 1.7.0.4 -- To unsubscribe from this list: send the line unsubscribe linux-samsung-soc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html