From 4b6ea87be44ef34732846fc71e44c41125f0c4fa Mon Sep 17 00:00:00 2001 From: Douglas Anderson Date: Tue, 13 Oct 2020 14:25:28 -0700 Subject: [PATCH 001/102] soc: qcom: geni: More properly switch to DMA mode On geni-i2c transfers using DMA, it was seen that if you program the command (I2C_READ) before calling geni_se_rx_dma_prep() that it could cause interrupts to fire. If we get unlucky, these interrupts can just keep firing (and not be handled) blocking further progress and hanging the system. In commit 02b9aec59243 ("i2c: i2c-qcom-geni: Fix DMA transfer race") we avoided that by making sure we didn't program the command until after geni_se_rx_dma_prep() was called. While that avoided the problems, it also turns out to be invalid. At least in the TX case we started seeing sporadic corrupted transfers. This is easily seen by adding an msleep() between the DMA prep and the writing of the command, which makes the problem worse. That means we need to revert that commit and find another way to fix the bogus IRQs. Specifically, after reverting commit 02b9aec59243 ("i2c: i2c-qcom-geni: Fix DMA transfer race"), I put some traces in. I found that the when the interrupts were firing like crazy: - "m_stat" had bits for M_RX_IRQ_EN, M_RX_FIFO_WATERMARK_EN set. - "dma" was set. Further debugging showed that I could make the problem happen more reliably by adding an "msleep(1)" any time after geni_se_setup_m_cmd() ran up until geni_se_rx_dma_prep() programmed the length. A rather simple fix is to change geni_se_select_dma_mode() so it's a true inverse of geni_se_select_fifo_mode() and disables all the FIFO related interrupts. Now the problematic interrupts can't fire and we can program things in the correct order without worrying. As part of this, let's also change the writel_relaxed() in the prepare function to a writel() so that our DMA is guaranteed to be prepared now that we can't rely on geni_se_setup_m_cmd()'s writel(). NOTE: the only current user of GENI_SE_DMA in mainline is i2c. Fixes: 37692de5d523 ("i2c: i2c-qcom-geni: Add bus driver for the Qualcomm GENI I2C controller") Fixes: 02b9aec59243 ("i2c: i2c-qcom-geni: Fix DMA transfer race") Signed-off-by: Douglas Anderson Reviewed-by: Stephen Boyd Reviewed-by: Akash Asthana Tested-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20201013142448.v2.1.Ifdb1b69fa3367b81118e16e9e4e63299980ca798@changeid Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/qcom-geni-se.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/drivers/soc/qcom/qcom-geni-se.c b/drivers/soc/qcom/qcom-geni-se.c index d0e4f520cff8..751a49f6534f 100644 --- a/drivers/soc/qcom/qcom-geni-se.c +++ b/drivers/soc/qcom/qcom-geni-se.c @@ -289,10 +289,23 @@ static void geni_se_select_fifo_mode(struct geni_se *se) static void geni_se_select_dma_mode(struct geni_se *se) { + u32 proto = geni_se_read_proto(se); u32 val; geni_se_irq_clear(se); + val = readl_relaxed(se->base + SE_GENI_M_IRQ_EN); + if (proto != GENI_SE_UART) { + val &= ~(M_CMD_DONE_EN | M_TX_FIFO_WATERMARK_EN); + val &= ~(M_RX_FIFO_WATERMARK_EN | M_RX_FIFO_LAST_EN); + } + writel_relaxed(val, se->base + SE_GENI_M_IRQ_EN); + + val = readl_relaxed(se->base + SE_GENI_S_IRQ_EN); + if (proto != GENI_SE_UART) + val &= ~S_CMD_DONE_EN; + writel_relaxed(val, se->base + SE_GENI_S_IRQ_EN); + val = readl_relaxed(se->base + SE_GENI_DMA_MODE_EN); val |= GENI_DMA_MODE_EN; writel_relaxed(val, se->base + SE_GENI_DMA_MODE_EN); @@ -651,7 +664,7 @@ int geni_se_tx_dma_prep(struct geni_se *se, void *buf, size_t len, writel_relaxed(lower_32_bits(*iova), se->base + SE_DMA_TX_PTR_L); writel_relaxed(upper_32_bits(*iova), se->base + SE_DMA_TX_PTR_H); writel_relaxed(GENI_SE_DMA_EOT_BUF, se->base + SE_DMA_TX_ATTR); - writel_relaxed(len, se->base + SE_DMA_TX_LEN); + writel(len, se->base + SE_DMA_TX_LEN); return 0; } EXPORT_SYMBOL(geni_se_tx_dma_prep); @@ -688,7 +701,7 @@ int geni_se_rx_dma_prep(struct geni_se *se, void *buf, size_t len, writel_relaxed(upper_32_bits(*iova), se->base + SE_DMA_RX_PTR_H); /* RX does not have EOT buffer type bit. So just reset RX_ATTR */ writel_relaxed(0, se->base + SE_DMA_RX_ATTR); - writel_relaxed(len, se->base + SE_DMA_RX_LEN); + writel(len, se->base + SE_DMA_RX_LEN); return 0; } EXPORT_SYMBOL(geni_se_rx_dma_prep); From 9cb4c67d7717135d6f4600a49ab07b470ea4ee2f Mon Sep 17 00:00:00 2001 From: Douglas Anderson Date: Tue, 13 Oct 2020 14:25:29 -0700 Subject: [PATCH 002/102] Revert "i2c: i2c-qcom-geni: Fix DMA transfer race" This reverts commit 02b9aec59243c6240fc42884acc958602146ddf6. As talked about in the patch ("soc: qcom: geni: More properly switch to DMA mode"), swapping the order of geni_se_setup_m_cmd() and geni_se_xx_dma_prep() can sometimes cause corrupted transfers. Thus we traded one problem for another. Now that we've debugged the problem further and fixed the geni helper functions to more disable FIFO interrupts when we move to DMA mode we can revert it and end up with (hopefully) zero problems! To be explicit, the patch ("soc: qcom: geni: More properly switch to DMA mode") is a prerequisite for this one. Fixes: 02b9aec59243 ("i2c: i2c-qcom-geni: Fix DMA transfer race") Signed-off-by: Douglas Anderson Reviewed-by: Stephen Boyd Reviewed-by: Akash Asthana Tested-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20201013142448.v2.2.I7b22281453b8a18ab16ef2bfd4c641fb1cc6a92c@changeid Signed-off-by: Bjorn Andersson --- drivers/i2c/busses/i2c-qcom-geni.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/i2c/busses/i2c-qcom-geni.c b/drivers/i2c/busses/i2c-qcom-geni.c index 8b4c35f47a70..dce75b85253c 100644 --- a/drivers/i2c/busses/i2c-qcom-geni.c +++ b/drivers/i2c/busses/i2c-qcom-geni.c @@ -366,6 +366,7 @@ static int geni_i2c_rx_one_msg(struct geni_i2c_dev *gi2c, struct i2c_msg *msg, geni_se_select_mode(se, GENI_SE_FIFO); writel_relaxed(len, se->base + SE_I2C_RX_TRANS_LEN); + geni_se_setup_m_cmd(se, I2C_READ, m_param); if (dma_buf && geni_se_rx_dma_prep(se, dma_buf, len, &rx_dma)) { geni_se_select_mode(se, GENI_SE_FIFO); @@ -373,8 +374,6 @@ static int geni_i2c_rx_one_msg(struct geni_i2c_dev *gi2c, struct i2c_msg *msg, dma_buf = NULL; } - geni_se_setup_m_cmd(se, I2C_READ, m_param); - time_left = wait_for_completion_timeout(&gi2c->done, XFER_TIMEOUT); if (!time_left) geni_i2c_abort_xfer(gi2c); @@ -408,6 +407,7 @@ static int geni_i2c_tx_one_msg(struct geni_i2c_dev *gi2c, struct i2c_msg *msg, geni_se_select_mode(se, GENI_SE_FIFO); writel_relaxed(len, se->base + SE_I2C_TX_TRANS_LEN); + geni_se_setup_m_cmd(se, I2C_WRITE, m_param); if (dma_buf && geni_se_tx_dma_prep(se, dma_buf, len, &tx_dma)) { geni_se_select_mode(se, GENI_SE_FIFO); @@ -415,8 +415,6 @@ static int geni_i2c_tx_one_msg(struct geni_i2c_dev *gi2c, struct i2c_msg *msg, dma_buf = NULL; } - geni_se_setup_m_cmd(se, I2C_WRITE, m_param); - if (!dma_buf) /* Get FIFO IRQ */ writel_relaxed(1, se->base + SE_GENI_TX_WATERMARK_REG); From 80e8eaab5e98fc013fd4afb4aab1fceeb049cbfd Mon Sep 17 00:00:00 2001 From: Douglas Anderson Date: Tue, 13 Oct 2020 14:25:30 -0700 Subject: [PATCH 003/102] soc: qcom: geni: Optimize/comment select fifo/dma mode The functions geni_se_select_fifo_mode() and geni_se_select_fifo_mode() are a little funny. They read/write a bunch of memory mapped registers even if they don't change or aren't relevant for the current protocol. Let's make them a little more sane. We'll also add a comment explaining why we don't do some of the operations for UART. NOTE: there is no evidence at all that this makes any performance difference and it fixes no bugs. However, it seems (to me) like it makes the functions a little easier to understand. Decreasing the amount of times we read/write memory mapped registers is also nice, even if we are using "relaxed" variants. Signed-off-by: Douglas Anderson Link: https://lore.kernel.org/r/20201013142448.v2.3.I646736d3969dc47de8daceb379c6ba85993de9f4@changeid Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/qcom-geni-se.c | 50 +++++++++++++++++++++------------ 1 file changed, 32 insertions(+), 18 deletions(-) diff --git a/drivers/soc/qcom/qcom-geni-se.c b/drivers/soc/qcom/qcom-geni-se.c index 751a49f6534f..7649b2057b9a 100644 --- a/drivers/soc/qcom/qcom-geni-se.c +++ b/drivers/soc/qcom/qcom-geni-se.c @@ -266,49 +266,63 @@ EXPORT_SYMBOL(geni_se_init); static void geni_se_select_fifo_mode(struct geni_se *se) { u32 proto = geni_se_read_proto(se); - u32 val; + u32 val, val_old; geni_se_irq_clear(se); - val = readl_relaxed(se->base + SE_GENI_M_IRQ_EN); + /* + * The RX path for the UART is asynchronous and so needs more + * complex logic for enabling / disabling its interrupts. + * + * Specific notes: + * - The done and TX-related interrupts are managed manually. + * - We don't RX from the main sequencer (we use the secondary) so + * we don't need the RX-related interrupts enabled in the main + * sequencer for UART. + */ if (proto != GENI_SE_UART) { + val_old = val = readl_relaxed(se->base + SE_GENI_M_IRQ_EN); val |= M_CMD_DONE_EN | M_TX_FIFO_WATERMARK_EN; val |= M_RX_FIFO_WATERMARK_EN | M_RX_FIFO_LAST_EN; - } - writel_relaxed(val, se->base + SE_GENI_M_IRQ_EN); + if (val != val_old) + writel_relaxed(val, se->base + SE_GENI_M_IRQ_EN); - val = readl_relaxed(se->base + SE_GENI_S_IRQ_EN); - if (proto != GENI_SE_UART) + val_old = val = readl_relaxed(se->base + SE_GENI_S_IRQ_EN); val |= S_CMD_DONE_EN; - writel_relaxed(val, se->base + SE_GENI_S_IRQ_EN); + if (val != val_old) + writel_relaxed(val, se->base + SE_GENI_S_IRQ_EN); + } - val = readl_relaxed(se->base + SE_GENI_DMA_MODE_EN); + val_old = val = readl_relaxed(se->base + SE_GENI_DMA_MODE_EN); val &= ~GENI_DMA_MODE_EN; - writel_relaxed(val, se->base + SE_GENI_DMA_MODE_EN); + if (val != val_old) + writel_relaxed(val, se->base + SE_GENI_DMA_MODE_EN); } static void geni_se_select_dma_mode(struct geni_se *se) { u32 proto = geni_se_read_proto(se); - u32 val; + u32 val, val_old; geni_se_irq_clear(se); - val = readl_relaxed(se->base + SE_GENI_M_IRQ_EN); if (proto != GENI_SE_UART) { + val_old = val = readl_relaxed(se->base + SE_GENI_M_IRQ_EN); val &= ~(M_CMD_DONE_EN | M_TX_FIFO_WATERMARK_EN); val &= ~(M_RX_FIFO_WATERMARK_EN | M_RX_FIFO_LAST_EN); - } - writel_relaxed(val, se->base + SE_GENI_M_IRQ_EN); + if (val != val_old) + writel_relaxed(val, se->base + SE_GENI_M_IRQ_EN); - val = readl_relaxed(se->base + SE_GENI_S_IRQ_EN); - if (proto != GENI_SE_UART) + val_old = val = readl_relaxed(se->base + SE_GENI_S_IRQ_EN); val &= ~S_CMD_DONE_EN; - writel_relaxed(val, se->base + SE_GENI_S_IRQ_EN); + if (val != val_old) + writel_relaxed(val, se->base + SE_GENI_S_IRQ_EN); + } - val = readl_relaxed(se->base + SE_GENI_DMA_MODE_EN); + val_old = val = readl_relaxed(se->base + SE_GENI_DMA_MODE_EN); val |= GENI_DMA_MODE_EN; - writel_relaxed(val, se->base + SE_GENI_DMA_MODE_EN); + if (val != val_old) + writel_relaxed(val, se->base + SE_GENI_DMA_MODE_EN); } /** From 46d43ee48d4fed3f8a5c93295f5a414c71a30fd4 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Wed, 30 Sep 2020 16:56:54 +0200 Subject: [PATCH 004/102] i2c: at91: remove legacy DMA left overs Commit dc6df6e90de9 ("i2c: at91: remove legacy DMA support") removed legcy DMA support from the driver. Remove the last use of the definitions from linux/platform_data/dma-atmel.h and stop including this header. Signed-off-by: Alexandre Belloni Reviewed-by: Codrin Ciubotariu [wsa: fixed typo in subject] Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-at91-master.c | 1 - drivers/i2c/busses/i2c-at91.h | 2 -- 2 files changed, 3 deletions(-) diff --git a/drivers/i2c/busses/i2c-at91-master.c b/drivers/i2c/busses/i2c-at91-master.c index 66864f9cf7ac..1cceb6866689 100644 --- a/drivers/i2c/busses/i2c-at91-master.c +++ b/drivers/i2c/busses/i2c-at91-master.c @@ -26,7 +26,6 @@ #include #include #include -#include #include #include "i2c-at91.h" diff --git a/drivers/i2c/busses/i2c-at91.h b/drivers/i2c/busses/i2c-at91.h index eae673ae786c..942e9c3973bb 100644 --- a/drivers/i2c/busses/i2c-at91.h +++ b/drivers/i2c/busses/i2c-at91.h @@ -18,7 +18,6 @@ #include #include #include -#include #include #define AT91_I2C_TIMEOUT msecs_to_jiffies(100) /* transfer timeout */ @@ -123,7 +122,6 @@ struct at91_twi_pdata { bool has_adv_dig_filtr; bool has_ana_filtr; bool has_clear_cmd; - struct at_dma_slave dma_slave; }; struct at91_twi_dma { From b8be24ec67b6374efded49b35a10b84a1b255b30 Mon Sep 17 00:00:00 2001 From: Cristian Ciocaltea Date: Fri, 9 Oct 2020 00:44:40 +0300 Subject: [PATCH 005/102] i2c: owl: Add support for atomic transfers Atomic transfers are required to properly power off a machine through an I2C controlled PMIC, such as the Actions Semi ATC260x series. System shutdown may happen with interrupts being disabled and, as a consequence, the kernel may hang if the driver does not support atomic transfers. This functionality is essentially implemented by polling the FIFO Status register until either Command Execute Completed or NACK Error bits are set. Signed-off-by: Cristian Ciocaltea Reviewed-by: Manivannan Sadhasivam [wsa: rebased to current tree] Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-owl.c | 73 ++++++++++++++++++++++++++---------- 1 file changed, 54 insertions(+), 19 deletions(-) diff --git a/drivers/i2c/busses/i2c-owl.c b/drivers/i2c/busses/i2c-owl.c index 9918b2a0b909..de3e107ab8d2 100644 --- a/drivers/i2c/busses/i2c-owl.c +++ b/drivers/i2c/busses/i2c-owl.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include @@ -76,6 +77,7 @@ #define OWL_I2C_FIFOCTL_TFR BIT(2) /* I2Cc_FIFOSTAT Bit Mask */ +#define OWL_I2C_FIFOSTAT_CECB BIT(0) #define OWL_I2C_FIFOSTAT_RNB BIT(1) #define OWL_I2C_FIFOSTAT_RFE BIT(2) #define OWL_I2C_FIFOSTAT_TFF BIT(5) @@ -83,7 +85,8 @@ #define OWL_I2C_FIFOSTAT_RFD GENMASK(15, 8) /* I2C bus timeout */ -#define OWL_I2C_TIMEOUT msecs_to_jiffies(4 * 1000) +#define OWL_I2C_TIMEOUT_MS (4 * 1000) +#define OWL_I2C_TIMEOUT msecs_to_jiffies(OWL_I2C_TIMEOUT_MS) #define OWL_I2C_MAX_RETRIES 50 @@ -161,14 +164,11 @@ static void owl_i2c_set_freq(struct owl_i2c_dev *i2c_dev) writel(OWL_I2C_DIV_FACTOR(val), i2c_dev->base + OWL_I2C_REG_CLKDIV); } -static irqreturn_t owl_i2c_interrupt(int irq, void *_dev) +static void owl_i2c_xfer_data(struct owl_i2c_dev *i2c_dev) { - struct owl_i2c_dev *i2c_dev = _dev; struct i2c_msg *msg = i2c_dev->msg; unsigned int stat, fifostat; - spin_lock(&i2c_dev->lock); - i2c_dev->err = 0; /* Handle NACK from slave */ @@ -178,7 +178,7 @@ static irqreturn_t owl_i2c_interrupt(int irq, void *_dev) /* Clear NACK error bit by writing "1" */ owl_i2c_update_reg(i2c_dev->base + OWL_I2C_REG_FIFOSTAT, OWL_I2C_FIFOSTAT_RNB, true); - goto stop; + return; } /* Handle bus error */ @@ -188,7 +188,7 @@ static irqreturn_t owl_i2c_interrupt(int irq, void *_dev) /* Clear BUS error bit by writing "1" */ owl_i2c_update_reg(i2c_dev->base + OWL_I2C_REG_STAT, OWL_I2C_STAT_BEB, true); - goto stop; + return; } /* Handle FIFO read */ @@ -206,8 +206,16 @@ static irqreturn_t owl_i2c_interrupt(int irq, void *_dev) i2c_dev->base + OWL_I2C_REG_TXDAT); } } +} + +static irqreturn_t owl_i2c_interrupt(int irq, void *_dev) +{ + struct owl_i2c_dev *i2c_dev = _dev; + + spin_lock(&i2c_dev->lock); + + owl_i2c_xfer_data(i2c_dev); -stop: /* Clear pending interrupts */ owl_i2c_update_reg(i2c_dev->base + OWL_I2C_REG_STAT, OWL_I2C_STAT_IRQP, true); @@ -240,8 +248,8 @@ static int owl_i2c_check_bus_busy(struct i2c_adapter *adap) return 0; } -static int owl_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, - int num) +static int owl_i2c_xfer_common(struct i2c_adapter *adap, struct i2c_msg *msgs, + int num, bool atomic) { struct owl_i2c_dev *i2c_dev = i2c_get_adapdata(adap); struct i2c_msg *msg; @@ -285,11 +293,12 @@ static int owl_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, goto err_exit; } - reinit_completion(&i2c_dev->msg_complete); + if (!atomic) + reinit_completion(&i2c_dev->msg_complete); - /* Enable I2C controller interrupt */ + /* Enable/disable I2C controller interrupt */ owl_i2c_update_reg(i2c_dev->base + OWL_I2C_REG_CTL, - OWL_I2C_CTL_IRQE, true); + OWL_I2C_CTL_IRQE, !atomic); /* * Select: FIFO enable, Master mode, Stop enable, Data count enable, @@ -357,20 +366,33 @@ static int owl_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, spin_unlock_irqrestore(&i2c_dev->lock, flags); - time_left = wait_for_completion_timeout(&i2c_dev->msg_complete, - adap->timeout); + if (atomic) { + /* Wait for Command Execute Completed or NACK Error bits */ + ret = readl_poll_timeout_atomic(i2c_dev->base + OWL_I2C_REG_FIFOSTAT, + val, val & (OWL_I2C_FIFOSTAT_CECB | + OWL_I2C_FIFOSTAT_RNB), + 10, OWL_I2C_TIMEOUT_MS * 1000); + } else { + time_left = wait_for_completion_timeout(&i2c_dev->msg_complete, + adap->timeout); + if (!time_left) + ret = -ETIMEDOUT; + } spin_lock_irqsave(&i2c_dev->lock, flags); - if (time_left == 0) { + + if (ret) { dev_err(&adap->dev, "Transaction timed out\n"); /* Send stop condition and release the bus */ owl_i2c_update_reg(i2c_dev->base + OWL_I2C_REG_CTL, OWL_I2C_CTL_GBCC_STOP | OWL_I2C_CTL_RB, true); - ret = -ETIMEDOUT; goto err_exit; } + if (atomic) + owl_i2c_xfer_data(i2c_dev); + ret = i2c_dev->err < 0 ? i2c_dev->err : num; err_exit: @@ -384,9 +406,22 @@ static int owl_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, return ret; } +static int owl_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, + int num) +{ + return owl_i2c_xfer_common(adap, msgs, num, false); +} + +static int owl_i2c_xfer_atomic(struct i2c_adapter *adap, + struct i2c_msg *msgs, int num) +{ + return owl_i2c_xfer_common(adap, msgs, num, true); +} + static const struct i2c_algorithm owl_i2c_algorithm = { - .master_xfer = owl_i2c_master_xfer, - .functionality = owl_i2c_func, + .master_xfer = owl_i2c_xfer, + .master_xfer_atomic = owl_i2c_xfer_atomic, + .functionality = owl_i2c_func, }; static const struct i2c_adapter_quirks owl_i2c_quirks = { From 46f8bfebf3a2ddfe949d45a1b63556de4354e706 Mon Sep 17 00:00:00 2001 From: Cristian Ciocaltea Date: Fri, 9 Oct 2020 00:44:41 +0300 Subject: [PATCH 006/102] i2c: owl: Enable asynchronous probing Speed up the boot process by using the asynchronous probing feature supported by the recent kernels. For SBCs based on the Actions Semi S500 SoC, the overall boot time is expected to be reduced by 200-300 ms. Suggested-by: Manivannan Sadhasivam Signed-off-by: Cristian Ciocaltea Reviewed-by: Manivannan Sadhasivam Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-owl.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/i2c/busses/i2c-owl.c b/drivers/i2c/busses/i2c-owl.c index de3e107ab8d2..5cf5a119a6ad 100644 --- a/drivers/i2c/busses/i2c-owl.c +++ b/drivers/i2c/busses/i2c-owl.c @@ -519,6 +519,7 @@ static struct platform_driver owl_i2c_driver = { .driver = { .name = "owl-i2c", .of_match_table = of_match_ptr(owl_i2c_of_match), + .probe_type = PROBE_PREFER_ASYNCHRONOUS, }, }; module_platform_driver(owl_i2c_driver); From eda03fa0279a43b5211485b50686f075bd17e5aa Mon Sep 17 00:00:00 2001 From: Sagar Shrikant Kadam Date: Wed, 21 Oct 2020 07:50:14 -0700 Subject: [PATCH 007/102] i2c: ocores: fix polling mode workaround on FU540-C000 SoC The FU540-C000 has a broken IRQ and support was added earlier so that it will operate in polling mode, but seems to work only in case interrupts property is missing from the i2c0 dt-node. This should not be the case and the driver should handle polling mode with the interrupt property present in i2c0 node of the device tree. So check if it's the FU540-C000 soc and enable polling mode master xfers, as the IRQ for this chip is broken. Fixes commit c45d4ba86731 ("i2c: ocores: add polling mode workaround for Sifive FU540-C000 SoC") Signed-off-by: Sagar Shrikant Kadam Acked-by: Peter Korsgaard Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-ocores.c | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/drivers/i2c/busses/i2c-ocores.c b/drivers/i2c/busses/i2c-ocores.c index f5fc75b65a19..a97cbaabd308 100644 --- a/drivers/i2c/busses/i2c-ocores.c +++ b/drivers/i2c/busses/i2c-ocores.c @@ -83,7 +83,6 @@ struct ocores_i2c { #define TYPE_OCORES 0 #define TYPE_GRLIB 1 -#define TYPE_SIFIVE_REV0 2 #define OCORES_FLAG_BROKEN_IRQ BIT(1) /* Broken IRQ for FU540-C000 SoC */ @@ -476,11 +475,9 @@ static const struct of_device_id ocores_i2c_match[] = { }, { .compatible = "sifive,fu540-c000-i2c", - .data = (void *)TYPE_SIFIVE_REV0, }, { .compatible = "sifive,i2c0", - .data = (void *)TYPE_SIFIVE_REV0, }, {}, }; @@ -606,7 +603,6 @@ static int ocores_i2c_probe(struct platform_device *pdev) { struct ocores_i2c *i2c; struct ocores_i2c_platform_data *pdata; - const struct of_device_id *match; struct resource *res; int irq; int ret; @@ -687,16 +683,19 @@ static int ocores_i2c_probe(struct platform_device *pdev) init_waitqueue_head(&i2c->wait); irq = platform_get_irq(pdev, 0); + /* + * Since the SoC does have an interrupt, its DT has an interrupt + * property - But this should be bypassed as the IRQ logic in this + * SoC is broken. + */ + if (of_device_is_compatible(pdev->dev.of_node, + "sifive,fu540-c000-i2c")) { + i2c->flags |= OCORES_FLAG_BROKEN_IRQ; + irq = -ENXIO; + } + if (irq == -ENXIO) { ocores_algorithm.master_xfer = ocores_xfer_polling; - - /* - * Set in OCORES_FLAG_BROKEN_IRQ to enable workaround for - * FU540-C000 SoC in polling mode. - */ - match = of_match_node(ocores_i2c_match, pdev->dev.of_node); - if (match && (long)match->data == TYPE_SIFIVE_REV0) - i2c->flags |= OCORES_FLAG_BROKEN_IRQ; } else { if (irq < 0) return irq; From c0164159c2dce4acdd6e9901b3d2fe0995b78430 Mon Sep 17 00:00:00 2001 From: Martin Kaiser Date: Sun, 1 Nov 2020 18:18:05 +0100 Subject: [PATCH 008/102] i2c: exynos5: remove duplicate error message platform_get_irq already prints an error message if the requested irq was not found. Don't print another message in the driver. Signed-off-by: Martin Kaiser Reviewed-by: Krzysztof Kozlowski Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-exynos5.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/i2c/busses/i2c-exynos5.c b/drivers/i2c/busses/i2c-exynos5.c index 6ce3ec03b595..c5f5fb28762d 100644 --- a/drivers/i2c/busses/i2c-exynos5.c +++ b/drivers/i2c/busses/i2c-exynos5.c @@ -779,7 +779,6 @@ static int exynos5_i2c_probe(struct platform_device *pdev) i2c->irq = ret = platform_get_irq(pdev, 0); if (ret <= 0) { - dev_err(&pdev->dev, "cannot find HS-I2C IRQ\n"); ret = -EINVAL; goto err_clk; } From 40af583d16465aae2a570e469fc72a5d24438a20 Mon Sep 17 00:00:00 2001 From: Martin Kaiser Date: Sun, 1 Nov 2020 18:18:06 +0100 Subject: [PATCH 009/102] i2c: exynos5: fix platform_get_irq error handling If platform_get_irq returns an error, relay this error to the caller of the probe function. Don't change all errors to -EINVAL. This breaks the case where platform_get_irq returns -EPROBE_DEFER. Signed-off-by: Martin Kaiser Reviewed-by: Krzysztof Kozlowski Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-exynos5.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/i2c/busses/i2c-exynos5.c b/drivers/i2c/busses/i2c-exynos5.c index c5f5fb28762d..fad1c52857aa 100644 --- a/drivers/i2c/busses/i2c-exynos5.c +++ b/drivers/i2c/busses/i2c-exynos5.c @@ -778,10 +778,8 @@ static int exynos5_i2c_probe(struct platform_device *pdev) init_completion(&i2c->msg_complete); i2c->irq = ret = platform_get_irq(pdev, 0); - if (ret <= 0) { - ret = -EINVAL; + if (ret <= 0) goto err_clk; - } ret = devm_request_irq(&pdev->dev, i2c->irq, exynos5_i2c_irq, IRQF_NO_SUSPEND, dev_name(&pdev->dev), i2c); From 5df324b5f4baa3a51990f078fa445800197dfba3 Mon Sep 17 00:00:00 2001 From: Martin Kaiser Date: Sun, 1 Nov 2020 18:18:07 +0100 Subject: [PATCH 010/102] i2c: exynos5: don't check for irq 0 platform_get_irq never returns 0. Don't check for this. Make it clear that the error path always returns a negative error code. Signed-off-by: Martin Kaiser Reviewed-by: Krzysztof Kozlowski Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-exynos5.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/i2c/busses/i2c-exynos5.c b/drivers/i2c/busses/i2c-exynos5.c index fad1c52857aa..20a9881a0d6c 100644 --- a/drivers/i2c/busses/i2c-exynos5.c +++ b/drivers/i2c/busses/i2c-exynos5.c @@ -778,7 +778,7 @@ static int exynos5_i2c_probe(struct platform_device *pdev) init_completion(&i2c->msg_complete); i2c->irq = ret = platform_get_irq(pdev, 0); - if (ret <= 0) + if (ret < 0) goto err_clk; ret = devm_request_irq(&pdev->dev, i2c->irq, exynos5_i2c_irq, From 1dc575490bff8b1c491d6b723b772ab6f02865a5 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Mon, 26 Oct 2020 16:38:08 +0100 Subject: [PATCH 011/102] mmc: s3cmci: include GPIO descriptor consumer header MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The driver uses GPIO Descriptor Consumer Interface so include proper header to fix compile test errors like: drivers/mmc/host/s3cmci.c: In function ‘s3cmci_check_sdio_irq’: drivers/mmc/host/s3cmci.c:304:7: error: implicit declaration of function ‘gpiod_get_value’; did you mean ‘gpio_get_value’? [-Werror=implicit-function-declaration] drivers/mmc/host/s3cmci.c: In function ‘s3cmci_probe_pdata’: drivers/mmc/host/s3cmci.c:1451:19: error: implicit declaration of function ‘devm_gpiod_get_index’ [-Werror=implicit-function-declaration] Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20201026153810.89512-1-krzk@kernel.org Signed-off-by: Ulf Hansson --- drivers/mmc/host/s3cmci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mmc/host/s3cmci.c b/drivers/mmc/host/s3cmci.c index 643d54eceef6..a33a7823c265 100644 --- a/drivers/mmc/host/s3cmci.c +++ b/drivers/mmc/host/s3cmci.c @@ -17,7 +17,7 @@ #include #include #include -#include +#include #include #include #include From 1b0e4a2141c7bf6a122f1e04cbc1690b835707cf Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Mon, 26 Oct 2020 16:38:09 +0100 Subject: [PATCH 012/102] mmc: s3cmci: enable compile testing The driver can be compile tested to increase build coverage. Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20201026153810.89512-2-krzk@kernel.org Signed-off-by: Ulf Hansson --- drivers/mmc/host/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig index 31481c9fcc2e..310e546e5898 100644 --- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig @@ -631,8 +631,8 @@ config MMC_SPI config MMC_S3C tristate "Samsung S3C SD/MMC Card Interface support" - depends on ARCH_S3C24XX - depends on S3C24XX_DMAC + depends on ARCH_S3C24XX || COMPILE_TEST + depends on S3C24XX_DMAC || COMPILE_TEST help This selects a driver for the MCI interface found in Samsung's S3C2410, S3C2412, S3C2440, S3C2442 CPUs. From b733775fb68f2a179dd28e6b41ff189fbcd3e95b Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Mon, 26 Oct 2020 16:38:10 +0100 Subject: [PATCH 013/102] mmc: sunxi: drop of_match_ptr from of_device_id table MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The driver can match only via DT table so it should be always used and the of_match_ptr does not have any sense (this also allows ACPI matching via PRP0001, even though it is not relevant for sunxi). This fixes compile warning: drivers/mmc/host/sunxi-mmc.c:1181:34: warning: ‘sunxi_mmc_of_match’ defined but not used [-Wunused-const-variable=] Reported-by: kernel test robot Signed-off-by: Krzysztof Kozlowski Acked-by: Maxime Ripard Link: https://lore.kernel.org/r/20201026153810.89512-3-krzk@kernel.org Signed-off-by: Ulf Hansson --- drivers/mmc/host/sunxi-mmc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/mmc/host/sunxi-mmc.c b/drivers/mmc/host/sunxi-mmc.c index fc62773602ec..6310693f2ac0 100644 --- a/drivers/mmc/host/sunxi-mmc.c +++ b/drivers/mmc/host/sunxi-mmc.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -1515,7 +1516,7 @@ static struct platform_driver sunxi_mmc_driver = { .driver = { .name = "sunxi-mmc", .probe_type = PROBE_PREFER_ASYNCHRONOUS, - .of_match_table = of_match_ptr(sunxi_mmc_of_match), + .of_match_table = sunxi_mmc_of_match, .pm = &sunxi_mmc_pm_ops, }, .probe = sunxi_mmc_probe, From e10f480902da770db895b6a1d2f10b11d80fe5d8 Mon Sep 17 00:00:00 2001 From: Raul E Rangel Date: Tue, 27 Oct 2020 19:46:12 +1100 Subject: [PATCH 014/102] mmc: sdhci-acpi: AMDI0040: Allow changing HS200/HS400 driver strength This change will allow platform designers better control over signal integrity by allowing them to tune the HS200 and HS400 driver strengths. The driver strength was previously hard coded to A to solve boot problems with certain platforms. This driver strength does not universally apply to all platforms so we need a knob to adjust it. All older platforms currently have the SDR104 preset hard coded to A in the firmware. This means that switching from the hard coded value in the kernel to reading the SDR104 preset is a no-op for these platforms. Newer platforms will have properly set presets. So this change will support both new and old platforms. Signed-off-by: Raul E Rangel Signed-off-by: Victor Ding Acked-by: Adrian Hunter Link: https://lore.kernel.org/r/20201027084612.528301-1-victording@google.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci-acpi.c | 38 ++++++++++++++++++++++++++++++++--- 1 file changed, 35 insertions(+), 3 deletions(-) diff --git a/drivers/mmc/host/sdhci-acpi.c b/drivers/mmc/host/sdhci-acpi.c index 54205e3be9e8..b6574e7fd26b 100644 --- a/drivers/mmc/host/sdhci-acpi.c +++ b/drivers/mmc/host/sdhci-acpi.c @@ -5,6 +5,7 @@ * Copyright (c) 2012, Intel Corporation. */ +#include #include #include #include @@ -545,10 +546,41 @@ struct amd_sdhci_host { static int amd_select_drive_strength(struct mmc_card *card, unsigned int max_dtr, int host_drv, - int card_drv, int *drv_type) + int card_drv, int *host_driver_strength) { - *drv_type = MMC_SET_DRIVER_TYPE_A; - return MMC_SET_DRIVER_TYPE_A; + struct sdhci_host *host = mmc_priv(card->host); + u16 preset, preset_driver_strength; + + /* + * This method is only called by mmc_select_hs200 so we only need to + * read from the HS200 (SDR104) preset register. + * + * Firmware that has "invalid/default" presets return a driver strength + * of A. This matches the previously hard coded value. + */ + preset = sdhci_readw(host, SDHCI_PRESET_FOR_SDR104); + preset_driver_strength = FIELD_GET(SDHCI_PRESET_DRV_MASK, preset); + + /* + * We want the controller driver strength to match the card's driver + * strength so they have similar rise/fall times. + * + * The controller driver strength set by this method is sticky for all + * timings after this method is called. This unfortunately means that + * while HS400 tuning is in progress we end up with mismatched driver + * strengths between the controller and the card. HS400 tuning requires + * switching from HS400->DDR52->HS->HS200->HS400. So the driver mismatch + * happens while in DDR52 and HS modes. This has not been observed to + * cause problems. Enabling presets would fix this issue. + */ + *host_driver_strength = preset_driver_strength; + + /* + * The resulting card driver strength is only set when switching the + * card's timing to HS200 or HS400. The card will use the default driver + * strength (B) for any other mode. + */ + return preset_driver_strength; } static void sdhci_acpi_amd_hs400_dll(struct sdhci_host *host, bool enable) From c626695ecd8b8a5f66982519d07207423107c077 Mon Sep 17 00:00:00 2001 From: Wenbin Mei Date: Wed, 14 Oct 2020 11:08:43 +0800 Subject: [PATCH 015/102] dt-bindings: mmc: Convert mtk-sd to json-schema Convert the mtk-sd binding to DT schema format using json-schema. Signed-off-by: Wenbin Mei Reviewed-by: Rob Herring Link: https://lore.kernel.org/r/20201014030846.12428-2-wenbin.mei@mediatek.com Signed-off-by: Ulf Hansson --- .../devicetree/bindings/mmc/mtk-sd.txt | 75 -------- .../devicetree/bindings/mmc/mtk-sd.yaml | 165 ++++++++++++++++++ 2 files changed, 165 insertions(+), 75 deletions(-) delete mode 100644 Documentation/devicetree/bindings/mmc/mtk-sd.txt create mode 100644 Documentation/devicetree/bindings/mmc/mtk-sd.yaml diff --git a/Documentation/devicetree/bindings/mmc/mtk-sd.txt b/Documentation/devicetree/bindings/mmc/mtk-sd.txt deleted file mode 100644 index 26a8f320a156..000000000000 --- a/Documentation/devicetree/bindings/mmc/mtk-sd.txt +++ /dev/null @@ -1,75 +0,0 @@ -* MTK MMC controller - -The MTK MSDC can act as a MMC controller -to support MMC, SD, and SDIO types of memory cards. - -This file documents differences between the core properties in mmc.txt -and the properties used by the msdc driver. - -Required properties: -- compatible: value should be either of the following. - "mediatek,mt8135-mmc": for mmc host ip compatible with mt8135 - "mediatek,mt8173-mmc": for mmc host ip compatible with mt8173 - "mediatek,mt8183-mmc": for mmc host ip compatible with mt8183 - "mediatek,mt8516-mmc": for mmc host ip compatible with mt8516 - "mediatek,mt6779-mmc": for mmc host ip compatible with mt6779 - "mediatek,mt2701-mmc": for mmc host ip compatible with mt2701 - "mediatek,mt2712-mmc": for mmc host ip compatible with mt2712 - "mediatek,mt7622-mmc": for MT7622 SoC - "mediatek,mt7623-mmc", "mediatek,mt2701-mmc": for MT7623 SoC - "mediatek,mt7620-mmc", for MT7621 SoC (and others) - -- reg: physical base address of the controller and length -- interrupts: Should contain MSDC interrupt number -- clocks: Should contain phandle for the clock feeding the MMC controller -- clock-names: Should contain the following: - "source" - source clock (required) - "hclk" - HCLK which used for host (required) - "source_cg" - independent source clock gate (required for MT2712) - "bus_clk" - bus clock used for internal register access (required for MT2712 MSDC0/3) -- pinctrl-names: should be "default", "state_uhs" -- pinctrl-0: should contain default/high speed pin ctrl -- pinctrl-1: should contain uhs mode pin ctrl -- vmmc-supply: power to the Core -- vqmmc-supply: power to the IO - -Optional properties: -- assigned-clocks: PLL of the source clock -- assigned-clock-parents: parent of source clock, used for HS400 mode to get 400Mhz source clock -- hs400-ds-delay: HS400 DS delay setting -- mediatek,hs200-cmd-int-delay: HS200 command internal delay setting. - This field has total 32 stages. - The value is an integer from 0 to 31. -- mediatek,hs400-cmd-int-delay: HS400 command internal delay setting - This field has total 32 stages. - The value is an integer from 0 to 31. -- mediatek,hs400-cmd-resp-sel-rising: HS400 command response sample selection - If present,HS400 command responses are sampled on rising edges. - If not present,HS400 command responses are sampled on falling edges. -- mediatek,latch-ck: Some SoCs do not support enhance_rx, need set correct latch-ck to avoid data crc - error caused by stop clock(fifo full) - Valid range = [0:0x7]. if not present, default value is 0. - applied to compatible "mediatek,mt2701-mmc". -- resets: Phandle and reset specifier pair to softreset line of MSDC IP. -- reset-names: Should be "hrst". - -Examples: -mmc0: mmc@11230000 { - compatible = "mediatek,mt8173-mmc", "mediatek,mt8135-mmc"; - reg = <0 0x11230000 0 0x108>; - interrupts = ; - vmmc-supply = <&mt6397_vemc_3v3_reg>; - vqmmc-supply = <&mt6397_vio18_reg>; - clocks = <&pericfg CLK_PERI_MSDC30_0>, - <&topckgen CLK_TOP_MSDC50_0_H_SEL>; - clock-names = "source", "hclk"; - pinctrl-names = "default", "state_uhs"; - pinctrl-0 = <&mmc0_pins_default>; - pinctrl-1 = <&mmc0_pins_uhs>; - assigned-clocks = <&topckgen CLK_TOP_MSDC50_0_SEL>; - assigned-clock-parents = <&topckgen CLK_TOP_MSDCPLL_D2>; - hs400-ds-delay = <0x14015>; - mediatek,hs200-cmd-int-delay = <26>; - mediatek,hs400-cmd-int-delay = <14>; - mediatek,hs400-cmd-resp-sel-rising; -}; diff --git a/Documentation/devicetree/bindings/mmc/mtk-sd.yaml b/Documentation/devicetree/bindings/mmc/mtk-sd.yaml new file mode 100644 index 000000000000..79905df75f1d --- /dev/null +++ b/Documentation/devicetree/bindings/mmc/mtk-sd.yaml @@ -0,0 +1,165 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/mmc/mtk-sd.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: MTK MSDC Storage Host Controller Binding + +maintainers: + - Chaotian Jing + - Wenbin Mei + +allOf: + - $ref: mmc-controller.yaml# + +properties: + compatible: + oneOf: + - enum: + - mediatek,mt2701-mmc + - mediatek,mt2712-mmc + - mediatek,mt6779-mmc + - mediatek,mt7620-mmc + - mediatek,mt7622-mmc + - mediatek,mt8135-mmc + - mediatek,mt8173-mmc + - mediatek,mt8183-mmc + - mediatek,mt8516-mmc + - items: + - const: mediatek,mt7623-mmc + - const: mediatek,mt2701-mmc + + clocks: + description: + Should contain phandle for the clock feeding the MMC controller. + minItems: 2 + maxItems: 4 + items: + - description: source clock (required). + - description: HCLK which used for host (required). + - description: independent source clock gate (required for MT2712). + - description: bus clock used for internal register access (required for MT2712 MSDC0/3). + + clock-names: + minItems: 2 + maxItems: 4 + items: + - const: source + - const: hclk + - const: source_cg + - const: bus_clk + + pinctrl-names: + items: + - const: default + - const: state_uhs + + pinctrl-0: + description: + should contain default/high speed pin ctrl. + maxItems: 1 + + pinctrl-1: + description: + should contain uhs mode pin ctrl. + maxItems: 1 + + assigned-clocks: + description: + PLL of the source clock. + maxItems: 1 + + assigned-clock-parents: + description: + parent of source clock, used for HS400 mode to get 400Mhz source clock. + maxItems: 1 + + hs400-ds-delay: + $ref: /schemas/types.yaml#/definitions/uint32 + description: + HS400 DS delay setting. + minimum: 0 + maximum: 0xffffffff + + mediatek,hs200-cmd-int-delay: + $ref: /schemas/types.yaml#/definitions/uint32 + description: + HS200 command internal delay setting. + This field has total 32 stages. + The value is an integer from 0 to 31. + minimum: 0 + maximum: 31 + + mediatek,hs400-cmd-int-delay: + $ref: /schemas/types.yaml#/definitions/uint32 + description: + HS400 command internal delay setting. + This field has total 32 stages. + The value is an integer from 0 to 31. + minimum: 0 + maximum: 31 + + mediatek,hs400-cmd-resp-sel-rising: + $ref: /schemas/types.yaml#/definitions/flag + description: + HS400 command response sample selection. + If present, HS400 command responses are sampled on rising edges. + If not present, HS400 command responses are sampled on falling edges. + + mediatek,latch-ck: + $ref: /schemas/types.yaml#/definitions/uint32 + description: + Some SoCs do not support enhance_rx, need set correct latch-ck to avoid + data crc error caused by stop clock(fifo full) Valid range = [0:0x7]. + if not present, default value is 0. + applied to compatible "mediatek,mt2701-mmc". + minimum: 0 + maximum: 7 + + resets: + maxItems: 1 + + reset-names: + const: hrst + +required: + - compatible + - reg + - interrupts + - clocks + - clock-names + - pinctrl-names + - pinctrl-0 + - pinctrl-1 + - vmmc-supply + - vqmmc-supply + +unevaluatedProperties: false + +examples: + - | + #include + #include + #include + mmc0: mmc@11230000 { + compatible = "mediatek,mt8173-mmc"; + reg = <0x11230000 0x1000>; + interrupts = ; + vmmc-supply = <&mt6397_vemc_3v3_reg>; + vqmmc-supply = <&mt6397_vio18_reg>; + clocks = <&pericfg CLK_PERI_MSDC30_0>, + <&topckgen CLK_TOP_MSDC50_0_H_SEL>; + clock-names = "source", "hclk"; + pinctrl-names = "default", "state_uhs"; + pinctrl-0 = <&mmc0_pins_default>; + pinctrl-1 = <&mmc0_pins_uhs>; + assigned-clocks = <&topckgen CLK_TOP_MSDC50_0_SEL>; + assigned-clock-parents = <&topckgen CLK_TOP_MSDCPLL_D2>; + hs400-ds-delay = <0x14015>; + mediatek,hs200-cmd-int-delay = <26>; + mediatek,hs400-cmd-int-delay = <14>; + mediatek,hs400-cmd-resp-sel-rising; + }; + +... From 59a23395d8aa2662725ec9f162b9d3b0f34d56ce Mon Sep 17 00:00:00 2001 From: Wenbin Mei Date: Wed, 14 Oct 2020 11:08:44 +0800 Subject: [PATCH 016/102] dt-bindings: mmc: Add support for MT8192 SoC MT8192 mmc host IP is compatible with MT8183, let's add support for this. Signed-off-by: Wenbin Mei Link: https://lore.kernel.org/r/20201014030846.12428-3-wenbin.mei@mediatek.com Signed-off-by: Ulf Hansson --- Documentation/devicetree/bindings/mmc/mtk-sd.yaml | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/mmc/mtk-sd.yaml b/Documentation/devicetree/bindings/mmc/mtk-sd.yaml index 79905df75f1d..030e3fdce492 100644 --- a/Documentation/devicetree/bindings/mmc/mtk-sd.yaml +++ b/Documentation/devicetree/bindings/mmc/mtk-sd.yaml @@ -29,26 +29,37 @@ properties: - items: - const: mediatek,mt7623-mmc - const: mediatek,mt2701-mmc + - items: + - const: mediatek,mt8192-mmc + - const: mediatek,mt8183-mmc clocks: description: Should contain phandle for the clock feeding the MMC controller. minItems: 2 - maxItems: 4 + maxItems: 8 items: - description: source clock (required). - description: HCLK which used for host (required). - description: independent source clock gate (required for MT2712). - description: bus clock used for internal register access (required for MT2712 MSDC0/3). + - description: msdc subsys clock gate (required for MT8192). + - description: peripheral bus clock gate (required for MT8192). + - description: AXI bus clock gate (required for MT8192). + - description: AHB bus clock gate (required for MT8192). clock-names: minItems: 2 - maxItems: 4 + maxItems: 8 items: - const: source - const: hclk - const: source_cg - const: bus_clk + - const: sys_cg + - const: pclk_cg + - const: axi_cg + - const: ahb_cg pinctrl-names: items: From f5eccd94b63f6abf74b890770f268bfc8f59a9bb Mon Sep 17 00:00:00 2001 From: Wenbin Mei Date: Wed, 14 Oct 2020 11:08:46 +0800 Subject: [PATCH 017/102] mmc: mediatek: Add subsys clock control for MT8192 msdc MT8192 msdc is an independent sub system, we need control more bus clocks for it. Add support for the additional subsys clocks to allow it to be configured appropriately. Signed-off-by: Wenbin Mei Reviewed-by: Nicolas Boichat Link: https://lore.kernel.org/r/20201014030846.12428-5-wenbin.mei@mediatek.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/mtk-sd.c | 74 +++++++++++++++++++++++++++++---------- 1 file changed, 56 insertions(+), 18 deletions(-) diff --git a/drivers/mmc/host/mtk-sd.c b/drivers/mmc/host/mtk-sd.c index a704745e5882..c7df7510f120 100644 --- a/drivers/mmc/host/mtk-sd.c +++ b/drivers/mmc/host/mtk-sd.c @@ -35,6 +35,7 @@ #include "cqhci.h" #define MAX_BD_NUM 1024 +#define MSDC_NR_CLOCKS 3 /*--------------------------------------------------------------------------*/ /* Common Definition */ @@ -425,6 +426,8 @@ struct msdc_host { struct clk *h_clk; /* msdc h_clk */ struct clk *bus_clk; /* bus clock which used to access register */ struct clk *src_clk_cg; /* msdc source clock control gate */ + struct clk *sys_clk_cg; /* msdc subsys clock control gate */ + struct clk_bulk_data bulk_clks[MSDC_NR_CLOCKS]; u32 mclk; /* mmc subsystem clock frequency */ u32 src_clk_freq; /* source clock frequency */ unsigned char timing; @@ -784,6 +787,7 @@ static void msdc_set_busy_timeout(struct msdc_host *host, u64 ns, u64 clks) static void msdc_gate_clock(struct msdc_host *host) { + clk_bulk_disable_unprepare(MSDC_NR_CLOCKS, host->bulk_clks); clk_disable_unprepare(host->src_clk_cg); clk_disable_unprepare(host->src_clk); clk_disable_unprepare(host->bus_clk); @@ -792,10 +796,18 @@ static void msdc_gate_clock(struct msdc_host *host) static void msdc_ungate_clock(struct msdc_host *host) { + int ret; + clk_prepare_enable(host->h_clk); clk_prepare_enable(host->bus_clk); clk_prepare_enable(host->src_clk); clk_prepare_enable(host->src_clk_cg); + ret = clk_bulk_prepare_enable(MSDC_NR_CLOCKS, host->bulk_clks); + if (ret) { + dev_err(host->dev, "Cannot enable pclk/axi/ahb clock gates\n"); + return; + } + while (!(readl(host->base + MSDC_CFG) & MSDC_CFG_CKSTB)) cpu_relax(); } @@ -2366,6 +2378,48 @@ static void msdc_of_property_parse(struct platform_device *pdev, host->cqhci = false; } +static int msdc_of_clock_parse(struct platform_device *pdev, + struct msdc_host *host) +{ + int ret; + + host->src_clk = devm_clk_get(&pdev->dev, "source"); + if (IS_ERR(host->src_clk)) + return PTR_ERR(host->src_clk); + + host->h_clk = devm_clk_get(&pdev->dev, "hclk"); + if (IS_ERR(host->h_clk)) + return PTR_ERR(host->h_clk); + + host->bus_clk = devm_clk_get_optional(&pdev->dev, "bus_clk"); + if (IS_ERR(host->bus_clk)) + host->bus_clk = NULL; + + /*source clock control gate is optional clock*/ + host->src_clk_cg = devm_clk_get_optional(&pdev->dev, "source_cg"); + if (IS_ERR(host->src_clk_cg)) + host->src_clk_cg = NULL; + + host->sys_clk_cg = devm_clk_get_optional(&pdev->dev, "sys_cg"); + if (IS_ERR(host->sys_clk_cg)) + host->sys_clk_cg = NULL; + + /* If present, always enable for this clock gate */ + clk_prepare_enable(host->sys_clk_cg); + + host->bulk_clks[0].id = "pclk_cg"; + host->bulk_clks[1].id = "axi_cg"; + host->bulk_clks[2].id = "ahb_cg"; + ret = devm_clk_bulk_get_optional(&pdev->dev, MSDC_NR_CLOCKS, + host->bulk_clks); + if (ret) { + dev_err(&pdev->dev, "Cannot get pclk/axi/ahb clock gates\n"); + return ret; + } + + return 0; +} + static int msdc_drv_probe(struct platform_device *pdev) { struct mmc_host *mmc; @@ -2405,25 +2459,9 @@ static int msdc_drv_probe(struct platform_device *pdev) if (ret) goto host_free; - host->src_clk = devm_clk_get(&pdev->dev, "source"); - if (IS_ERR(host->src_clk)) { - ret = PTR_ERR(host->src_clk); + ret = msdc_of_clock_parse(pdev, host); + if (ret) goto host_free; - } - - host->h_clk = devm_clk_get(&pdev->dev, "hclk"); - if (IS_ERR(host->h_clk)) { - ret = PTR_ERR(host->h_clk); - goto host_free; - } - - host->bus_clk = devm_clk_get(&pdev->dev, "bus_clk"); - if (IS_ERR(host->bus_clk)) - host->bus_clk = NULL; - /*source clock control gate is optional clock*/ - host->src_clk_cg = devm_clk_get(&pdev->dev, "source_cg"); - if (IS_ERR(host->src_clk_cg)) - host->src_clk_cg = NULL; host->reset = devm_reset_control_get_optional_exclusive(&pdev->dev, "hrst"); From 9baf7c5e3ab364c038070a3b396de3b8a10016cd Mon Sep 17 00:00:00 2001 From: Tian Tao Date: Mon, 19 Oct 2020 08:43:13 +0800 Subject: [PATCH 018/102] mmc: mediatek: Replace spin_lock_irqsave by spin_lock in hard IRQ The code has been in a irq-disabled context since it is hard IRQ. Therefore there no need to do it again. Signed-off-by: Tian Tao Link: https://lore.kernel.org/r/1603068193-44688-1-git-send-email-tiantao6@hisilicon.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/mtk-sd.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/mmc/host/mtk-sd.c b/drivers/mmc/host/mtk-sd.c index c7df7510f120..f7f68623fefc 100644 --- a/drivers/mmc/host/mtk-sd.c +++ b/drivers/mmc/host/mtk-sd.c @@ -1548,13 +1548,12 @@ static irqreturn_t msdc_irq(int irq, void *dev_id) struct mmc_host *mmc = mmc_from_priv(host); while (true) { - unsigned long flags; struct mmc_request *mrq; struct mmc_command *cmd; struct mmc_data *data; u32 events, event_mask; - spin_lock_irqsave(&host->lock, flags); + spin_lock(&host->lock); events = readl(host->base + MSDC_INT); event_mask = readl(host->base + MSDC_INTEN); if ((events & event_mask) & MSDC_INT_SDIOIRQ) @@ -1565,7 +1564,7 @@ static irqreturn_t msdc_irq(int irq, void *dev_id) mrq = host->mrq; cmd = host->cmd; data = host->data; - spin_unlock_irqrestore(&host->lock, flags); + spin_unlock(&host->lock); if ((events & event_mask) & MSDC_INT_SDIOIRQ) sdio_signal_irq(mmc); From ead49373d2916080509f51fc6a4ee8f9bc021b9b Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Thu, 29 Oct 2020 09:57:16 +0800 Subject: [PATCH 019/102] mmc: core: Initial support for SD express card/host In the SD specification v7.10 the SD express card has been added. This new type of removable SD card, can be managed via a PCIe/NVMe based interface, while also allowing backwards compatibility towards the legacy SD interface. To keep the backwards compatibility, it's required to start the initialization through the legacy SD interface. If it turns out that the mmc host and the SD card, both supports the PCIe/NVMe interface, then a switch should be allowed. Therefore, let's introduce some basic support for this type of SD cards to the mmc core. The mmc host, should set MMC_CAP2_SD_EXP if it supports this interface and MMC_CAP2_SD_EXP_1_2V, if also 1.2V is supported, as to inform the core about it. To deal with the switch to the PCIe/NVMe interface, the mmc host is required to implement a new host ops, ->init_sd_express(). Based on the initial communication between the host and the card, host->ios.timing is set to either MMC_TIMING_SD_EXP or MMC_TIMING_SD_EXP_1_2V, depending on if 1.2V is supported or not. In this way, the mmc host can check these values in its ->init_sd_express() ops, to know how to proceed with the handover. Note that, to manage card insert/removal, the mmc core sticks with using the ->get_cd() callback, which means it's the host's responsibility to make sure it provides valid data, even if the card may be managed by PCIe/NVMe at the moment. As long as the card seems to be present, the mmc core keeps the card powered on. Cc: Greg Kroah-Hartman Cc: Arnd Bergmann Cc: Christoph Hellwig Cc: Rui Feng Signed-off-by: Ulf Hansson Reviewed-by: Greg Kroah-Hartman Link: https://lore.kernel.org/r/1603936636-3126-1-git-send-email-rui_feng@realsil.com.cn --- drivers/mmc/core/core.c | 15 ++++++++++-- drivers/mmc/core/host.h | 6 +++++ drivers/mmc/core/sd_ops.c | 49 +++++++++++++++++++++++++++++++++++++-- drivers/mmc/core/sd_ops.h | 1 + include/linux/mmc/host.h | 7 ++++++ 5 files changed, 74 insertions(+), 4 deletions(-) diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index d42037f0f10d..19f1ee57fb34 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -2147,8 +2147,12 @@ static int mmc_rescan_try_freq(struct mmc_host *host, unsigned freq) mmc_go_idle(host); - if (!(host->caps2 & MMC_CAP2_NO_SD)) - mmc_send_if_cond(host, host->ocr_avail); + if (!(host->caps2 & MMC_CAP2_NO_SD)) { + if (mmc_send_if_cond_pcie(host, host->ocr_avail)) + goto out; + if (mmc_card_sd_express(host)) + return 0; + } /* Order's important: probe SDIO, then SD, then MMC */ if (!(host->caps2 & MMC_CAP2_NO_SDIO)) @@ -2163,6 +2167,7 @@ static int mmc_rescan_try_freq(struct mmc_host *host, unsigned freq) if (!mmc_attach_mmc(host)) return 0; +out: mmc_power_off(host); return -EIO; } @@ -2290,6 +2295,12 @@ void mmc_rescan(struct work_struct *work) goto out; } + /* If an SD express card is present, then leave it as is. */ + if (mmc_card_sd_express(host)) { + mmc_release_host(host); + goto out; + } + for (i = 0; i < ARRAY_SIZE(freqs); i++) { unsigned int freq = freqs[i]; if (freq > host->f_max) { diff --git a/drivers/mmc/core/host.h b/drivers/mmc/core/host.h index 5e3b9534ffb2..ba407617ed23 100644 --- a/drivers/mmc/core/host.h +++ b/drivers/mmc/core/host.h @@ -77,5 +77,11 @@ static inline bool mmc_card_hs400es(struct mmc_card *card) return card->host->ios.enhanced_strobe; } +static inline bool mmc_card_sd_express(struct mmc_host *host) +{ + return host->ios.timing == MMC_TIMING_SD_EXP || + host->ios.timing == MMC_TIMING_SD_EXP_1_2V; +} + #endif diff --git a/drivers/mmc/core/sd_ops.c b/drivers/mmc/core/sd_ops.c index 22bf528294b9..d61ff811218c 100644 --- a/drivers/mmc/core/sd_ops.c +++ b/drivers/mmc/core/sd_ops.c @@ -158,7 +158,8 @@ int mmc_send_app_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr) return err; } -int mmc_send_if_cond(struct mmc_host *host, u32 ocr) +static int __mmc_send_if_cond(struct mmc_host *host, u32 ocr, u8 pcie_bits, + u32 *resp) { struct mmc_command cmd = {}; int err; @@ -171,7 +172,7 @@ int mmc_send_if_cond(struct mmc_host *host, u32 ocr) * SD 1.0 cards. */ cmd.opcode = SD_SEND_IF_COND; - cmd.arg = ((ocr & 0xFF8000) != 0) << 8 | test_pattern; + cmd.arg = ((ocr & 0xFF8000) != 0) << 8 | pcie_bits << 8 | test_pattern; cmd.flags = MMC_RSP_SPI_R7 | MMC_RSP_R7 | MMC_CMD_BCR; err = mmc_wait_for_cmd(host, &cmd, 0); @@ -186,6 +187,50 @@ int mmc_send_if_cond(struct mmc_host *host, u32 ocr) if (result_pattern != test_pattern) return -EIO; + if (resp) + *resp = cmd.resp[0]; + + return 0; +} + +int mmc_send_if_cond(struct mmc_host *host, u32 ocr) +{ + return __mmc_send_if_cond(host, ocr, 0, NULL); +} + +int mmc_send_if_cond_pcie(struct mmc_host *host, u32 ocr) +{ + u32 resp = 0; + u8 pcie_bits = 0; + int ret; + + if (host->caps2 & MMC_CAP2_SD_EXP) { + /* Probe card for SD express support via PCIe. */ + pcie_bits = 0x10; + if (host->caps2 & MMC_CAP2_SD_EXP_1_2V) + /* Probe also for 1.2V support. */ + pcie_bits = 0x30; + } + + ret = __mmc_send_if_cond(host, ocr, pcie_bits, &resp); + if (ret) + return 0; + + /* Continue with the SD express init, if the card supports it. */ + resp &= 0x3000; + if (pcie_bits && resp) { + if (resp == 0x3000) + host->ios.timing = MMC_TIMING_SD_EXP_1_2V; + else + host->ios.timing = MMC_TIMING_SD_EXP; + + /* + * According to the spec the clock shall also be gated, but + * let's leave this to the host driver for more flexibility. + */ + return host->ops->init_sd_express(host, &host->ios); + } + return 0; } diff --git a/drivers/mmc/core/sd_ops.h b/drivers/mmc/core/sd_ops.h index 2194cabfcfc5..3ba7b3cf4652 100644 --- a/drivers/mmc/core/sd_ops.h +++ b/drivers/mmc/core/sd_ops.h @@ -16,6 +16,7 @@ struct mmc_host; int mmc_app_set_bus_width(struct mmc_card *card, int width); int mmc_send_app_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr); int mmc_send_if_cond(struct mmc_host *host, u32 ocr); +int mmc_send_if_cond_pcie(struct mmc_host *host, u32 ocr); int mmc_send_relative_addr(struct mmc_host *host, unsigned int *rca); int mmc_app_send_scr(struct mmc_card *card); int mmc_sd_switch(struct mmc_card *card, int mode, int group, diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h index c079b932330f..01bba36545c5 100644 --- a/include/linux/mmc/host.h +++ b/include/linux/mmc/host.h @@ -60,6 +60,8 @@ struct mmc_ios { #define MMC_TIMING_MMC_DDR52 8 #define MMC_TIMING_MMC_HS200 9 #define MMC_TIMING_MMC_HS400 10 +#define MMC_TIMING_SD_EXP 11 +#define MMC_TIMING_SD_EXP_1_2V 12 unsigned char signal_voltage; /* signalling voltage (1.8V or 3.3V) */ @@ -173,6 +175,9 @@ struct mmc_host_ops { */ int (*multi_io_quirk)(struct mmc_card *card, unsigned int direction, int blk_size); + + /* Initialize an SD express card, mandatory for MMC_CAP2_SD_EXP. */ + int (*init_sd_express)(struct mmc_host *host, struct mmc_ios *ios); }; struct mmc_cqe_ops { @@ -358,6 +363,8 @@ struct mmc_host { #define MMC_CAP2_HS200_1_2V_SDR (1 << 6) /* can support */ #define MMC_CAP2_HS200 (MMC_CAP2_HS200_1_8V_SDR | \ MMC_CAP2_HS200_1_2V_SDR) +#define MMC_CAP2_SD_EXP (1 << 7) /* SD express via PCIe */ +#define MMC_CAP2_SD_EXP_1_2V (1 << 8) /* SD express 1.2V */ #define MMC_CAP2_CD_ACTIVE_HIGH (1 << 10) /* Card-detect signal active high */ #define MMC_CAP2_RO_ACTIVE_HIGH (1 << 11) /* Write-protect signal active high */ #define MMC_CAP2_NO_PRESCAN_POWERUP (1 << 14) /* Don't power up before scan */ From 5afe802132f242f5520d2acac09ea05d31e3c7cf Mon Sep 17 00:00:00 2001 From: Rui Feng Date: Thu, 29 Oct 2020 09:57:48 +0800 Subject: [PATCH 020/102] misc: rtsx: Add SD Express mode support for RTS5261 RTS5261 support SD mode and PCIe/NVMe mode. The workflow is as follows. 1.RTS5261 work in SD mode and set MMC_CAPS2_SD_EXP flag. 2.If card is plugged in, Host send CMD8 to ask card's PCIe availability. 3.If the card has PCIe availability and WP is not set, init_sd_express() will be invoked, RTS5261 switch to PCIe/NVMe mode. 4.Mmc driver handover it to NVMe driver. 5.If card is unplugged, RTS5261 will switch to SD mode. Signed-off-by: Rui Feng Acked-by: Greg Kroah-Hartman Link: https://lore.kernel.org/r/1603936668-3363-1-git-send-email-rui_feng@realsil.com.cn Signed-off-by: Ulf Hansson --- drivers/misc/cardreader/rts5261.c | 4 ++++ drivers/misc/cardreader/rts5261.h | 23 ----------------------- drivers/misc/cardreader/rtsx_pcr.c | 5 +++++ include/linux/rtsx_pci.h | 23 +++++++++++++++++++++++ 4 files changed, 32 insertions(+), 23 deletions(-) diff --git a/drivers/misc/cardreader/rts5261.c b/drivers/misc/cardreader/rts5261.c index 471961487ff8..536c90d4fd76 100644 --- a/drivers/misc/cardreader/rts5261.c +++ b/drivers/misc/cardreader/rts5261.c @@ -738,8 +738,12 @@ void rts5261_init_params(struct rtsx_pcr *pcr) { struct rtsx_cr_option *option = &pcr->option; struct rtsx_hw_param *hw_param = &pcr->hw_param; + u8 val; pcr->extra_caps = EXTRA_CAPS_SD_SDR50 | EXTRA_CAPS_SD_SDR104; + rtsx_pci_read_register(pcr, RTS5261_FW_STATUS, &val); + if (!(val & RTS5261_EXPRESS_LINK_FAIL_MASK)) + pcr->extra_caps |= EXTRA_CAPS_SD_EXPRESS; pcr->num_slots = 1; pcr->ops = &rts5261_pcr_ops; diff --git a/drivers/misc/cardreader/rts5261.h b/drivers/misc/cardreader/rts5261.h index ebfdd236a553..8d80f0d5d5d6 100644 --- a/drivers/misc/cardreader/rts5261.h +++ b/drivers/misc/cardreader/rts5261.h @@ -65,23 +65,6 @@ #define RTS5261_FW_EXPRESS_TEST_MASK (0x01<<0) #define RTS5261_FW_EA_MODE_MASK (0x01<<5) -/* FW config register */ -#define RTS5261_FW_CFG0 0xFF54 -#define RTS5261_FW_ENTER_EXPRESS (0x01<<0) - -#define RTS5261_FW_CFG1 0xFF55 -#define RTS5261_SYS_CLK_SEL_MCU_CLK (0x01<<7) -#define RTS5261_CRC_CLK_SEL_MCU_CLK (0x01<<6) -#define RTS5261_FAKE_MCU_CLOCK_GATING (0x01<<5) -/*MCU_bus_mode_sel: 0=real 8051 1=fake mcu*/ -#define RTS5261_MCU_BUS_SEL_MASK (0x01<<4) -/*MCU_clock_sel:VerA 00=aux16M 01=aux400K 1x=REFCLK100M*/ -/*MCU_clock_sel:VerB 00=aux400K 01=aux16M 10=REFCLK100M*/ -#define RTS5261_MCU_CLOCK_SEL_MASK (0x03<<2) -#define RTS5261_MCU_CLOCK_SEL_16M (0x01<<2) -#define RTS5261_MCU_CLOCK_GATING (0x01<<1) -#define RTS5261_DRIVER_ENABLE_FW (0x01<<0) - /* FW status register */ #define RTS5261_FW_STATUS 0xFF56 #define RTS5261_EXPRESS_LINK_FAIL_MASK (0x01<<7) @@ -121,12 +104,6 @@ #define RTS5261_DV3318_19 (0x04<<4) #define RTS5261_DV3318_33 (0x07<<4) -#define RTS5261_LDO1_CFG0 0xFF72 -#define RTS5261_LDO1_OCP_THD_MASK (0x07<<5) -#define RTS5261_LDO1_OCP_EN (0x01<<4) -#define RTS5261_LDO1_OCP_LMT_THD_MASK (0x03<<2) -#define RTS5261_LDO1_OCP_LMT_EN (0x01<<1) - /* CRD6603-433 190319 request changed */ #define RTS5261_LDO1_OCP_THD_740 (0x00<<5) #define RTS5261_LDO1_OCP_THD_800 (0x01<<5) diff --git a/drivers/misc/cardreader/rtsx_pcr.c b/drivers/misc/cardreader/rtsx_pcr.c index 5d15607027e9..56f63fa7f646 100644 --- a/drivers/misc/cardreader/rtsx_pcr.c +++ b/drivers/misc/cardreader/rtsx_pcr.c @@ -990,6 +990,11 @@ static irqreturn_t rtsx_pci_isr(int irq, void *dev_id) } else { pcr->card_removed |= SD_EXIST; pcr->card_inserted &= ~SD_EXIST; + if (PCI_PID(pcr) == PID_5261) { + rtsx_pci_write_register(pcr, RTS5261_FW_STATUS, + RTS5261_EXPRESS_LINK_FAIL_MASK, 0); + pcr->extra_caps |= EXTRA_CAPS_SD_EXPRESS; + } } pcr->dma_error_count = 0; } diff --git a/include/linux/rtsx_pci.h b/include/linux/rtsx_pci.h index 745f5e73f99a..b47959f48ccd 100644 --- a/include/linux/rtsx_pci.h +++ b/include/linux/rtsx_pci.h @@ -658,6 +658,19 @@ #define PM_WAKE_EN 0x01 #define PM_CTRL4 0xFF47 +#define RTS5261_FW_CFG0 0xFF54 +#define RTS5261_FW_ENTER_EXPRESS (0x01 << 0) + +#define RTS5261_FW_CFG1 0xFF55 +#define RTS5261_SYS_CLK_SEL_MCU_CLK (0x01 << 7) +#define RTS5261_CRC_CLK_SEL_MCU_CLK (0x01 << 6) +#define RTS5261_FAKE_MCU_CLOCK_GATING (0x01 << 5) +#define RTS5261_MCU_BUS_SEL_MASK (0x01 << 4) +#define RTS5261_MCU_CLOCK_SEL_MASK (0x03 << 2) +#define RTS5261_MCU_CLOCK_SEL_16M (0x01 << 2) +#define RTS5261_MCU_CLOCK_GATING (0x01 << 1) +#define RTS5261_DRIVER_ENABLE_FW (0x01 << 0) + #define REG_CFG_OOBS_OFF_TIMER 0xFEA6 #define REG_CFG_OOBS_ON_TIMER 0xFEA7 #define REG_CFG_VCM_ON_TIMER 0xFEA8 @@ -701,6 +714,13 @@ #define RTS5260_DVCC_TUNE_MASK 0x70 #define RTS5260_DVCC_33 0x70 +/*RTS5261*/ +#define RTS5261_LDO1_CFG0 0xFF72 +#define RTS5261_LDO1_OCP_THD_MASK (0x07 << 5) +#define RTS5261_LDO1_OCP_EN (0x01 << 4) +#define RTS5261_LDO1_OCP_LMT_THD_MASK (0x03 << 2) +#define RTS5261_LDO1_OCP_LMT_EN (0x01 << 1) + #define LDO_VCC_CFG1 0xFF73 #define LDO_VCC_REF_TUNE_MASK 0x30 #define LDO_VCC_REF_1V2 0x20 @@ -741,6 +761,8 @@ #define RTS5260_AUTOLOAD_CFG4 0xFF7F #define RTS5260_MIMO_DISABLE 0x8A +/*RTS5261*/ +#define RTS5261_AUX_CLK_16M_EN (1 << 5) #define RTS5260_REG_GPIO_CTL0 0xFC1A #define RTS5260_REG_GPIO_MASK 0x01 @@ -1191,6 +1213,7 @@ struct rtsx_pcr { #define EXTRA_CAPS_MMC_HS200 (1 << 4) #define EXTRA_CAPS_MMC_8BIT (1 << 5) #define EXTRA_CAPS_NO_MMC (1 << 7) +#define EXTRA_CAPS_SD_EXPRESS (1 << 8) u32 extra_caps; #define IC_VER_A 0 From 9ff43c7be9b417ed712de0f6a0918974f60beacf Mon Sep 17 00:00:00 2001 From: Rui Feng Date: Thu, 29 Oct 2020 09:58:23 +0800 Subject: [PATCH 021/102] mmc: rtsx_pci: Add SD Express mode support for RTS5261 RTS5261 support SD mode and PCIe/NVMe mode. The workflow is as follows. 1.RTS5261 work in SD mode and set MMC_CAPS2_SD_EXP flag. 2.If card is plugged in, Host send CMD8 to ask card's PCIe availability. 3.If the card has PCIe availability and WP is not set, init_sd_express() will be invoked, RTS5261 switch to PCIe/NVMe mode. 4.Mmc driver handover it to NVMe driver. 5.If card is unplugged, RTS5261 will switch to SD mode. Signed-off-by: Rui Feng Link: https://lore.kernel.org/r/1603936703-3403-1-git-send-email-rui_feng@realsil.com.cn Signed-off-by: Ulf Hansson --- drivers/mmc/host/rtsx_pci_sdmmc.c | 58 +++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/drivers/mmc/host/rtsx_pci_sdmmc.c b/drivers/mmc/host/rtsx_pci_sdmmc.c index eb395e144207..c584070b39fe 100644 --- a/drivers/mmc/host/rtsx_pci_sdmmc.c +++ b/drivers/mmc/host/rtsx_pci_sdmmc.c @@ -895,7 +895,9 @@ static int sd_set_bus_width(struct realtek_pci_sdmmc *host, static int sd_power_on(struct realtek_pci_sdmmc *host) { struct rtsx_pcr *pcr = host->pcr; + struct mmc_host *mmc = host->mmc; int err; + u32 val; if (host->power_state == SDMMC_POWER_ON) return 0; @@ -922,6 +924,21 @@ static int sd_power_on(struct realtek_pci_sdmmc *host) if (err < 0) return err; + if (PCI_PID(pcr) == PID_5261) { + if (pcr->extra_caps & EXTRA_CAPS_SD_EXPRESS) + mmc->caps2 |= MMC_CAP2_SD_EXP | MMC_CAP2_SD_EXP_1_2V; + /* + * HW read wp status when resuming from S3/S4, + * and then picks SD legacy interface if it's set + * in read-only mode. + */ + val = rtsx_pci_readl(pcr, RTSX_BIPR); + if (val & SD_WRITE_PROTECT) { + pcr->extra_caps &= ~EXTRA_CAPS_SD_EXPRESS; + mmc->caps2 &= ~(MMC_CAP2_SD_EXP | MMC_CAP2_SD_EXP_1_2V); + } + } + host->power_state = SDMMC_POWER_ON; return 0; } @@ -1308,6 +1325,44 @@ static int sdmmc_execute_tuning(struct mmc_host *mmc, u32 opcode) return err; } +static int sdmmc_init_sd_express(struct mmc_host *mmc, struct mmc_ios *ios) +{ + u32 relink_time; + struct realtek_pci_sdmmc *host = mmc_priv(mmc); + struct rtsx_pcr *pcr = host->pcr; + + /* Set relink_time for changing to PCIe card */ + relink_time = 0x8FFF; + + rtsx_pci_write_register(pcr, 0xFF01, 0xFF, relink_time); + rtsx_pci_write_register(pcr, 0xFF02, 0xFF, relink_time >> 8); + rtsx_pci_write_register(pcr, 0xFF03, 0x01, relink_time >> 16); + + rtsx_pci_write_register(pcr, PETXCFG, 0x80, 0x80); + rtsx_pci_write_register(pcr, LDO_VCC_CFG0, + RTS5261_LDO1_OCP_THD_MASK, + pcr->option.sd_800mA_ocp_thd); + + if (pcr->ops->disable_auto_blink) + pcr->ops->disable_auto_blink(pcr); + + /* For PCIe/NVMe mode can't enter delink issue */ + pcr->hw_param.interrupt_en &= ~(SD_INT_EN); + rtsx_pci_writel(pcr, RTSX_BIER, pcr->hw_param.interrupt_en); + + rtsx_pci_write_register(pcr, RTS5260_AUTOLOAD_CFG4, + RTS5261_AUX_CLK_16M_EN, RTS5261_AUX_CLK_16M_EN); + rtsx_pci_write_register(pcr, RTS5261_FW_CFG0, + RTS5261_FW_ENTER_EXPRESS, RTS5261_FW_ENTER_EXPRESS); + rtsx_pci_write_register(pcr, RTS5261_FW_CFG1, + RTS5261_MCU_BUS_SEL_MASK | RTS5261_MCU_CLOCK_SEL_MASK + | RTS5261_MCU_CLOCK_GATING | RTS5261_DRIVER_ENABLE_FW, + RTS5261_MCU_CLOCK_SEL_16M | RTS5261_MCU_CLOCK_GATING + | RTS5261_DRIVER_ENABLE_FW); + host->eject = true; + return 0; +} + static const struct mmc_host_ops realtek_pci_sdmmc_ops = { .pre_req = sdmmc_pre_req, .post_req = sdmmc_post_req, @@ -1317,6 +1372,7 @@ static const struct mmc_host_ops realtek_pci_sdmmc_ops = { .get_cd = sdmmc_get_cd, .start_signal_voltage_switch = sdmmc_switch_voltage, .execute_tuning = sdmmc_execute_tuning, + .init_sd_express = sdmmc_init_sd_express, }; static void init_extra_caps(struct realtek_pci_sdmmc *host) @@ -1338,6 +1394,8 @@ static void init_extra_caps(struct realtek_pci_sdmmc *host) mmc->caps |= MMC_CAP_8_BIT_DATA; if (pcr->extra_caps & EXTRA_CAPS_NO_MMC) mmc->caps2 |= MMC_CAP2_NO_MMC; + if (pcr->extra_caps & EXTRA_CAPS_SD_EXPRESS) + mmc->caps2 |= MMC_CAP2_SD_EXP | MMC_CAP2_SD_EXP_1_2V; } static void realtek_init_host(struct realtek_pci_sdmmc *host) From fb8298631b11ba81e4326f8a8e54505e8439d28d Mon Sep 17 00:00:00 2001 From: Tom Rix Date: Sat, 31 Oct 2020 07:25:05 -0700 Subject: [PATCH 022/102] memstick: jmb38x_ms: remove unneeded semicolon A semicolon is not needed after a switch statement. Signed-off-by: Tom Rix Link: https://lore.kernel.org/r/20201031142505.2139539-1-trix@redhat.com Signed-off-by: Ulf Hansson --- drivers/memstick/host/jmb38x_ms.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/memstick/host/jmb38x_ms.c b/drivers/memstick/host/jmb38x_ms.c index e83c3ada9389..f9a93b0565e1 100644 --- a/drivers/memstick/host/jmb38x_ms.c +++ b/drivers/memstick/host/jmb38x_ms.c @@ -748,7 +748,7 @@ static int jmb38x_ms_set_param(struct memstick_host *msh, clock_delay); host->ifmode = value; break; - }; + } return 0; } From 8c3c0aca1a0cef20ac739b63f26971849b0f453a Mon Sep 17 00:00:00 2001 From: Tom Rix Date: Sat, 31 Oct 2020 06:48:18 -0700 Subject: [PATCH 023/102] memstick: mspro_block: remove unneeded semicolon A semicolon is not needed after a switch statement. Signed-off-by: Tom Rix Link: https://lore.kernel.org/r/20201031134818.2135446-1-trix@redhat.com Signed-off-by: Ulf Hansson --- drivers/memstick/core/mspro_block.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/memstick/core/mspro_block.c b/drivers/memstick/core/mspro_block.c index cd6b8d4f2335..afb892e7ffc6 100644 --- a/drivers/memstick/core/mspro_block.c +++ b/drivers/memstick/core/mspro_block.c @@ -276,7 +276,7 @@ static const char *mspro_block_attr_name(unsigned char tag) return "attr_devinfo"; default: return NULL; - }; + } } typedef ssize_t (*sysfs_show_t)(struct device *dev, From a85344d347284cc3d81e8fc230788d3f82b9bb45 Mon Sep 17 00:00:00 2001 From: Tom Rix Date: Sat, 31 Oct 2020 07:27:56 -0700 Subject: [PATCH 024/102] memstick: tifm: remove unneeded semicolon A semicolon is not needed after a switch statement. Signed-off-by: Tom Rix Link: https://lore.kernel.org/r/20201031142756.2140029-1-trix@redhat.com Signed-off-by: Ulf Hansson --- drivers/memstick/host/tifm_ms.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/memstick/host/tifm_ms.c b/drivers/memstick/host/tifm_ms.c index 786e46798da2..57145374f6ac 100644 --- a/drivers/memstick/host/tifm_ms.c +++ b/drivers/memstick/host/tifm_ms.c @@ -528,7 +528,7 @@ static int tifm_ms_set_param(struct memstick_host *msh, } else return -EINVAL; break; - }; + } return 0; } From 86d9bf50af08ab696c3f29a30cfb0b04cc59a78c Mon Sep 17 00:00:00 2001 From: Tom Rix Date: Sat, 31 Oct 2020 08:27:08 -0700 Subject: [PATCH 025/102] mmc: davinci: remove unneeded semicolon A semicolon is not needed after a switch statement. Signed-off-by: Tom Rix Link: https://lore.kernel.org/r/20201031152708.2146690-1-trix@redhat.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/davinci_mmc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mmc/host/davinci_mmc.c b/drivers/mmc/host/davinci_mmc.c index 90cd179625fc..2a757c88f9d2 100644 --- a/drivers/mmc/host/davinci_mmc.c +++ b/drivers/mmc/host/davinci_mmc.c @@ -290,7 +290,7 @@ static void mmc_davinci_start_command(struct mmc_davinci_host *host, default: s = ", (R? response)"; break; - }; s; })); + } s; })); host->cmd = cmd; switch (mmc_resp_type(cmd)) { From 120ae805fbb96424ecf28bda3a0316faa3361a3e Mon Sep 17 00:00:00 2001 From: Tian Tao Date: Fri, 30 Oct 2020 09:28:39 +0800 Subject: [PATCH 026/102] mmc: moxart: replace spin_lock_irqsave by spin_lock in hard IRQ The code has been in a irq-disabled context since it is hard IRQ. There is no necessity to do it again. Signed-off-by: Tian Tao Link: https://lore.kernel.org/r/1604021319-31338-1-git-send-email-tiantao6@hisilicon.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/moxart-mmc.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/mmc/host/moxart-mmc.c b/drivers/mmc/host/moxart-mmc.c index f25079ba3bca..89bff4e8ec10 100644 --- a/drivers/mmc/host/moxart-mmc.c +++ b/drivers/mmc/host/moxart-mmc.c @@ -465,9 +465,8 @@ static irqreturn_t moxart_irq(int irq, void *devid) { struct moxart_host *host = (struct moxart_host *)devid; u32 status; - unsigned long flags; - spin_lock_irqsave(&host->lock, flags); + spin_lock(&host->lock); status = readl(host->base + REG_STATUS); if (status & CARD_CHANGE) { @@ -484,7 +483,7 @@ static irqreturn_t moxart_irq(int irq, void *devid) if (status & (FIFO_ORUN | FIFO_URUN) && host->mrq) moxart_transfer_pio(host); - spin_unlock_irqrestore(&host->lock, flags); + spin_unlock(&host->lock); return IRQ_HANDLED; } From 291a81c3b0610c5dc4689d13e94b8557069788fe Mon Sep 17 00:00:00 2001 From: Tian Tao Date: Tue, 3 Nov 2020 11:48:43 +0800 Subject: [PATCH 027/102] mmc: meson-mx-sdio: replace spin_lock_irqsave by spin_lock in hard IRQ The code has been in a irq-disabled context since it is hard IRQ. There is no necessity to do it again. Signed-off-by: Tian Tao Reviewed-by: Jerome Brunet Link: https://lore.kernel.org/r/1604375323-33556-1-git-send-email-tiantao6@hisilicon.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/meson-mx-sdio.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/mmc/host/meson-mx-sdio.c b/drivers/mmc/host/meson-mx-sdio.c index 1c5299cd0cbe..d4a48916bfb6 100644 --- a/drivers/mmc/host/meson-mx-sdio.c +++ b/drivers/mmc/host/meson-mx-sdio.c @@ -418,10 +418,9 @@ static irqreturn_t meson_mx_mmc_irq(int irq, void *data) { struct meson_mx_mmc_host *host = (void *) data; u32 irqs, send; - unsigned long irqflags; irqreturn_t ret; - spin_lock_irqsave(&host->irq_lock, irqflags); + spin_lock(&host->irq_lock); irqs = readl(host->base + MESON_MX_SDIO_IRQS); send = readl(host->base + MESON_MX_SDIO_SEND); @@ -434,7 +433,7 @@ static irqreturn_t meson_mx_mmc_irq(int irq, void *data) /* finally ACK all pending interrupts */ writel(irqs, host->base + MESON_MX_SDIO_IRQS); - spin_unlock_irqrestore(&host->irq_lock, irqflags); + spin_unlock(&host->irq_lock); return ret; } From fa4c9a497c2cdc6d398cbde146c1358d006f6608 Mon Sep 17 00:00:00 2001 From: Tian Tao Date: Mon, 2 Nov 2020 08:52:17 +0800 Subject: [PATCH 028/102] mmc: owl-mmc: replace spin_lock_irqsave by spin_lock in hard IRQ The code has been in a irq-disabled context since it is hard IRQ. There is no necessity to do it again. Signed-off-by: Tian Tao Reviewed-by: Manivannan Sadhasivam Link: https://lore.kernel.org/r/1604278337-55624-1-git-send-email-tiantao6@hisilicon.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/owl-mmc.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/mmc/host/owl-mmc.c b/drivers/mmc/host/owl-mmc.c index ccf214a89eda..82d2bad577ca 100644 --- a/drivers/mmc/host/owl-mmc.c +++ b/drivers/mmc/host/owl-mmc.c @@ -134,10 +134,9 @@ static void owl_mmc_update_reg(void __iomem *reg, unsigned int val, bool state) static irqreturn_t owl_irq_handler(int irq, void *devid) { struct owl_mmc_host *owl_host = devid; - unsigned long flags; u32 state; - spin_lock_irqsave(&owl_host->lock, flags); + spin_lock(&owl_host->lock); state = readl(owl_host->base + OWL_REG_SD_STATE); if (state & OWL_SD_STATE_TEI) { @@ -147,7 +146,7 @@ static irqreturn_t owl_irq_handler(int irq, void *devid) complete(&owl_host->sdc_complete); } - spin_unlock_irqrestore(&owl_host->lock, flags); + spin_unlock(&owl_host->lock); return IRQ_HANDLED; } From 13b4e1e92411d4f375c7ffe1b72abb162369ab53 Mon Sep 17 00:00:00 2001 From: Wenbin Mei Date: Mon, 2 Nov 2020 17:28:22 +0800 Subject: [PATCH 029/102] mmc: mediatek: add HS400 enhanced strobe support Add support for HS400ES mode to MediaTek MMC Card Driver. Signed-off-by: Wenbin Mei Link: https://lore.kernel.org/r/20201102092822.5301-2-wenbin.mei@mediatek.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/mtk-sd.c | 40 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/drivers/mmc/host/mtk-sd.c b/drivers/mmc/host/mtk-sd.c index f7f68623fefc..fc5ee5df91ad 100644 --- a/drivers/mmc/host/mtk-sd.c +++ b/drivers/mmc/host/mtk-sd.c @@ -78,9 +78,12 @@ #define MSDC_PAD_TUNE0 0xf0 #define PAD_DS_TUNE 0x188 #define PAD_CMD_TUNE 0x18c +#define EMMC51_CFG0 0x204 #define EMMC50_CFG0 0x208 +#define EMMC50_CFG1 0x20c #define EMMC50_CFG3 0x220 #define SDC_FIFO_CFG 0x228 +#define CQHCI_SETTING 0x7fc /*--------------------------------------------------------------------------*/ /* Top Pad Register Offset */ @@ -261,15 +264,26 @@ #define PAD_CMD_TUNE_RX_DLY3 (0x1f << 1) /* RW */ +/* EMMC51_CFG0 mask */ +#define CMDQ_RDAT_CNT (0x3ff << 12) /* RW */ + #define EMMC50_CFG_PADCMD_LATCHCK (0x1 << 0) /* RW */ #define EMMC50_CFG_CRCSTS_EDGE (0x1 << 3) /* RW */ #define EMMC50_CFG_CFCSTS_SEL (0x1 << 4) /* RW */ +#define EMMC50_CFG_CMD_RESP_SEL (0x1 << 9) /* RW */ + +/* EMMC50_CFG1 mask */ +#define EMMC50_CFG1_DS_CFG (0x1 << 28) /* RW */ #define EMMC50_CFG3_OUTS_WR (0x1f << 0) /* RW */ #define SDC_FIFO_CFG_WRVALIDSEL (0x1 << 24) /* RW */ #define SDC_FIFO_CFG_RDVALIDSEL (0x1 << 25) /* RW */ +/* CQHCI_SETTING */ +#define CQHCI_RD_CMD_WND_SEL (0x1 << 14) /* RW */ +#define CQHCI_WR_CMD_WND_SEL (0x1 << 15) /* RW */ + /* EMMC_TOP_CONTROL mask */ #define PAD_RXDLY_SEL (0x1 << 0) /* RW */ #define DELAY_EN (0x1 << 1) /* RW */ @@ -2276,6 +2290,31 @@ static int msdc_get_cd(struct mmc_host *mmc) return !val; } +static void msdc_hs400_enhanced_strobe(struct mmc_host *mmc, + struct mmc_ios *ios) +{ + struct msdc_host *host = mmc_priv(mmc); + + if (ios->enhanced_strobe) { + msdc_prepare_hs400_tuning(mmc, ios); + sdr_set_field(host->base + EMMC50_CFG0, EMMC50_CFG_PADCMD_LATCHCK, 1); + sdr_set_field(host->base + EMMC50_CFG0, EMMC50_CFG_CMD_RESP_SEL, 1); + sdr_set_field(host->base + EMMC50_CFG1, EMMC50_CFG1_DS_CFG, 1); + + sdr_clr_bits(host->base + CQHCI_SETTING, CQHCI_RD_CMD_WND_SEL); + sdr_clr_bits(host->base + CQHCI_SETTING, CQHCI_WR_CMD_WND_SEL); + sdr_clr_bits(host->base + EMMC51_CFG0, CMDQ_RDAT_CNT); + } else { + sdr_set_field(host->base + EMMC50_CFG0, EMMC50_CFG_PADCMD_LATCHCK, 0); + sdr_set_field(host->base + EMMC50_CFG0, EMMC50_CFG_CMD_RESP_SEL, 0); + sdr_set_field(host->base + EMMC50_CFG1, EMMC50_CFG1_DS_CFG, 0); + + sdr_set_bits(host->base + CQHCI_SETTING, CQHCI_RD_CMD_WND_SEL); + sdr_set_bits(host->base + CQHCI_SETTING, CQHCI_WR_CMD_WND_SEL); + sdr_set_field(host->base + EMMC51_CFG0, CMDQ_RDAT_CNT, 0xb4); + } +} + static void msdc_cqe_enable(struct mmc_host *mmc) { struct msdc_host *host = mmc_priv(mmc); @@ -2333,6 +2372,7 @@ static const struct mmc_host_ops mt_msdc_ops = { .set_ios = msdc_ops_set_ios, .get_ro = mmc_gpio_get_ro, .get_cd = msdc_get_cd, + .hs400_enhanced_strobe = msdc_hs400_enhanced_strobe, .enable_sdio_irq = msdc_enable_sdio_irq, .ack_sdio_irq = msdc_ack_sdio_irq, .start_signal_voltage_switch = msdc_ops_switch_volt, From 6b7b58f425c3359787483479d73c0bb98ffc65b8 Mon Sep 17 00:00:00 2001 From: Rui Feng Date: Tue, 3 Nov 2020 17:54:29 +0800 Subject: [PATCH 030/102] mmc: rtsx: Add test mode for RTS5261 This patch add test mode for RTS5261. If test mode is set, reader will switch to SD Express mode mandatorily, and this mode is used by factory testing only. Signed-off-by: Rui Feng Acked-by: Greg Kroah-Hartman Link: https://lore.kernel.org/r/1604397269-2780-1-git-send-email-rui_feng@realsil.com.cn Signed-off-by: Ulf Hansson --- drivers/misc/cardreader/rts5261.h | 5 ----- drivers/mmc/host/rtsx_pci_sdmmc.c | 19 ++++++++++++++++--- include/linux/rtsx_pci.h | 4 ++++ 3 files changed, 20 insertions(+), 8 deletions(-) diff --git a/drivers/misc/cardreader/rts5261.h b/drivers/misc/cardreader/rts5261.h index 8d80f0d5d5d6..80179353bc46 100644 --- a/drivers/misc/cardreader/rts5261.h +++ b/drivers/misc/cardreader/rts5261.h @@ -60,11 +60,6 @@ /* DMACTL 0xFE2C */ #define RTS5261_DMA_PACK_SIZE_MASK 0xF0 -/* FW config info register */ -#define RTS5261_FW_CFG_INFO0 0xFF50 -#define RTS5261_FW_EXPRESS_TEST_MASK (0x01<<0) -#define RTS5261_FW_EA_MODE_MASK (0x01<<5) - /* FW status register */ #define RTS5261_FW_STATUS 0xFF56 #define RTS5261_EXPRESS_LINK_FAIL_MASK (0x01<<7) diff --git a/drivers/mmc/host/rtsx_pci_sdmmc.c b/drivers/mmc/host/rtsx_pci_sdmmc.c index c584070b39fe..e9ea703f08c5 100644 --- a/drivers/mmc/host/rtsx_pci_sdmmc.c +++ b/drivers/mmc/host/rtsx_pci_sdmmc.c @@ -47,6 +47,8 @@ struct realtek_pci_sdmmc { bool using_cookie; }; +static int sdmmc_init_sd_express(struct mmc_host *mmc, struct mmc_ios *ios); + static inline struct device *sdmmc_dev(struct realtek_pci_sdmmc *host) { return &(host->pdev->dev); @@ -898,6 +900,7 @@ static int sd_power_on(struct realtek_pci_sdmmc *host) struct mmc_host *mmc = host->mmc; int err; u32 val; + u8 test_mode; if (host->power_state == SDMMC_POWER_ON) return 0; @@ -925,6 +928,15 @@ static int sd_power_on(struct realtek_pci_sdmmc *host) return err; if (PCI_PID(pcr) == PID_5261) { + /* + * If test mode is set switch to SD Express mandatorily, + * this is only for factory testing. + */ + rtsx_pci_read_register(pcr, RTS5261_FW_CFG_INFO0, &test_mode); + if (test_mode & RTS5261_FW_EXPRESS_TEST_MASK) { + sdmmc_init_sd_express(mmc, NULL); + return 0; + } if (pcr->extra_caps & EXTRA_CAPS_SD_EXPRESS) mmc->caps2 |= MMC_CAP2_SD_EXP | MMC_CAP2_SD_EXP_1_2V; /* @@ -1354,11 +1366,12 @@ static int sdmmc_init_sd_express(struct mmc_host *mmc, struct mmc_ios *ios) RTS5261_AUX_CLK_16M_EN, RTS5261_AUX_CLK_16M_EN); rtsx_pci_write_register(pcr, RTS5261_FW_CFG0, RTS5261_FW_ENTER_EXPRESS, RTS5261_FW_ENTER_EXPRESS); + rtsx_pci_write_register(pcr, RTS5261_FW_CFG1, + RTS5261_MCU_CLOCK_GATING, RTS5261_MCU_CLOCK_GATING); rtsx_pci_write_register(pcr, RTS5261_FW_CFG1, RTS5261_MCU_BUS_SEL_MASK | RTS5261_MCU_CLOCK_SEL_MASK - | RTS5261_MCU_CLOCK_GATING | RTS5261_DRIVER_ENABLE_FW, - RTS5261_MCU_CLOCK_SEL_16M | RTS5261_MCU_CLOCK_GATING - | RTS5261_DRIVER_ENABLE_FW); + | RTS5261_DRIVER_ENABLE_FW, + RTS5261_MCU_CLOCK_SEL_16M | RTS5261_DRIVER_ENABLE_FW); host->eject = true; return 0; } diff --git a/include/linux/rtsx_pci.h b/include/linux/rtsx_pci.h index b47959f48ccd..db249e8707f3 100644 --- a/include/linux/rtsx_pci.h +++ b/include/linux/rtsx_pci.h @@ -658,6 +658,10 @@ #define PM_WAKE_EN 0x01 #define PM_CTRL4 0xFF47 +/* FW config info register */ +#define RTS5261_FW_CFG_INFO0 0xFF50 +#define RTS5261_FW_EXPRESS_TEST_MASK (0x01 << 0) +#define RTS5261_FW_EA_MODE_MASK (0x01 << 5) #define RTS5261_FW_CFG0 0xFF54 #define RTS5261_FW_ENTER_EXPRESS (0x01 << 0) From c28e3fb28f87cc0dba915f1303f4d018686363b8 Mon Sep 17 00:00:00 2001 From: Rui Feng Date: Tue, 3 Nov 2020 17:54:38 +0800 Subject: [PATCH 031/102] misc: rtsx: Fix OCP function for RTS5261 This patch fix the bug that when there is over current but reader can't enable OCP. Signed-off-by: Rui Feng Acked-by: Greg Kroah-Hartman Link: https://lore.kernel.org/r/1604397278-2815-1-git-send-email-rui_feng@realsil.com.cn Signed-off-by: Ulf Hansson --- drivers/misc/cardreader/rts5261.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/misc/cardreader/rts5261.c b/drivers/misc/cardreader/rts5261.c index 536c90d4fd76..531bbaed7a12 100644 --- a/drivers/misc/cardreader/rts5261.c +++ b/drivers/misc/cardreader/rts5261.c @@ -272,6 +272,9 @@ static void rts5261_enable_ocp(struct rtsx_pcr *pcr) u8 val = 0; val = SD_OCP_INT_EN | SD_DETECT_EN; + rtsx_pci_write_register(pcr, RTS5261_LDO1_CFG0, + RTS5261_LDO1_OCP_EN | RTS5261_LDO1_OCP_LMT_EN, + RTS5261_LDO1_OCP_EN | RTS5261_LDO1_OCP_LMT_EN); rtsx_pci_write_register(pcr, REG_OCPCTL, 0xFF, val); } @@ -340,7 +343,7 @@ static void rts5261_clear_ocpstat(struct rtsx_pcr *pcr) rtsx_pci_write_register(pcr, REG_OCPCTL, mask, val); - udelay(10); + udelay(1000); rtsx_pci_write_register(pcr, REG_OCPCTL, mask, 0); } @@ -353,9 +356,9 @@ static void rts5261_process_ocp(struct rtsx_pcr *pcr) rtsx_pci_get_ocpstat(pcr, &pcr->ocp_stat); if (pcr->ocp_stat & (SD_OC_NOW | SD_OC_EVER)) { + rts5261_clear_ocpstat(pcr); rts5261_card_power_off(pcr, RTSX_SD_CARD); rtsx_pci_write_register(pcr, CARD_OE, SD_OUTPUT_EN, 0); - rts5261_clear_ocpstat(pcr); pcr->ocp_stat = 0; } @@ -513,6 +516,7 @@ static int rts5261_extra_init_hw(struct rtsx_pcr *pcr) rtsx_pci_write_register(pcr, PETXCFG, FORCE_CLKREQ_DELINK_MASK, FORCE_CLKREQ_HIGH); + rtsx_pci_write_register(pcr, PWD_SUSPEND_EN, 0xFF, 0xFB); rtsx_pci_write_register(pcr, pcr->reg_pm_ctrl3, 0x10, 0x00); rtsx_pci_write_register(pcr, RTS5261_REG_PME_FORCE_CTL, FORCE_PM_CONTROL | FORCE_PM_VALUE, FORCE_PM_CONTROL); From 0a3bbf92df7faf8b30c8e4560db5021bbf07766d Mon Sep 17 00:00:00 2001 From: Rui Feng Date: Tue, 3 Nov 2020 17:54:45 +0800 Subject: [PATCH 032/102] misc: rtsx: Fix aspm for RTS5261 This patch fix the bug that LDO is off when aspm is enabled. Signed-off-by: Rui Feng Acked-by: Greg Kroah-Hartman Link: https://lore.kernel.org/r/1604397285-2850-1-git-send-email-rui_feng@realsil.com.cn Signed-off-by: Ulf Hansson --- drivers/misc/cardreader/rts5261.c | 10 +++++++++- drivers/misc/cardreader/rts5261.h | 3 ++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/drivers/misc/cardreader/rts5261.c b/drivers/misc/cardreader/rts5261.c index 531bbaed7a12..3e30e542ef1a 100644 --- a/drivers/misc/cardreader/rts5261.c +++ b/drivers/misc/cardreader/rts5261.c @@ -530,22 +530,30 @@ static int rts5261_extra_init_hw(struct rtsx_pcr *pcr) static void rts5261_enable_aspm(struct rtsx_pcr *pcr, bool enable) { + u8 val = FORCE_ASPM_CTL0 | FORCE_ASPM_CTL1; + u8 mask = FORCE_ASPM_VAL_MASK | FORCE_ASPM_CTL0 | FORCE_ASPM_CTL1; + if (pcr->aspm_enabled == enable) return; + val |= (pcr->aspm_en & 0x02); + rtsx_pci_write_register(pcr, ASPM_FORCE_CTL, mask, val); pcie_capability_clear_and_set_word(pcr->pci, PCI_EXP_LNKCTL, PCI_EXP_LNKCTL_ASPMC, pcr->aspm_en); pcr->aspm_enabled = enable; - } static void rts5261_disable_aspm(struct rtsx_pcr *pcr, bool enable) { + u8 val = FORCE_ASPM_CTL0 | FORCE_ASPM_CTL1; + u8 mask = FORCE_ASPM_VAL_MASK | FORCE_ASPM_CTL0 | FORCE_ASPM_CTL1; + if (pcr->aspm_enabled == enable) return; pcie_capability_clear_and_set_word(pcr->pci, PCI_EXP_LNKCTL, PCI_EXP_LNKCTL_ASPMC, 0); + rtsx_pci_write_register(pcr, ASPM_FORCE_CTL, mask, val); rtsx_pci_write_register(pcr, SD_CFG1, SD_ASYNC_FIFO_NOT_RST, 0); udelay(10); pcr->aspm_enabled = enable; diff --git a/drivers/misc/cardreader/rts5261.h b/drivers/misc/cardreader/rts5261.h index 80179353bc46..cb98abb7c935 100644 --- a/drivers/misc/cardreader/rts5261.h +++ b/drivers/misc/cardreader/rts5261.h @@ -12,7 +12,8 @@ /*New add*/ #define rts5261_vendor_setting_valid(reg) ((reg) & 0x010000) -#define rts5261_reg_to_aspm(reg) (((reg) >> 28) ^ 0x03) +#define rts5261_reg_to_aspm(reg) \ + (((~(reg) >> 28) & 0x02) | (((reg) >> 28) & 0x01)) #define rts5261_reg_check_reverse_socket(reg) ((reg) & 0x04) #define rts5261_reg_to_card_drive_sel(reg) ((((reg) >> 6) & 0x01) << 6) #define rts5261_reg_to_sd30_drive_sel_1v8(reg) (((reg) >> 22) ^ 0x03) From 6f61dd284475a82e8224b16f4376a118e01e303b Mon Sep 17 00:00:00 2001 From: Rui Feng Date: Tue, 3 Nov 2020 17:54:51 +0800 Subject: [PATCH 033/102] misc: rtsx: Fix PAD driving for RTS5261 This patch fix PAD driving for RTS5261 Signed-off-by: Rui Feng Acked-by: Greg Kroah-Hartman Link: https://lore.kernel.org/r/1604397291-2885-1-git-send-email-rui_feng@realsil.com.cn Signed-off-by: Ulf Hansson --- drivers/misc/cardreader/rts5261.c | 15 ++++++--------- drivers/misc/cardreader/rts5261.h | 6 ++---- 2 files changed, 8 insertions(+), 13 deletions(-) diff --git a/drivers/misc/cardreader/rts5261.c b/drivers/misc/cardreader/rts5261.c index 3e30e542ef1a..b299e472e87b 100644 --- a/drivers/misc/cardreader/rts5261.c +++ b/drivers/misc/cardreader/rts5261.c @@ -26,16 +26,16 @@ static u8 rts5261_get_ic_version(struct rtsx_pcr *pcr) static void rts5261_fill_driving(struct rtsx_pcr *pcr, u8 voltage) { u8 driving_3v3[4][3] = { - {0x13, 0x13, 0x13}, + {0x96, 0x96, 0x96}, {0x96, 0x96, 0x96}, {0x7F, 0x7F, 0x7F}, - {0x96, 0x96, 0x96}, + {0x13, 0x13, 0x13}, }; u8 driving_1v8[4][3] = { - {0x99, 0x99, 0x99}, + {0xB3, 0xB3, 0xB3}, {0x3A, 0x3A, 0x3A}, {0xE6, 0xE6, 0xE6}, - {0xB3, 0xB3, 0xB3}, + {0x99, 0x99, 0x99}, }; u8 (*driving)[3], drive_sel; @@ -71,9 +71,6 @@ static void rtsx5261_fetch_vendor_settings(struct rtsx_pcr *pcr) return; } - pcr->card_drive_sel &= 0x3F; - pcr->card_drive_sel |= rts5261_reg_to_card_drive_sel(reg); - if (rts5261_reg_check_reverse_socket(reg)) pcr->flags |= PCR_REVERSE_SOCKET; @@ -761,8 +758,8 @@ void rts5261_init_params(struct rtsx_pcr *pcr) pcr->flags = 0; pcr->card_drive_sel = RTSX_CARD_DRIVE_DEFAULT; - pcr->sd30_drive_sel_1v8 = CFG_DRIVER_TYPE_B; - pcr->sd30_drive_sel_3v3 = CFG_DRIVER_TYPE_B; + pcr->sd30_drive_sel_1v8 = 0x00; + pcr->sd30_drive_sel_3v3 = 0x00; pcr->aspm_en = ASPM_L1_EN; pcr->tx_initial_phase = SET_CLOCK_PHASE(27, 27, 11); pcr->rx_initial_phase = SET_CLOCK_PHASE(24, 6, 5); diff --git a/drivers/misc/cardreader/rts5261.h b/drivers/misc/cardreader/rts5261.h index cb98abb7c935..2e47c798607b 100644 --- a/drivers/misc/cardreader/rts5261.h +++ b/drivers/misc/cardreader/rts5261.h @@ -15,10 +15,8 @@ #define rts5261_reg_to_aspm(reg) \ (((~(reg) >> 28) & 0x02) | (((reg) >> 28) & 0x01)) #define rts5261_reg_check_reverse_socket(reg) ((reg) & 0x04) -#define rts5261_reg_to_card_drive_sel(reg) ((((reg) >> 6) & 0x01) << 6) -#define rts5261_reg_to_sd30_drive_sel_1v8(reg) (((reg) >> 22) ^ 0x03) -#define rts5261_reg_to_sd30_drive_sel_3v3(reg) (((reg) >> 16) ^ 0x03) - +#define rts5261_reg_to_sd30_drive_sel_1v8(reg) (((reg) >> 22) & 0x03) +#define rts5261_reg_to_sd30_drive_sel_3v3(reg) (((reg) >> 16) & 0x03) #define RTS5261_AUTOLOAD_CFG0 0xFF7B #define RTS5261_AUTOLOAD_CFG1 0xFF7C From 5b0f429ede5af1e6da80d60a0b164346008e30ec Mon Sep 17 00:00:00 2001 From: Rui Feng Date: Tue, 3 Nov 2020 17:54:58 +0800 Subject: [PATCH 034/102] misc: rtsx: Check mmc support for RTS5261 This patch check mmc support when RTS5261 initialize, and not support mmc default. Signed-off-by: Rui Feng Acked-by: Greg Kroah-Hartman Link: https://lore.kernel.org/r/1604397298-2921-1-git-send-email-rui_feng@realsil.com.cn Signed-off-by: Ulf Hansson --- drivers/misc/cardreader/rts5261.c | 8 ++++++++ drivers/misc/cardreader/rts5261.h | 2 ++ 2 files changed, 10 insertions(+) diff --git a/drivers/misc/cardreader/rts5261.c b/drivers/misc/cardreader/rts5261.c index b299e472e87b..ce65c5703453 100644 --- a/drivers/misc/cardreader/rts5261.c +++ b/drivers/misc/cardreader/rts5261.c @@ -67,10 +67,18 @@ static void rtsx5261_fetch_vendor_settings(struct rtsx_pcr *pcr) pcr_dbg(pcr, "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG2, reg); if (!rts5261_vendor_setting_valid(reg)) { + /* Not support MMC default */ + pcr->extra_caps |= EXTRA_CAPS_NO_MMC; pcr_dbg(pcr, "skip fetch vendor setting\n"); return; } + if (!rts5261_reg_check_mmc_support(reg)) + pcr->extra_caps |= EXTRA_CAPS_NO_MMC; + + /* TO do: need to add rtd3 function */ + pcr->rtd3_en = rts5261_reg_to_rtd3(reg); + if (rts5261_reg_check_reverse_socket(reg)) pcr->flags |= PCR_REVERSE_SOCKET; diff --git a/drivers/misc/cardreader/rts5261.h b/drivers/misc/cardreader/rts5261.h index 2e47c798607b..2344c560a637 100644 --- a/drivers/misc/cardreader/rts5261.h +++ b/drivers/misc/cardreader/rts5261.h @@ -17,6 +17,8 @@ #define rts5261_reg_check_reverse_socket(reg) ((reg) & 0x04) #define rts5261_reg_to_sd30_drive_sel_1v8(reg) (((reg) >> 22) & 0x03) #define rts5261_reg_to_sd30_drive_sel_3v3(reg) (((reg) >> 16) & 0x03) +#define rts5261_reg_to_rtd3(reg) ((reg) & 0x08) +#define rts5261_reg_check_mmc_support(reg) ((reg) & 0x10) #define RTS5261_AUTOLOAD_CFG0 0xFF7B #define RTS5261_AUTOLOAD_CFG1 0xFF7C From 1da3c51512ce01dec42ad763421ab24c3dc1e3dd Mon Sep 17 00:00:00 2001 From: Rui Feng Date: Tue, 3 Nov 2020 17:55:05 +0800 Subject: [PATCH 035/102] misc: rtsx: Add CD & WP reverse support for RTS5261 This patch add CD & WP reverse support for RTS5261 Signed-off-by: Rui Feng Acked-by: Greg Kroah-Hartman Link: https://lore.kernel.org/r/1604397305-2956-1-git-send-email-rui_feng@realsil.com.cn Signed-off-by: Ulf Hansson --- drivers/misc/cardreader/rts5261.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/misc/cardreader/rts5261.c b/drivers/misc/cardreader/rts5261.c index ce65c5703453..0ef6b3e04a8d 100644 --- a/drivers/misc/cardreader/rts5261.c +++ b/drivers/misc/cardreader/rts5261.c @@ -510,6 +510,11 @@ static int rts5261_extra_init_hw(struct rtsx_pcr *pcr) /* Configure driving */ rts5261_fill_driving(pcr, OUTPUT_3V3); + if (pcr->flags & PCR_REVERSE_SOCKET) + rtsx_pci_write_register(pcr, PETXCFG, 0x30, 0x30); + else + rtsx_pci_write_register(pcr, PETXCFG, 0x30, 0x00); + /* * If u_force_clkreq_0 is enabled, CLKREQ# PIN will be forced * to drive low, and we forcibly request clock. From 1672617d512880f31d1d43ca0eb0d13d50b8c680 Mon Sep 17 00:00:00 2001 From: Rui Feng Date: Tue, 3 Nov 2020 17:55:12 +0800 Subject: [PATCH 036/102] misc: rtsx: Add hardware auto power off for RTS5261 This patch enable hardware auto power off when card is removed. Signed-off-by: Rui Feng Acked-by: Greg Kroah-Hartman Link: https://lore.kernel.org/r/1604397312-2991-1-git-send-email-rui_feng@realsil.com.cn Signed-off-by: Ulf Hansson --- drivers/misc/cardreader/rts5261.c | 9 +++++++++ include/linux/rtsx_pci.h | 3 +++ 2 files changed, 12 insertions(+) diff --git a/drivers/misc/cardreader/rts5261.c b/drivers/misc/cardreader/rts5261.c index 0ef6b3e04a8d..2ada973a0f33 100644 --- a/drivers/misc/cardreader/rts5261.c +++ b/drivers/misc/cardreader/rts5261.c @@ -176,6 +176,8 @@ static int rts5261_card_power_on(struct rtsx_pcr *pcr, int card) if (option->ocp_en) rtsx_pci_enable_ocp(pcr); + rtsx_pci_write_register(pcr, REG_CRC_DUMMY_0, + CFG_SD_POW_AUTO_PD, CFG_SD_POW_AUTO_PD); rtsx_pci_write_register(pcr, RTS5261_LDO1_CFG1, RTS5261_LDO1_TUNE_MASK, RTS5261_LDO1_33); @@ -303,6 +305,8 @@ static int rts5261_card_power_off(struct rtsx_pcr *pcr, int card) err = rtsx_pci_write_register(pcr, RTS5261_LDO1233318_POW_CTL, RTS5261_LDO_POWERON_MASK, 0); + rtsx_pci_write_register(pcr, REG_CRC_DUMMY_0, + CFG_SD_POW_AUTO_PD, 0); if (pcr->option.ocp_en) rtsx_pci_disable_ocp(pcr); @@ -475,6 +479,7 @@ static void rts5261_init_from_cfg(struct rtsx_pcr *pcr) static int rts5261_extra_init_hw(struct rtsx_pcr *pcr) { struct rtsx_cr_option *option = &pcr->option; + u32 val; rtsx_pci_write_register(pcr, RTS5261_AUTOLOAD_CFG1, CD_RESUME_EN_MASK, CD_RESUME_EN_MASK); @@ -489,6 +494,10 @@ static int rts5261_extra_init_hw(struct rtsx_pcr *pcr) AUX_CLK_ACTIVE_SEL_MASK, MAC_CKSW_DONE); rtsx_pci_write_register(pcr, L1SUB_CONFIG3, 0xFF, 0); + if (is_version_higher_than(pcr, PID_5261, IC_VER_B)) { + val = rtsx_pci_readl(pcr, RTSX_DUM_REG); + rtsx_pci_writel(pcr, RTSX_DUM_REG, val | 0x1); + } rtsx_pci_write_register(pcr, RTS5261_AUTOLOAD_CFG4, RTS5261_AUX_CLK_16M_EN, 0); diff --git a/include/linux/rtsx_pci.h b/include/linux/rtsx_pci.h index db249e8707f3..fcaadc7c9df1 100644 --- a/include/linux/rtsx_pci.h +++ b/include/linux/rtsx_pci.h @@ -82,6 +82,7 @@ #define MS_OC_INT_EN (1 << 23) #define SD_OC_INT_EN (1 << 22) +#define RTSX_DUM_REG 0x1C /* * macros for easy use @@ -1272,6 +1273,8 @@ struct rtsx_pcr { #define PCI_PID(pcr) ((pcr)->pci->device) #define is_version(pcr, pid, ver) \ (CHK_PCI_PID(pcr, pid) && (pcr)->ic_version == (ver)) +#define is_version_higher_than(pcr, pid, ver) \ + (CHK_PCI_PID(pcr, pid) && (pcr)->ic_version > (ver)) #define pcr_dbg(pcr, fmt, arg...) \ dev_dbg(&(pcr)->pci->dev, fmt, ##arg) From 5eefe22d223573a32afb9be7e53bff2acff6423a Mon Sep 17 00:00:00 2001 From: Rui Feng Date: Tue, 3 Nov 2020 17:55:21 +0800 Subject: [PATCH 037/102] misc: rtsx: Fix clock timing for RTS5261 This patch fix clock timing for RTS5261, using 256 divide for the version higher than version C. Signed-off-by: Rui Feng Acked-by: Greg Kroah-Hartman Link: https://lore.kernel.org/r/1604397321-3026-1-git-send-email-rui_feng@realsil.com.cn Signed-off-by: Ulf Hansson --- drivers/misc/cardreader/rts5261.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/misc/cardreader/rts5261.c b/drivers/misc/cardreader/rts5261.c index 2ada973a0f33..6c64dade8e1a 100644 --- a/drivers/misc/cardreader/rts5261.c +++ b/drivers/misc/cardreader/rts5261.c @@ -649,7 +649,7 @@ int rts5261_pci_switch_clock(struct rtsx_pcr *pcr, unsigned int card_clock, if (initial_mode) { /* We use 250k(around) here, in initial stage */ - if (is_version(pcr, PID_5261, IC_VER_D)) { + if (is_version_higher_than(pcr, PID_5261, IC_VER_C)) { clk_divider = SD_CLK_DIVIDE_256; card_clock = 60000000; } else { @@ -700,7 +700,7 @@ int rts5261_pci_switch_clock(struct rtsx_pcr *pcr, unsigned int card_clock, div++; } - n = (n / 2); + n = (n / 2) - 1; pcr_dbg(pcr, "n = %d, div = %d\n", n, div); ssc_depth = depth[ssc_depth]; From e2c01e9192758d0d011df1f4ed20eac2bdca2a3b Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Tue, 3 Nov 2020 17:30:46 +0100 Subject: [PATCH 038/102] mmc: meson-gx: drop of_match_ptr from of_device_id table MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The driver can match only via the DT table so the table should be always used and the of_match_ptr does not have any sense (this also allows ACPI matching via PRP0001, even though it is not relevant here). This fixes compile warning (!CONFIG_OF && !CONFIG_MODULES): drivers/mmc/host/meson-gx-mmc.c:1252:34: warning: ‘meson_mmc_of_match’ defined but not used [-Wunused-const-variable=] Reported-by: kernel test robot Signed-off-by: Krzysztof Kozlowski Acked-by: Kevin Hilman Link: https://lore.kernel.org/r/20201103163046.14336-1-krzk@kernel.org Signed-off-by: Ulf Hansson --- drivers/mmc/host/meson-gx-mmc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mmc/host/meson-gx-mmc.c b/drivers/mmc/host/meson-gx-mmc.c index 4ec41579940a..13f6a2c0ed04 100644 --- a/drivers/mmc/host/meson-gx-mmc.c +++ b/drivers/mmc/host/meson-gx-mmc.c @@ -1265,7 +1265,7 @@ static struct platform_driver meson_mmc_driver = { .driver = { .name = DRIVER_NAME, .probe_type = PROBE_PREFER_ASYNCHRONOUS, - .of_match_table = of_match_ptr(meson_mmc_of_match), + .of_match_table = meson_mmc_of_match, }, }; From 9f7d4c916c42ec310d17dc0ea8f4ebf64aa1bbf1 Mon Sep 17 00:00:00 2001 From: Tian Tao Date: Fri, 6 Nov 2020 09:56:53 +0800 Subject: [PATCH 039/102] mmc: dw_mmc: replace spin_lock_irqsave by spin_lock in hard IRQ The code has been in a irq-disabled context since it is hard IRQ. There is no necessity to do it again. Signed-off-by: Tian Tao Link: https://lore.kernel.org/r/1604627813-59785-1-git-send-email-tiantao6@hisilicon.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/dw_mmc.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index 43c5795691fb..a5244435556b 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c @@ -2617,7 +2617,6 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id) struct dw_mci *host = dev_id; u32 pending; struct dw_mci_slot *slot = host->slot; - unsigned long irqflags; pending = mci_readl(host, MINTSTS); /* read-only mask reg */ @@ -2632,15 +2631,15 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id) * Hold the lock; we know cmd11_timer can't be kicked * off after the lock is released, so safe to delete. */ - spin_lock_irqsave(&host->irq_lock, irqflags); + spin_lock(&host->irq_lock); dw_mci_cmd_interrupt(host, pending); - spin_unlock_irqrestore(&host->irq_lock, irqflags); + spin_unlock(&host->irq_lock); del_timer(&host->cmd11_timer); } if (pending & DW_MCI_CMD_ERROR_FLAGS) { - spin_lock_irqsave(&host->irq_lock, irqflags); + spin_lock(&host->irq_lock); del_timer(&host->cto_timer); mci_writel(host, RINTSTS, DW_MCI_CMD_ERROR_FLAGS); @@ -2648,7 +2647,7 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id) smp_wmb(); /* drain writebuffer */ set_bit(EVENT_CMD_COMPLETE, &host->pending_events); - spin_unlock_irqrestore(&host->irq_lock, irqflags); + spin_unlock(&host->irq_lock); } if (pending & DW_MCI_DATA_ERROR_FLAGS) { @@ -2661,7 +2660,7 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id) } if (pending & SDMMC_INT_DATA_OVER) { - spin_lock_irqsave(&host->irq_lock, irqflags); + spin_lock(&host->irq_lock); del_timer(&host->dto_timer); @@ -2676,7 +2675,7 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id) set_bit(EVENT_DATA_COMPLETE, &host->pending_events); tasklet_schedule(&host->tasklet); - spin_unlock_irqrestore(&host->irq_lock, irqflags); + spin_unlock(&host->irq_lock); } if (pending & SDMMC_INT_RXDR) { @@ -2692,12 +2691,12 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id) } if (pending & SDMMC_INT_CMD_DONE) { - spin_lock_irqsave(&host->irq_lock, irqflags); + spin_lock(&host->irq_lock); mci_writel(host, RINTSTS, SDMMC_INT_CMD_DONE); dw_mci_cmd_interrupt(host, pending); - spin_unlock_irqrestore(&host->irq_lock, irqflags); + spin_unlock(&host->irq_lock); } if (pending & SDMMC_INT_CD) { From c24aa7b160f558c5ca4f05168dfab021987601c9 Mon Sep 17 00:00:00 2001 From: Kaixu Xia Date: Sun, 8 Nov 2020 23:00:48 +0800 Subject: [PATCH 040/102] mmc: sdhci-pic32: Make pic32_sdhci_probe_platform() void pic32_sdhci_probe_platform() always returned 0, so there's no reason for a return value. In addition, pic32_sdhci_probe() checked the return value for possible error which is unnecessary. Convert pic32_sdhci_probe_platform() to a void function and remove the return value check. Fix the following Coccinelle warning: ./drivers/mmc/host/sdhci-pic32.c:127:5-8: Unneeded variable: "ret". Return "0" on line 137 Reported-by: Tosk Robot Signed-off-by: Kaixu Xia Link: https://lore.kernel.org/r/1604847648-13036-1-git-send-email-kaixuxia@tencent.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci-pic32.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/drivers/mmc/host/sdhci-pic32.c b/drivers/mmc/host/sdhci-pic32.c index 6ce1519ae177..6696b6bdd88e 100644 --- a/drivers/mmc/host/sdhci-pic32.c +++ b/drivers/mmc/host/sdhci-pic32.c @@ -121,10 +121,9 @@ static void pic32_sdhci_shared_bus(struct platform_device *pdev) writel(bus, host->ioaddr + SDH_SHARED_BUS_CTRL); } -static int pic32_sdhci_probe_platform(struct platform_device *pdev, +static void pic32_sdhci_probe_platform(struct platform_device *pdev, struct pic32_sdhci_priv *pdata) { - int ret = 0; u32 caps_slot_type; struct sdhci_host *host = platform_get_drvdata(pdev); @@ -133,8 +132,6 @@ static int pic32_sdhci_probe_platform(struct platform_device *pdev, caps_slot_type = (host->caps & SDH_CAPS_SDH_SLOT_TYPE_MASK) >> 30; if (caps_slot_type == SDH_SLOT_TYPE_SHARED_BUS) pic32_sdhci_shared_bus(pdev); - - return ret; } static int pic32_sdhci_probe(struct platform_device *pdev) @@ -193,11 +190,7 @@ static int pic32_sdhci_probe(struct platform_device *pdev) if (ret) goto err_base_clk; - ret = pic32_sdhci_probe_platform(pdev, sdhci_pdata); - if (ret) { - dev_err(&pdev->dev, "failed to probe platform!\n"); - goto err_base_clk; - } + pic32_sdhci_probe_platform(pdev, sdhci_pdata); ret = sdhci_add_host(host); if (ret) From 1f71b0bf4ef8992ae7749f917b6593fd902ec476 Mon Sep 17 00:00:00 2001 From: Zou Wei Date: Mon, 9 Nov 2020 10:25:06 +0800 Subject: [PATCH 041/102] mmc: owl-mmc: use true and false for bool variables Fix coccicheck warnings: ./owl-mmc.c:524:2-18: WARNING: Assignment of 0/1 to bool variable ./owl-mmc.c:528:2-18: WARNING: Assignment of 0/1 to bool variable Reported-by: Hulk Robot Signed-off-by: Zou Wei Link: https://lore.kernel.org/r/1604888706-63429-1-git-send-email-zou_wei@huawei.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/owl-mmc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/mmc/host/owl-mmc.c b/drivers/mmc/host/owl-mmc.c index 82d2bad577ca..53b81582f1af 100644 --- a/drivers/mmc/host/owl-mmc.c +++ b/drivers/mmc/host/owl-mmc.c @@ -521,11 +521,11 @@ static void owl_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) /* Enable DDR mode if requested */ if (ios->timing == MMC_TIMING_UHS_DDR50) { - owl_host->ddr_50 = 1; + owl_host->ddr_50 = true; owl_mmc_update_reg(owl_host->base + OWL_REG_SD_EN, OWL_SD_EN_DDREN, true); } else { - owl_host->ddr_50 = 0; + owl_host->ddr_50 = false; } } From 45bffc371fefd8537804b001080a47c6b69d5efa Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Tue, 10 Nov 2020 15:20:55 +0100 Subject: [PATCH 042/102] mmc: renesas_sdhi: only reset SCC when its pointer is populated MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Only re-initialize SCC and tuning when an SCC was found during probe(). This is currently a noop because all R-Car Gen2+ are considered to have an SCC. But this will change in a later patch, so we need this preparation. Signed-off-by: Wolfram Sang Reviewed-by: Niklas Söderlund Reviewed-by: Yoshihiro Shimoda Tested-by: Yoshihiro Shimoda Link: https://lore.kernel.org/r/20201110142058.36393-2-wsa+renesas@sang-engineering.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/renesas_sdhi_core.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/drivers/mmc/host/renesas_sdhi_core.c b/drivers/mmc/host/renesas_sdhi_core.c index acb9c81a4e45..a395f835e836 100644 --- a/drivers/mmc/host/renesas_sdhi_core.c +++ b/drivers/mmc/host/renesas_sdhi_core.c @@ -556,16 +556,18 @@ static void renesas_sdhi_reset(struct tmio_mmc_host *host) { struct renesas_sdhi *priv = host_to_priv(host); - renesas_sdhi_reset_scc(host, priv); - renesas_sdhi_reset_hs400_mode(host, priv); - priv->needs_adjust_hs400 = false; + if (priv->scc_ctl) { + renesas_sdhi_reset_scc(host, priv); + renesas_sdhi_reset_hs400_mode(host, priv); + priv->needs_adjust_hs400 = false; - sd_ctrl_write16(host, CTL_SD_CARD_CLK_CTL, CLK_CTL_SCLKEN | - sd_ctrl_read16(host, CTL_SD_CARD_CLK_CTL)); + sd_ctrl_write16(host, CTL_SD_CARD_CLK_CTL, CLK_CTL_SCLKEN | + sd_ctrl_read16(host, CTL_SD_CARD_CLK_CTL)); - sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_RVSCNTL, - ~SH_MOBILE_SDHI_SCC_RVSCNTL_RVSEN & - sd_scc_read32(host, priv, SH_MOBILE_SDHI_SCC_RVSCNTL)); + sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_RVSCNTL, + ~SH_MOBILE_SDHI_SCC_RVSCNTL_RVSEN & + sd_scc_read32(host, priv, SH_MOBILE_SDHI_SCC_RVSCNTL)); + } if (host->pdata->flags & TMIO_MMC_MIN_RCAR2) sd_ctrl_write32_as_16_and_16(host, CTL_IRQ_MASK, From b161d87dfd3d9f3fb064a089a9e521d0e5d3e38f Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Tue, 10 Nov 2020 15:20:56 +0100 Subject: [PATCH 043/102] mmc: renesas_sdhi: probe into TMIO after SCC parameters have been setup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Setting up the SCC parameters does not need a probed TMIO device. But in the near future, probing the TMIO device needs the SCC parameters setup. So, fix the ordering. Signed-off-by: Wolfram Sang Reviewed-by: Niklas Söderlund Reviewed-by: Yoshihiro Shimoda Tested-by: Yoshihiro Shimoda Link: https://lore.kernel.org/r/20201110142058.36393-3-wsa+renesas@sang-engineering.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/renesas_sdhi_core.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/mmc/host/renesas_sdhi_core.c b/drivers/mmc/host/renesas_sdhi_core.c index a395f835e836..17ebaa324ca1 100644 --- a/drivers/mmc/host/renesas_sdhi_core.c +++ b/drivers/mmc/host/renesas_sdhi_core.c @@ -1067,10 +1067,6 @@ int renesas_sdhi_probe(struct platform_device *pdev, quirks->hs400_calib_table + 1); } - ret = tmio_mmc_host_probe(host); - if (ret < 0) - goto edisclk; - /* Enable tuning iff we have an SCC and a supported mode */ if (of_data && of_data->scc_offset && (host->mmc->caps & MMC_CAP_UHS_SDR104 || @@ -1102,6 +1098,10 @@ int renesas_sdhi_probe(struct platform_device *pdev, host->ops.hs400_complete = renesas_sdhi_hs400_complete; } + ret = tmio_mmc_host_probe(host); + if (ret < 0) + goto edisclk; + num_irqs = platform_irq_count(pdev); if (num_irqs < 0) { ret = num_irqs; From d14ac691bb6f6ebaa7eeec21ca04dd47300ff5b6 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Tue, 10 Nov 2020 15:20:57 +0100 Subject: [PATCH 044/102] mmc: renesas_sdhi: populate SCC pointer at the proper place MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The SCC pointer is currently filled whenever the SoC is Gen2+. This is wrong because there is a Gen2-variant without SCC (SDHI_VER_GEN2_SDR50). We have been lucky because the writes to unintended registers have not caused problems so far. But further refactoring work exposed the problem. So, move the pointer initialization to the place where we know that the SDHI instance supports tuning. And also populate the 'reset' pointer unconditionally to make sure the interrupt enable register is always properly set for Gen2+. Signed-off-by: Wolfram Sang Reviewed-by: Niklas Söderlund Reviewed-by: Yoshihiro Shimoda Tested-by: Yoshihiro Shimoda Link: https://lore.kernel.org/r/20201110142058.36393-4-wsa+renesas@sang-engineering.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/renesas_sdhi_core.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/mmc/host/renesas_sdhi_core.c b/drivers/mmc/host/renesas_sdhi_core.c index 17ebaa324ca1..4a1ed5bf216c 100644 --- a/drivers/mmc/host/renesas_sdhi_core.c +++ b/drivers/mmc/host/renesas_sdhi_core.c @@ -1007,11 +1007,7 @@ int renesas_sdhi_probe(struct platform_device *pdev, host->ops.start_signal_voltage_switch = renesas_sdhi_start_signal_voltage_switch; host->sdcard_irq_setbit_mask = TMIO_STAT_ALWAYS_SET_27; - - if (of_data && of_data->scc_offset) { - priv->scc_ctl = host->ctl + of_data->scc_offset; - host->reset = renesas_sdhi_reset; - } + host->reset = renesas_sdhi_reset; } /* Orginally registers were 16 bit apart, could be 32 or 64 nowadays */ @@ -1091,6 +1087,7 @@ int renesas_sdhi_probe(struct platform_device *pdev, if (!hit) dev_warn(&host->pdev->dev, "Unknown clock rate for tuning\n"); + priv->scc_ctl = host->ctl + of_data->scc_offset; host->check_retune = renesas_sdhi_check_scc_error; host->ops.execute_tuning = renesas_sdhi_execute_tuning; host->ops.prepare_hs400_tuning = renesas_sdhi_prepare_hs400_tuning; From 9f809065d86dec2070263acedaa5758f8c9e95a9 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Tue, 10 Nov 2020 15:20:58 +0100 Subject: [PATCH 045/102] mmc: renesas_sdhi: simplify reset routine a little MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The 'reset' pointer is only populated for Gen2+. So, we don't need to check for that flag inside the routine. Signed-off-by: Wolfram Sang Reviewed-by: Niklas Söderlund Reviewed-by: Yoshihiro Shimoda Tested-by: Yoshihiro Shimoda Link: https://lore.kernel.org/r/20201110142058.36393-5-wsa+renesas@sang-engineering.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/renesas_sdhi_core.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/mmc/host/renesas_sdhi_core.c b/drivers/mmc/host/renesas_sdhi_core.c index 4a1ed5bf216c..1fabf8c5773c 100644 --- a/drivers/mmc/host/renesas_sdhi_core.c +++ b/drivers/mmc/host/renesas_sdhi_core.c @@ -552,6 +552,7 @@ static int renesas_sdhi_prepare_hs400_tuning(struct mmc_host *mmc, struct mmc_io return 0; } +/* only populated for TMIO_MMC_MIN_RCAR2 */ static void renesas_sdhi_reset(struct tmio_mmc_host *host) { struct renesas_sdhi *priv = host_to_priv(host); @@ -569,9 +570,7 @@ static void renesas_sdhi_reset(struct tmio_mmc_host *host) sd_scc_read32(host, priv, SH_MOBILE_SDHI_SCC_RVSCNTL)); } - if (host->pdata->flags & TMIO_MMC_MIN_RCAR2) - sd_ctrl_write32_as_16_and_16(host, CTL_IRQ_MASK, - TMIO_MASK_INIT_RCAR2); + sd_ctrl_write32_as_16_and_16(host, CTL_IRQ_MASK, TMIO_MASK_INIT_RCAR2); } #define SH_MOBILE_SDHI_MIN_TAP_ROW 3 From 183edc060e6969a3afe83f663b534f6324fb7e3a Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Tue, 10 Nov 2020 17:21:49 +0100 Subject: [PATCH 046/102] mmc: renesas_sdhi: clear TAPEN when resetting, too MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We want to clear TAPEN in a software reset, too, to have a completely known state. Especially when we doing the initial reset during boot to clear previous firmware states. Signed-off-by: Wolfram Sang Tested-by: Niklas Söderlund Reviewed-by: Yoshihiro Shimoda Tested-by: Yoshihiro Shimoda Link: https://lore.kernel.org/r/20201110162151.37622-2-wsa+renesas@sang-engineering.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/renesas_sdhi_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mmc/host/renesas_sdhi_core.c b/drivers/mmc/host/renesas_sdhi_core.c index 1fabf8c5773c..476a0c0198c6 100644 --- a/drivers/mmc/host/renesas_sdhi_core.c +++ b/drivers/mmc/host/renesas_sdhi_core.c @@ -558,7 +558,7 @@ static void renesas_sdhi_reset(struct tmio_mmc_host *host) struct renesas_sdhi *priv = host_to_priv(host); if (priv->scc_ctl) { - renesas_sdhi_reset_scc(host, priv); + renesas_sdhi_disable_scc(host->mmc); renesas_sdhi_reset_hs400_mode(host, priv); priv->needs_adjust_hs400 = false; From 80d0be81102405f1172f9b017feef323e5931959 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Tue, 10 Nov 2020 17:21:50 +0100 Subject: [PATCH 047/102] mmc: renesas_sdhi: merge the SCC reset functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There is no user of renesas_sdhi_reset_scc() anymore, only renesas_sdhi_disable_scc() so merge these functions into one. I guess the seperation was cruft anyhow. The BSP doesn't have it anymore and I can't recall the reason we had it. Signed-off-by: Wolfram Sang Tested-by: Niklas Söderlund Reviewed-by: Yoshihiro Shimoda Tested-by: Yoshihiro Shimoda Link: https://lore.kernel.org/r/20201110162151.37622-3-wsa+renesas@sang-engineering.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/renesas_sdhi_core.c | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/drivers/mmc/host/renesas_sdhi_core.c b/drivers/mmc/host/renesas_sdhi_core.c index 476a0c0198c6..a77dc9b46041 100644 --- a/drivers/mmc/host/renesas_sdhi_core.c +++ b/drivers/mmc/host/renesas_sdhi_core.c @@ -424,9 +424,11 @@ static void renesas_sdhi_hs400_complete(struct mmc_host *mmc) priv->needs_adjust_hs400 = true; } -static void renesas_sdhi_reset_scc(struct tmio_mmc_host *host, - struct renesas_sdhi *priv) +static void renesas_sdhi_disable_scc(struct mmc_host *mmc) { + struct tmio_mmc_host *host = mmc_priv(mmc); + struct renesas_sdhi *priv = host_to_priv(host); + sd_ctrl_write16(host, CTL_SD_CARD_CLK_CTL, ~CLK_CTL_SCLKEN & sd_ctrl_read16(host, CTL_SD_CARD_CLK_CTL)); @@ -434,14 +436,6 @@ static void renesas_sdhi_reset_scc(struct tmio_mmc_host *host, ~SH_MOBILE_SDHI_SCC_CKSEL_DTSEL & sd_scc_read32(host, priv, SH_MOBILE_SDHI_SCC_CKSEL)); -} - -static void renesas_sdhi_disable_scc(struct mmc_host *mmc) -{ - struct tmio_mmc_host *host = mmc_priv(mmc); - struct renesas_sdhi *priv = host_to_priv(host); - - renesas_sdhi_reset_scc(host, priv); sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_DTCNTL, ~SH_MOBILE_SDHI_SCC_DTCNTL_TAPEN & From 8c8310a6c2a6b86edadf15d511f4c1b332516b21 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Tue, 10 Nov 2020 17:21:51 +0100 Subject: [PATCH 048/102] mmc: renesas_sdhi: remove superfluous SCLKEN MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit All previously called functions handle SCLKEN on their own, no need to enable it again in sdhi_reset(). Signed-off-by: Wolfram Sang Tested-by: Niklas Söderlund Reviewed-by: Yoshihiro Shimoda Tested-by: Yoshihiro Shimoda Link: https://lore.kernel.org/r/20201110162151.37622-4-wsa+renesas@sang-engineering.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/renesas_sdhi_core.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/mmc/host/renesas_sdhi_core.c b/drivers/mmc/host/renesas_sdhi_core.c index a77dc9b46041..25c6a1993f8e 100644 --- a/drivers/mmc/host/renesas_sdhi_core.c +++ b/drivers/mmc/host/renesas_sdhi_core.c @@ -556,9 +556,6 @@ static void renesas_sdhi_reset(struct tmio_mmc_host *host) renesas_sdhi_reset_hs400_mode(host, priv); priv->needs_adjust_hs400 = false; - sd_ctrl_write16(host, CTL_SD_CARD_CLK_CTL, CLK_CTL_SCLKEN | - sd_ctrl_read16(host, CTL_SD_CARD_CLK_CTL)); - sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_RVSCNTL, ~SH_MOBILE_SDHI_SCC_RVSCNTL_RVSEN & sd_scc_read32(host, priv, SH_MOBILE_SDHI_SCC_RVSCNTL)); From 4533c3eb893d8d6881f792a855fa5e11d5ddf0c2 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Wed, 11 Nov 2020 11:02:42 +0100 Subject: [PATCH 049/102] mmc: renesas_sdhi: improve HOST_MODE usage MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit HOST_MODE should have a CTL_ prefix, too. This makes the code more readable because we immediately know what it is. Also, remove the hardcoded values with something readable, too. Signed-off-by: Wolfram Sang Reviewed-by: Niklas Söderlund Reviewed-by: Yoshihiro Shimoda Link: https://lore.kernel.org/r/20201111100244.15823-2-wsa+renesas@sang-engineering.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/renesas_sdhi_core.c | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/drivers/mmc/host/renesas_sdhi_core.c b/drivers/mmc/host/renesas_sdhi_core.c index 25c6a1993f8e..b3eb0182c4af 100644 --- a/drivers/mmc/host/renesas_sdhi_core.c +++ b/drivers/mmc/host/renesas_sdhi_core.c @@ -39,7 +39,15 @@ #include "renesas_sdhi.h" #include "tmio_mmc.h" -#define HOST_MODE 0xe4 +#define CTL_HOST_MODE 0xe4 +#define HOST_MODE_GEN2_SDR50_WMODE BIT(0) +#define HOST_MODE_GEN2_SDR104_WMODE BIT(0) +#define HOST_MODE_GEN3_WMODE BIT(0) +#define HOST_MODE_GEN3_BUSWIDTH BIT(8) + +#define HOST_MODE_GEN3_16BIT HOST_MODE_GEN3_WMODE +#define HOST_MODE_GEN3_32BIT (HOST_MODE_GEN3_WMODE | HOST_MODE_GEN3_BUSWIDTH) +#define HOST_MODE_GEN3_64BIT 0 #define SDHI_VER_GEN2_SDR50 0x490c #define SDHI_VER_RZ_A1 0x820b @@ -60,26 +68,26 @@ static void renesas_sdhi_sdbuf_width(struct tmio_mmc_host *host, int width) */ switch (sd_ctrl_read16(host, CTL_VERSION)) { case SDHI_VER_GEN2_SDR50: - val = (width == 32) ? 0x0001 : 0x0000; + val = (width == 32) ? HOST_MODE_GEN2_SDR50_WMODE : 0; break; case SDHI_VER_GEN2_SDR104: - val = (width == 32) ? 0x0000 : 0x0001; + val = (width == 32) ? 0 : HOST_MODE_GEN2_SDR104_WMODE; break; case SDHI_VER_GEN3_SD: case SDHI_VER_GEN3_SDMMC: if (width == 64) - val = 0x0000; + val = HOST_MODE_GEN3_64BIT; else if (width == 32) - val = 0x0101; + val = HOST_MODE_GEN3_32BIT; else - val = 0x0001; + val = HOST_MODE_GEN3_16BIT; break; default: /* nothing to do */ return; } - sd_ctrl_write16(host, HOST_MODE, val); + sd_ctrl_write16(host, CTL_HOST_MODE, val); } static int renesas_sdhi_clk_enable(struct tmio_mmc_host *host) @@ -795,7 +803,7 @@ static int renesas_sdhi_write16_hook(struct tmio_mmc_host *host, int addr) case CTL_SD_MEM_CARD_OPT: case CTL_TRANSACTION_CTL: case CTL_DMA_ENABLE: - case HOST_MODE: + case CTL_HOST_MODE: if (host->pdata->flags & TMIO_MMC_HAVE_CBSY) bit = TMIO_STAT_CMD_BUSY; fallthrough; From 0e08a411585214360938022ca3f50a9f1cd91753 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Wed, 11 Nov 2020 11:02:43 +0100 Subject: [PATCH 050/102] mmc: renesas_sdhi: don't hardcode SDIF values MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use a macro to name the hardcoded values. Also, move the SDIF register definition into the SDHI driver because this is an SDHI extension. Signed-off-by: Wolfram Sang Reviewed-by: Niklas Söderlund Reviewed-by: Yoshihiro Shimoda Link: https://lore.kernel.org/r/20201111100244.15823-3-wsa+renesas@sang-engineering.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/renesas_sdhi_core.c | 7 +++++-- drivers/mmc/host/tmio_mmc.h | 1 - 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/mmc/host/renesas_sdhi_core.c b/drivers/mmc/host/renesas_sdhi_core.c index b3eb0182c4af..55633826d38c 100644 --- a/drivers/mmc/host/renesas_sdhi_core.c +++ b/drivers/mmc/host/renesas_sdhi_core.c @@ -49,6 +49,9 @@ #define HOST_MODE_GEN3_32BIT (HOST_MODE_GEN3_WMODE | HOST_MODE_GEN3_BUSWIDTH) #define HOST_MODE_GEN3_64BIT 0 +#define CTL_SDIF_MODE 0xe6 +#define SDIF_MODE_HS400 BIT(0) + #define SDHI_VER_GEN2_SDR50 0x490c #define SDHI_VER_RZ_A1 0x820b /* very old datasheets said 0x490c for SDR104, too. They are wrong! */ @@ -381,7 +384,7 @@ static void renesas_sdhi_hs400_complete(struct mmc_host *mmc) sd_ctrl_read16(host, CTL_SD_CARD_CLK_CTL)); /* Set HS400 mode */ - sd_ctrl_write16(host, CTL_SDIF_MODE, 0x0001 | + sd_ctrl_write16(host, CTL_SDIF_MODE, SDIF_MODE_HS400 | sd_ctrl_read16(host, CTL_SDIF_MODE)); sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_DT2FF, @@ -529,7 +532,7 @@ static void renesas_sdhi_reset_hs400_mode(struct tmio_mmc_host *host, sd_ctrl_read16(host, CTL_SD_CARD_CLK_CTL)); /* Reset HS400 mode */ - sd_ctrl_write16(host, CTL_SDIF_MODE, ~0x0001 & + sd_ctrl_write16(host, CTL_SDIF_MODE, ~SDIF_MODE_HS400 & sd_ctrl_read16(host, CTL_SDIF_MODE)); sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_DT2FF, priv->scc_tappos); diff --git a/drivers/mmc/host/tmio_mmc.h b/drivers/mmc/host/tmio_mmc.h index 9546e542619c..7ff41185896a 100644 --- a/drivers/mmc/host/tmio_mmc.h +++ b/drivers/mmc/host/tmio_mmc.h @@ -42,7 +42,6 @@ #define CTL_DMA_ENABLE 0xd8 #define CTL_RESET_SD 0xe0 #define CTL_VERSION 0xe2 -#define CTL_SDIF_MODE 0xe6 /* Definitions for values the CTL_STOP_INTERNAL_ACTION register can take */ #define TMIO_STOP_STP BIT(0) From ab07a1356043f07142ba351253904ef8c42ecd4f Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Wed, 11 Nov 2020 11:02:44 +0100 Subject: [PATCH 051/102] mmc: renesas_sdhi: sort includes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Better prevent double includes. Signed-off-by: Wolfram Sang Reviewed-by: Niklas Söderlund Reviewed-by: Yoshihiro Shimoda Link: https://lore.kernel.org/r/20201111100244.15823-4-wsa+renesas@sang-engineering.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/renesas_sdhi_core.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/mmc/host/renesas_sdhi_core.c b/drivers/mmc/host/renesas_sdhi_core.c index 55633826d38c..bb937411c2ec 100644 --- a/drivers/mmc/host/renesas_sdhi_core.c +++ b/drivers/mmc/host/renesas_sdhi_core.c @@ -18,22 +18,22 @@ * */ -#include #include -#include -#include -#include -#include -#include +#include +#include +#include #include #include #include -#include -#include -#include +#include +#include #include #include +#include +#include #include +#include +#include #include #include "renesas_sdhi.h" From bbba85fae44134e00c493705bd5604fd63958315 Mon Sep 17 00:00:00 2001 From: Zheng Liang Date: Thu, 12 Nov 2020 17:25:30 +0800 Subject: [PATCH 052/102] mmc: mediatek: fix mem leak in msdc_drv_probe It should use mmc_free_host to free mem in error patch of msdc_drv_probe. Reported-by: Hulk Robot Signed-off-by: Zheng Liang Reviewed-by: Chaotian Jing Link: https://lore.kernel.org/r/20201112092530.32446-1-zhengliang6@huawei.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/mtk-sd.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/mmc/host/mtk-sd.c b/drivers/mmc/host/mtk-sd.c index fc5ee5df91ad..eac7838e2dac 100644 --- a/drivers/mmc/host/mtk-sd.c +++ b/drivers/mmc/host/mtk-sd.c @@ -2504,8 +2504,10 @@ static int msdc_drv_probe(struct platform_device *pdev) host->reset = devm_reset_control_get_optional_exclusive(&pdev->dev, "hrst"); - if (IS_ERR(host->reset)) - return PTR_ERR(host->reset); + if (IS_ERR(host->reset)) { + ret = PTR_ERR(host->reset); + goto host_free; + } host->irq = platform_get_irq(pdev, 0); if (host->irq < 0) { From 8ffbfe43e903775832484c3ca9773ae07845d478 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Thu, 12 Nov 2020 20:36:36 +0300 Subject: [PATCH 053/102] mmc: sdhci-msm: detect if tassadar_dll is used by using core version Detect if tassadar_dll is required by using core version rather than just specifying it in the sdhci_msm_variant_info. Signed-off-by: Dmitry Baryshkov Cc: Veerabhadrarao Badiganti Reviewed-by: Veerabhadrarao Badiganti Link: https://lore.kernel.org/r/20201112173636.360186-1-dmitry.baryshkov@linaro.org Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci-msm.c | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c index 3451eb325513..9c7927b03253 100644 --- a/drivers/mmc/host/sdhci-msm.c +++ b/drivers/mmc/host/sdhci-msm.c @@ -248,7 +248,6 @@ struct sdhci_msm_variant_ops { struct sdhci_msm_variant_info { bool mci_removed; bool restore_dll_config; - bool uses_tassadar_dll; const struct sdhci_msm_variant_ops *var_ops; const struct sdhci_msm_offset *offset; }; @@ -2154,18 +2153,10 @@ static const struct sdhci_msm_variant_info sdm845_sdhci_var = { .offset = &sdhci_msm_v5_offset, }; -static const struct sdhci_msm_variant_info sm8250_sdhci_var = { - .mci_removed = true, - .uses_tassadar_dll = true, - .var_ops = &v5_var_ops, - .offset = &sdhci_msm_v5_offset, -}; - static const struct of_device_id sdhci_msm_dt_match[] = { {.compatible = "qcom,sdhci-msm-v4", .data = &sdhci_msm_mci_var}, {.compatible = "qcom,sdhci-msm-v5", .data = &sdhci_msm_v5_var}, {.compatible = "qcom,sdm845-sdhci", .data = &sdm845_sdhci_var}, - {.compatible = "qcom,sm8250-sdhci", .data = &sm8250_sdhci_var}, {.compatible = "qcom,sc7180-sdhci", .data = &sdm845_sdhci_var}, {}, }; @@ -2249,7 +2240,6 @@ static int sdhci_msm_probe(struct platform_device *pdev) msm_host->restore_dll_config = var_info->restore_dll_config; msm_host->var_ops = var_info->var_ops; msm_host->offset = var_info->offset; - msm_host->uses_tassadar_dll = var_info->uses_tassadar_dll; msm_offset = msm_host->offset; @@ -2396,6 +2386,9 @@ static int sdhci_msm_probe(struct platform_device *pdev) if (core_major == 1 && core_minor >= 0x49) msm_host->updated_ddr_cfg = true; + if (core_major == 1 && core_minor >= 0x71) + msm_host->uses_tassadar_dll = true; + ret = sdhci_msm_register_vreg(msm_host); if (ret) goto clk_disable; From fde71a3eeda2d285cfb7e09acb74f7b7964ab210 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Sat, 14 Nov 2020 12:08:19 +0000 Subject: [PATCH 054/102] mmc: host: Kconfig: fix spelling mistake "hardare" -> "hardware" There is a spelling mistake in the Kconfig file. Fix it. Signed-off-by: Colin Ian King Link: https://lore.kernel.org/r/20201114120819.416311-1-colin.king@canonical.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig index 310e546e5898..7324a61d7416 100644 --- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig @@ -664,7 +664,7 @@ config MMC_S3C_PIO config MMC_S3C_DMA bool "Use DMA transfers only" help - Use DMA to transfer data between memory and the hardare. + Use DMA to transfer data between memory and the hardware. Currently, the DMA support in this driver seems to not be working properly and needs to be debugged before this From fcc541fea394d67ad607ee41acfa891e79fe17a2 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Mon, 16 Nov 2020 14:22:06 +0100 Subject: [PATCH 055/102] mmc: sdhci: tegra: fix wrong unit with busy_timeout 'busy_timeout' is in msecs, not in jiffies. Use the correct factor. Fixes: 5e958e4aacf4 ("sdhci: tegra: Implement Tegra specific set_timeout callback") Signed-off-by: Wolfram Sang Acked-by: Sowjanya Komatineni Acked-by: Thierry Reding Link: https://lore.kernel.org/r/20201116132206.23518-1-wsa+renesas@sang-engineering.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci-tegra.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c index ed12aacb1c73..41d193fa77bb 100644 --- a/drivers/mmc/host/sdhci-tegra.c +++ b/drivers/mmc/host/sdhci-tegra.c @@ -1272,7 +1272,7 @@ static void tegra_sdhci_set_timeout(struct sdhci_host *host, * busy wait mode. */ val = sdhci_readl(host, SDHCI_TEGRA_VENDOR_MISC_CTRL); - if (cmd && cmd->busy_timeout >= 11 * HZ) + if (cmd && cmd->busy_timeout >= 11 * MSEC_PER_SEC) val |= SDHCI_MISC_CTRL_ERASE_TIMEOUT_LIMIT; else val &= ~SDHCI_MISC_CTRL_ERASE_TIMEOUT_LIMIT; From ade8e9d3fb9232ddfb87a4bc641b35b988d9757b Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Mon, 16 Nov 2020 17:42:52 +0100 Subject: [PATCH 056/102] mmc: tmio: do not print real IOMEM pointer Printing kernel pointers is discouraged because they might leak kernel memory layout. This fixes smatch warning: drivers/mmc/host/tmio_mmc.c:177 tmio_mmc_probe() warn: argument 3 to %08lx specifier is cast from pointer Reported-by: kernel test robot Reported-by: Dan Carpenter Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20201116164252.44078-1-krzk@kernel.org Signed-off-by: Ulf Hansson --- drivers/mmc/host/tmio_mmc.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/mmc/host/tmio_mmc.c b/drivers/mmc/host/tmio_mmc.c index d2d3b8df1bbe..b55a29c53d9c 100644 --- a/drivers/mmc/host/tmio_mmc.c +++ b/drivers/mmc/host/tmio_mmc.c @@ -174,8 +174,7 @@ static int tmio_mmc_probe(struct platform_device *pdev) if (ret) goto host_remove; - pr_info("%s at 0x%08lx irq %d\n", mmc_hostname(host->mmc), - (unsigned long)host->ctl, irq); + pr_info("%s at 0x%p irq %d\n", mmc_hostname(host->mmc), host->ctl, irq); return 0; From 854a22997ad5d6c9860a2d695c40cd4004151d5b Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Tue, 17 Nov 2020 08:37:50 -0300 Subject: [PATCH 057/102] mmc: sdhci-esdhc-imx: Convert the driver to DT-only Since 5.10-rc1 i.MX is a devicetree-only platform, so simplify the code by removing the unused non-DT support. Signed-off-by: Fabio Estevam Reviewed-by: Haibo Chen Link: https://lore.kernel.org/r/20201117113750.25053-1-festevam@gmail.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci-esdhc-imx.c | 91 +----------------------------- 1 file changed, 2 insertions(+), 89 deletions(-) diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c index fce8fa7e6b30..16ed19f47939 100644 --- a/drivers/mmc/host/sdhci-esdhc-imx.c +++ b/drivers/mmc/host/sdhci-esdhc-imx.c @@ -296,22 +296,6 @@ struct pltfm_imx_data { struct pm_qos_request pm_qos_req; }; -static const struct platform_device_id imx_esdhc_devtype[] = { - { - .name = "sdhci-esdhc-imx25", - .driver_data = (kernel_ulong_t) &esdhc_imx25_data, - }, { - .name = "sdhci-esdhc-imx35", - .driver_data = (kernel_ulong_t) &esdhc_imx35_data, - }, { - .name = "sdhci-esdhc-imx51", - .driver_data = (kernel_ulong_t) &esdhc_imx51_data, - }, { - /* sentinel */ - } -}; -MODULE_DEVICE_TABLE(platform, imx_esdhc_devtype); - static const struct of_device_id imx_esdhc_dt_ids[] = { { .compatible = "fsl,imx25-esdhc", .data = &esdhc_imx25_data, }, { .compatible = "fsl,imx35-esdhc", .data = &esdhc_imx35_data, }, @@ -1531,72 +1515,6 @@ sdhci_esdhc_imx_probe_dt(struct platform_device *pdev, } #endif -static int sdhci_esdhc_imx_probe_nondt(struct platform_device *pdev, - struct sdhci_host *host, - struct pltfm_imx_data *imx_data) -{ - struct esdhc_platform_data *boarddata = &imx_data->boarddata; - int err; - - if (!host->mmc->parent->platform_data) { - dev_err(mmc_dev(host->mmc), "no board data!\n"); - return -EINVAL; - } - - imx_data->boarddata = *((struct esdhc_platform_data *) - host->mmc->parent->platform_data); - /* write_protect */ - if (boarddata->wp_type == ESDHC_WP_GPIO) { - host->mmc->caps2 |= MMC_CAP2_RO_ACTIVE_HIGH; - - err = mmc_gpiod_request_ro(host->mmc, "wp", 0, 0); - if (err) { - dev_err(mmc_dev(host->mmc), - "failed to request write-protect gpio!\n"); - return err; - } - } - - /* card_detect */ - switch (boarddata->cd_type) { - case ESDHC_CD_GPIO: - err = mmc_gpiod_request_cd(host->mmc, "cd", 0, false, 0); - if (err) { - dev_err(mmc_dev(host->mmc), - "failed to request card-detect gpio!\n"); - return err; - } - fallthrough; - - case ESDHC_CD_CONTROLLER: - /* we have a working card_detect back */ - host->quirks &= ~SDHCI_QUIRK_BROKEN_CARD_DETECTION; - break; - - case ESDHC_CD_PERMANENT: - host->mmc->caps |= MMC_CAP_NONREMOVABLE; - break; - - case ESDHC_CD_NONE: - break; - } - - switch (boarddata->max_bus_width) { - case 8: - host->mmc->caps |= MMC_CAP_8_BIT_DATA | MMC_CAP_4_BIT_DATA; - break; - case 4: - host->mmc->caps |= MMC_CAP_4_BIT_DATA; - break; - case 1: - default: - host->quirks |= SDHCI_QUIRK_FORCE_1_BIT_DATA; - break; - } - - return 0; -} - static int sdhci_esdhc_imx_probe(struct platform_device *pdev) { const struct of_device_id *of_id = @@ -1616,8 +1534,7 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev) imx_data = sdhci_pltfm_priv(pltfm_host); - imx_data->socdata = of_id ? of_id->data : (struct esdhc_soc_data *) - pdev->id_entry->driver_data; + imx_data->socdata = of_id->data; if (imx_data->socdata->flags & ESDHC_FLAG_PMQOS) cpu_latency_qos_add_request(&imx_data->pm_qos_req, 0); @@ -1713,10 +1630,7 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev) goto disable_ahb_clk; } - if (of_id) - err = sdhci_esdhc_imx_probe_dt(pdev, host, imx_data); - else - err = sdhci_esdhc_imx_probe_nondt(pdev, host, imx_data); + err = sdhci_esdhc_imx_probe_dt(pdev, host, imx_data); if (err) goto disable_ahb_clk; @@ -1929,7 +1843,6 @@ static struct platform_driver sdhci_esdhc_imx_driver = { .of_match_table = imx_esdhc_dt_ids, .pm = &sdhci_esdhc_pmops, }, - .id_table = imx_esdhc_devtype, .probe = sdhci_esdhc_imx_probe, .remove = sdhci_esdhc_imx_remove, }; From 40e49564e189a81094fccac830818d6c89dde376 Mon Sep 17 00:00:00 2001 From: Masaharu Hayakawa Date: Tue, 17 Nov 2020 14:13:37 +0100 Subject: [PATCH 058/102] mmc: tmio: Fix command error processing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If some errors are detected at the same time as the access end interrupt, the access end interrupt was not cleared. Especially with DMA, because then the access end interrupt was never enabled and, thus, never cleared. Clear the interrupt register always when a command error occurs. Signed-off-by: Masaharu Hayakawa [saito: rebase to v5.4] Signed-off-by: Takeshi Saito [wsa: rebase and extension of the commit message] Signed-off-by: Wolfram Sang Reviewed-by: Niklas Söderlund Link: https://lore.kernel.org/r/20201117131337.35307-1-wsa+renesas@sang-engineering.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/tmio_mmc_core.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/mmc/host/tmio_mmc_core.c b/drivers/mmc/host/tmio_mmc_core.c index cb4149fd12e0..7f4a28125010 100644 --- a/drivers/mmc/host/tmio_mmc_core.c +++ b/drivers/mmc/host/tmio_mmc_core.c @@ -796,8 +796,10 @@ static void tmio_mmc_finish_request(struct tmio_mmc_host *host) spin_unlock_irqrestore(&host->lock, flags); - if (mrq->cmd->error || (mrq->data && mrq->data->error)) + if (mrq->cmd->error || (mrq->data && mrq->data->error)) { + tmio_mmc_ack_mmc_irqs(host, TMIO_MASK_IRQ); /* Clear all */ tmio_mmc_abort_dma(host); + } /* Error means retune, but executed command was still successful */ if (host->check_retune && host->check_retune(host)) From a96e6523d0162b75b01b13a9af7fb11ae2565fbf Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Fri, 20 Nov 2020 17:23:43 +0100 Subject: [PATCH 059/102] mmc: sdhci-sprd: drop of_match_ptr from of_device_id table MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The driver can match only via the DT table so the table should be always used and the of_match_ptr does not have any sense (this also allows ACPI matching via PRP0001, even though it is not relevant here). This fixes compile warning (!CONFIG_OF on x86_64): drivers/mmc/host/sdhci-sprd.c:723:34: warning: ‘sdhci_sprd_of_match’ defined but not used [-Wunused-const-variable=] Reported-by: kernel test robot Signed-off-by: Krzysztof Kozlowski Acked-by: Chunyan Zhang Link: https://lore.kernel.org/r/20201120162344.485921-1-krzk@kernel.org Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci-sprd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mmc/host/sdhci-sprd.c b/drivers/mmc/host/sdhci-sprd.c index 58109c5b53e2..f85171edabeb 100644 --- a/drivers/mmc/host/sdhci-sprd.c +++ b/drivers/mmc/host/sdhci-sprd.c @@ -788,7 +788,7 @@ static struct platform_driver sdhci_sprd_driver = { .driver = { .name = "sdhci_sprd_r11", .probe_type = PROBE_PREFER_ASYNCHRONOUS, - .of_match_table = of_match_ptr(sdhci_sprd_of_match), + .of_match_table = sdhci_sprd_of_match, .pm = &sdhci_sprd_pm_ops, }, }; From bf3023e6e863fb4c6607553708392de477d4983b Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Fri, 20 Nov 2020 17:23:44 +0100 Subject: [PATCH 060/102] mmc: sdhci-st: drop of_match_ptr from of_device_id table MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The driver can match only via the DT table so the table should be always used and the of_match_ptr does not have any sense (this also allows ACPI matching via PRP0001, even though it is not relevant here). This fixes compile warning (!CONFIG_OF on x86_64): drivers/mmc/host/sdhci-st.c:512:34: warning: ‘st_sdhci_match’ defined but not used [-Wunused-const-variable=] Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20201120162344.485921-2-krzk@kernel.org Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci-st.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mmc/host/sdhci-st.c b/drivers/mmc/host/sdhci-st.c index 4e9ff3e828ba..962872aec164 100644 --- a/drivers/mmc/host/sdhci-st.c +++ b/drivers/mmc/host/sdhci-st.c @@ -523,7 +523,7 @@ static struct platform_driver sdhci_st_driver = { .name = "sdhci-st", .probe_type = PROBE_PREFER_ASYNCHRONOUS, .pm = &sdhci_st_pmops, - .of_match_table = of_match_ptr(st_sdhci_match), + .of_match_table = st_sdhci_match, }, }; From e3e9ced5c93803d5b2ea1942c4bf0192622531d6 Mon Sep 17 00:00:00 2001 From: Qinglang Miao Date: Fri, 20 Nov 2020 15:48:46 +0800 Subject: [PATCH 061/102] memstick: fix a double-free bug in memstick_check kfree(host->card) has been called in put_device so that another kfree would raise cause a double-free bug. Fixes: 0193383a5833 ("memstick: core: fix device_register() error handling") Reported-by: Hulk Robot Signed-off-by: Qinglang Miao Link: https://lore.kernel.org/r/20201120074846.31322-1-miaoqinglang@huawei.com Signed-off-by: Ulf Hansson --- drivers/memstick/core/memstick.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/memstick/core/memstick.c b/drivers/memstick/core/memstick.c index ef03d6fafc5c..12bc3f5a6cbb 100644 --- a/drivers/memstick/core/memstick.c +++ b/drivers/memstick/core/memstick.c @@ -468,7 +468,6 @@ static void memstick_check(struct work_struct *work) host->card = card; if (device_register(&card->dev)) { put_device(&card->dev); - kfree(host->card); host->card = NULL; } } else From 2fd8a07886e00dd7b1c41cbc22911fad37fff639 Mon Sep 17 00:00:00 2001 From: Cristian Ciocaltea Date: Fri, 20 Nov 2020 01:56:02 +0200 Subject: [PATCH 062/102] dt-bindings: mmc: owl: Add compatible string for Actions Semi S500 SoC Add a new compatible string corresponding to the MMC controller found in the S500 variant of the Actions Semi Owl SoCs family. Signed-off-by: Cristian Ciocaltea Link: https://lore.kernel.org/r/713f57f4a66fff9a50a8d93643a7987d6560becb.1605823502.git.cristian.ciocaltea@gmail.com Signed-off-by: Ulf Hansson --- Documentation/devicetree/bindings/mmc/owl-mmc.yaml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/mmc/owl-mmc.yaml b/Documentation/devicetree/bindings/mmc/owl-mmc.yaml index b6ab527087d5..b0d81ebe0f6e 100644 --- a/Documentation/devicetree/bindings/mmc/owl-mmc.yaml +++ b/Documentation/devicetree/bindings/mmc/owl-mmc.yaml @@ -17,7 +17,9 @@ properties: oneOf: - const: actions,owl-mmc - items: - - const: actions,s700-mmc + - enum: + - actions,s500-mmc + - actions,s700-mmc - const: actions,owl-mmc reg: From c5b1c6dc13daec60405ecd31eaa5379a9f798fa8 Mon Sep 17 00:00:00 2001 From: Jeremy Linton Date: Fri, 20 Nov 2020 17:38:31 -0600 Subject: [PATCH 063/102] mmc: sdhci: Update firmware interface API The device_* calls were added a few years ago to abstract DT/ACPI/fwnode firmware interfaces. Lets convert the two sdhci caps fields to use the generic calls rather than the OF specific ones. This has the side effect of allowing ACPI based devices to quirk themselves when the caps field is broken. Signed-off-by: Jeremy Linton Link: https://lore.kernel.org/r/20201120233831.447365-1-jeremy.linton@arm.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 3561ae8a481a..6edf9fffd934 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -3994,10 +3994,10 @@ void __sdhci_read_caps(struct sdhci_host *host, const u16 *ver, if (host->v4_mode) sdhci_do_enable_v4_mode(host); - of_property_read_u64(mmc_dev(host->mmc)->of_node, - "sdhci-caps-mask", &dt_caps_mask); - of_property_read_u64(mmc_dev(host->mmc)->of_node, - "sdhci-caps", &dt_caps); + device_property_read_u64_array(mmc_dev(host->mmc), + "sdhci-caps-mask", &dt_caps_mask, 1); + device_property_read_u64_array(mmc_dev(host->mmc), + "sdhci-caps", &dt_caps, 1); v = ver ? *ver : sdhci_readw(host, SDHCI_HOST_VERSION); host->version = (v & SDHCI_SPEC_VER_MASK) >> SDHCI_SPEC_VER_SHIFT; From d7b819b5d33869d41bdaa427aeb98ae24c57a38b Mon Sep 17 00:00:00 2001 From: Zhihao Cheng Date: Sat, 21 Nov 2020 10:14:31 +0800 Subject: [PATCH 064/102] mmc: pxamci: Fix error return code in pxamci_probe Fix to return the error code from devm_gpiod_get_optional() instaed of 0 in pxamci_probe(). Fixes: f54005b508b9a9d9c ("mmc: pxa: Use GPIO descriptor for power") Reported-by: Hulk Robot Signed-off-by: Zhihao Cheng Link: https://lore.kernel.org/r/20201121021431.3168506-1-chengzhihao1@huawei.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/pxamci.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/mmc/host/pxamci.c b/drivers/mmc/host/pxamci.c index 29f6180a0036..316393c694d7 100644 --- a/drivers/mmc/host/pxamci.c +++ b/drivers/mmc/host/pxamci.c @@ -731,6 +731,7 @@ static int pxamci_probe(struct platform_device *pdev) host->power = devm_gpiod_get_optional(dev, "power", GPIOD_OUT_LOW); if (IS_ERR(host->power)) { + ret = PTR_ERR(host->power); dev_err(dev, "Failed requesting gpio_power\n"); goto out; } From b61d468d969f74acf704b3ec61c29c46b825e0c5 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Sun, 22 Nov 2020 13:00:56 +0100 Subject: [PATCH 065/102] mmc: mediatek: depend on COMMON_CLK to fix compile tests The MFD_OMAP_USB_HOST uses Common Clock Framework thus it cannot be built on platforms without it (e.g. compile test on MIPS with LANTIQ): mips-linux-ld: drivers/mmc/host/mtk-sd.o: in function `msdc_ops_set_ios': mtk-sd.c:(.text+0x2bbc): undefined reference to `clk_get_parent' Reported-by: kernel test robot Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20201122120056.100045-1-krzk@kernel.org Signed-off-by: Ulf Hansson --- drivers/mmc/host/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig index 7324a61d7416..596f32637315 100644 --- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig @@ -1023,6 +1023,7 @@ config MMC_BCM2835 config MMC_MTK tristate "MediaTek SD/MMC Card Interface support" depends on HAS_DMA + depends on COMMON_CLK select REGULATOR select MMC_CQHCI help From 0f1d9961d64faf819f79c471b74e53c63c9209fc Mon Sep 17 00:00:00 2001 From: Ben Chuang Date: Mon, 23 Nov 2020 13:37:02 +0800 Subject: [PATCH 066/102] mmc: sdhci-pci-gli: Reduce power consumption for GL9755 For GL9755, reduce power consumption by lowering the LFCLK and disabling the DMACLK on low-power. Signed-off-by: Ben Chuang Link: https://lore.kernel.org/r/20201123053702.6083-1-benchuanggli@gmail.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci-pci-gli.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/drivers/mmc/host/sdhci-pci-gli.c b/drivers/mmc/host/sdhci-pci-gli.c index 9887485a4134..f10bdfbfce36 100644 --- a/drivers/mmc/host/sdhci-pci-gli.c +++ b/drivers/mmc/host/sdhci-pci-gli.c @@ -97,6 +97,10 @@ #define GLI_9755_WT_EN_ON 0x1 #define GLI_9755_WT_EN_OFF 0x0 +#define PCI_GLI_9755_PECONF 0x44 +#define PCI_GLI_9755_LFCLK GENMASK(14, 12) +#define PCI_GLI_9755_DMACLK BIT(29) + #define PCI_GLI_9755_PLL 0x64 #define PCI_GLI_9755_PLL_LDIV GENMASK(9, 0) #define PCI_GLI_9755_PLL_PDIV GENMASK(14, 12) @@ -519,6 +523,21 @@ static void sdhci_gl9755_set_clock(struct sdhci_host *host, unsigned int clock) sdhci_enable_clk(host, clk); } +static void gl9755_hw_setting(struct sdhci_pci_slot *slot) +{ + struct pci_dev *pdev = slot->chip->pdev; + u32 value; + + gl9755_wt_on(pdev); + + pci_read_config_dword(pdev, PCI_GLI_9755_PECONF, &value); + value &= ~PCI_GLI_9755_LFCLK; + value &= ~PCI_GLI_9755_DMACLK; + pci_write_config_dword(pdev, PCI_GLI_9755_PECONF, value); + + gl9755_wt_off(pdev); +} + static int gli_probe_slot_gl9750(struct sdhci_pci_slot *slot) { struct sdhci_host *host = slot->host; @@ -534,6 +553,7 @@ static int gli_probe_slot_gl9755(struct sdhci_pci_slot *slot) { struct sdhci_host *host = slot->host; + gl9755_hw_setting(slot); gli_pcie_enable_msi(slot); slot->host->mmc->caps2 |= MMC_CAP2_NO_SDIO; sdhci_enable_v4_mode(host); From a3096ec649ea77a921d7612f71aa926d822641f5 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Fri, 20 Nov 2020 12:37:13 -0600 Subject: [PATCH 067/102] mmc: sdhci-of-arasan: Fix fall-through warnings for Clang In preparation to enable -Wimplicit-fallthrough for Clang, fix multiple warnings by explicitly adding multiple break statements instead of letting the code fall through to the next case. Link: https://github.com/KSPP/linux/issues/115 Signed-off-by: Gustavo A. R. Silva Acked-by: Michal Simek Link: https://lore.kernel.org/r/387cab3a466038aa5d1fc34b8b6a7c4f693826ea.1605896060.git.gustavoars@kernel.org Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci-of-arasan.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/mmc/host/sdhci-of-arasan.c b/drivers/mmc/host/sdhci-of-arasan.c index 3b8d456e857d..4f3774bcda94 100644 --- a/drivers/mmc/host/sdhci-of-arasan.c +++ b/drivers/mmc/host/sdhci-of-arasan.c @@ -624,6 +624,7 @@ static int sdhci_zynqmp_sdcardclk_set_phase(struct clk_hw *hw, int degrees) case MMC_TIMING_MMC_HS200: /* For 200MHz clock, 8 Taps are available */ tap_max = 8; + break; default: break; } @@ -692,6 +693,7 @@ static int sdhci_zynqmp_sampleclk_set_phase(struct clk_hw *hw, int degrees) case MMC_TIMING_MMC_HS200: /* For 200MHz clock, 30 Taps are available */ tap_max = 30; + break; default: break; } @@ -751,6 +753,7 @@ static int sdhci_versal_sdcardclk_set_phase(struct clk_hw *hw, int degrees) case MMC_TIMING_MMC_HS200: /* For 200MHz clock, 8 Taps are available */ tap_max = 8; + break; default: break; } @@ -817,6 +820,7 @@ static int sdhci_versal_sampleclk_set_phase(struct clk_hw *hw, int degrees) case MMC_TIMING_MMC_HS200: /* For 200MHz clock, 30 Taps are available */ tap_max = 30; + break; default: break; } From d33b5b6857204578e308b6c8f8e060a6c92cb183 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Mon, 23 Nov 2020 16:19:56 -0300 Subject: [PATCH 068/102] mmc: mxs: Remove the unused .id_table The mxs-mmc driver is only used by DT platforms and the .id_table is unused. Get rid of it to simplify the code. While at it, use of_device_get_match_data() to retrieve the driver data. Signed-off-by: Fabio Estevam Link: https://lore.kernel.org/r/20201123191956.10542-1-festevam@gmail.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/mxs-mmc.c | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/drivers/mmc/host/mxs-mmc.c b/drivers/mmc/host/mxs-mmc.c index 75007f61df97..56bbc6cd9c84 100644 --- a/drivers/mmc/host/mxs-mmc.c +++ b/drivers/mmc/host/mxs-mmc.c @@ -545,19 +545,6 @@ static const struct mmc_host_ops mxs_mmc_ops = { .enable_sdio_irq = mxs_mmc_enable_sdio_irq, }; -static const struct platform_device_id mxs_ssp_ids[] = { - { - .name = "imx23-mmc", - .driver_data = IMX23_SSP, - }, { - .name = "imx28-mmc", - .driver_data = IMX28_SSP, - }, { - /* sentinel */ - } -}; -MODULE_DEVICE_TABLE(platform, mxs_ssp_ids); - static const struct of_device_id mxs_mmc_dt_ids[] = { { .compatible = "fsl,imx23-mmc", .data = (void *) IMX23_SSP, }, { .compatible = "fsl,imx28-mmc", .data = (void *) IMX28_SSP, }, @@ -567,8 +554,6 @@ MODULE_DEVICE_TABLE(of, mxs_mmc_dt_ids); static int mxs_mmc_probe(struct platform_device *pdev) { - const struct of_device_id *of_id = - of_match_device(mxs_mmc_dt_ids, &pdev->dev); struct device_node *np = pdev->dev.of_node; struct mxs_mmc_host *host; struct mmc_host *mmc; @@ -593,7 +578,7 @@ static int mxs_mmc_probe(struct platform_device *pdev) goto out_mmc_free; } - ssp->devid = (enum mxs_ssp_id) of_id->data; + ssp->devid = (enum mxs_ssp_id)of_device_get_match_data(&pdev->dev); host->mmc = mmc; host->sdio_irq_en = 0; @@ -723,7 +708,6 @@ static SIMPLE_DEV_PM_OPS(mxs_mmc_pm_ops, mxs_mmc_suspend, mxs_mmc_resume); static struct platform_driver mxs_mmc_driver = { .probe = mxs_mmc_probe, .remove = mxs_mmc_remove, - .id_table = mxs_ssp_ids, .driver = { .name = DRIVER_NAME, .probe_type = PROBE_PREFER_ASYNCHRONOUS, From 8223e885e74b6424cd5b0ab1de4581ca017b7a4e Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Mon, 23 Nov 2020 17:30:04 -0300 Subject: [PATCH 069/102] mmc: mxc: Convert the driver to DT-only Since 5.10-rc1 i.MX is a devicetree-only platform, so simplify the code by removing the unused non-DT support. Signed-off-by: Fabio Estevam Link: https://lore.kernel.org/r/20201123203004.18792-1-festevam@gmail.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/mxcmmc.c | 33 ++++----------------------------- 1 file changed, 4 insertions(+), 29 deletions(-) diff --git a/drivers/mmc/host/mxcmmc.c b/drivers/mmc/host/mxcmmc.c index 12ee07285980..2fe6fcdbb1b3 100644 --- a/drivers/mmc/host/mxcmmc.c +++ b/drivers/mmc/host/mxcmmc.c @@ -157,32 +157,16 @@ struct mxcmci_host { enum mxcmci_type devtype; }; -static const struct platform_device_id mxcmci_devtype[] = { - { - .name = "imx21-mmc", - .driver_data = IMX21_MMC, - }, { - .name = "imx31-mmc", - .driver_data = IMX31_MMC, - }, { - .name = "mpc512x-sdhc", - .driver_data = MPC512X_MMC, - }, { - /* sentinel */ - } -}; -MODULE_DEVICE_TABLE(platform, mxcmci_devtype); - static const struct of_device_id mxcmci_of_match[] = { { .compatible = "fsl,imx21-mmc", - .data = &mxcmci_devtype[IMX21_MMC], + .data = (void *) IMX21_MMC, }, { .compatible = "fsl,imx31-mmc", - .data = &mxcmci_devtype[IMX31_MMC], + .data = (void *) IMX31_MMC, }, { .compatible = "fsl,mpc5121-sdhc", - .data = &mxcmci_devtype[MPC512X_MMC], + .data = (void *) MPC512X_MMC, }, { /* sentinel */ } @@ -1001,13 +985,10 @@ static int mxcmci_probe(struct platform_device *pdev) int ret = 0, irq; bool dat3_card_detect = false; dma_cap_mask_t mask; - const struct of_device_id *of_id; struct imxmmc_platform_data *pdata = pdev->dev.platform_data; pr_info("i.MX/MPC512x SDHC driver\n"); - of_id = of_match_device(mxcmci_of_match, &pdev->dev); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); irq = platform_get_irq(pdev, 0); if (irq < 0) @@ -1044,12 +1025,7 @@ static int mxcmci_probe(struct platform_device *pdev) mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count; mmc->max_seg_size = mmc->max_req_size; - if (of_id) { - const struct platform_device_id *id_entry = of_id->data; - host->devtype = id_entry->driver_data; - } else { - host->devtype = pdev->id_entry->driver_data; - } + host->devtype = (enum mxcmci_type)of_device_get_match_data(&pdev->dev); /* adjust max_segs after devtype detection */ if (!is_mpc512x_mmc(host)) @@ -1241,7 +1217,6 @@ static SIMPLE_DEV_PM_OPS(mxcmci_pm_ops, mxcmci_suspend, mxcmci_resume); static struct platform_driver mxcmci_driver = { .probe = mxcmci_probe, .remove = mxcmci_remove, - .id_table = mxcmci_devtype, .driver = { .name = DRIVER_NAME, .probe_type = PROBE_PREFER_ASYNCHRONOUS, From 9c7cae2427715502227f823364a6a77828fdf3ea Mon Sep 17 00:00:00 2001 From: Mark Tomlinson Date: Thu, 27 Aug 2020 10:35:16 +1200 Subject: [PATCH 070/102] i2c: mv64xxx: Add bus error recovery This adds i2c bus recovery to the mv64xxx driver. Implement bus recovery to recover from SCL/SDA stuck low. This uses the generic recovery function, setting the clock/data lines as GPIO pins, and sending 9 clocks to try and recover the bus. Signed-off-by: Mark Tomlinson [wsa: added some curly braces] Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-mv64xxx.c | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/drivers/i2c/busses/i2c-mv64xxx.c b/drivers/i2c/busses/i2c-mv64xxx.c index e0e45fc19b8f..5cfe70aedced 100644 --- a/drivers/i2c/busses/i2c-mv64xxx.c +++ b/drivers/i2c/busses/i2c-mv64xxx.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -147,6 +148,7 @@ struct mv64xxx_i2c_data { bool irq_clear_inverted; /* Clk div is 2 to the power n, not 2 to the power n + 1 */ bool clk_n_base_0; + struct i2c_bus_recovery_info rinfo; }; static struct mv64xxx_i2c_regs mv64xxx_i2c_regs_mv64xxx = { @@ -325,7 +327,8 @@ mv64xxx_i2c_fsm(struct mv64xxx_i2c_data *drv_data, u32 status) drv_data->msg->flags); drv_data->action = MV64XXX_I2C_ACTION_SEND_STOP; mv64xxx_i2c_hw_init(drv_data); - drv_data->rc = -EIO; + i2c_recover_bus(&drv_data->adapter); + drv_data->rc = -EAGAIN; } } @@ -561,6 +564,7 @@ mv64xxx_i2c_wait_for_completion(struct mv64xxx_i2c_data *drv_data) "time_left: %d\n", drv_data->block, (int)time_left); mv64xxx_i2c_hw_init(drv_data); + i2c_recover_bus(&drv_data->adapter); } } else spin_unlock_irqrestore(&drv_data->lock, flags); @@ -870,6 +874,25 @@ mv64xxx_of_config(struct mv64xxx_i2c_data *drv_data, } #endif /* CONFIG_OF */ +static int mv64xxx_i2c_init_recovery_info(struct mv64xxx_i2c_data *drv_data, + struct device *dev) +{ + struct i2c_bus_recovery_info *rinfo = &drv_data->rinfo; + + rinfo->pinctrl = devm_pinctrl_get(dev); + if (IS_ERR(rinfo->pinctrl)) { + if (PTR_ERR(rinfo->pinctrl) == -EPROBE_DEFER) + return -EPROBE_DEFER; + dev_info(dev, "can't get pinctrl, bus recovery not supported\n"); + return PTR_ERR(rinfo->pinctrl); + } else if (!rinfo->pinctrl) { + return -ENODEV; + } + + drv_data->adapter.bus_recovery_info = rinfo; + return 0; +} + static int mv64xxx_i2c_probe(struct platform_device *pd) { @@ -926,6 +949,10 @@ mv64xxx_i2c_probe(struct platform_device *pd) goto exit_reset; } + rc = mv64xxx_i2c_init_recovery_info(drv_data, &pd->dev); + if (rc == -EPROBE_DEFER) + goto exit_reset; + drv_data->adapter.dev.parent = &pd->dev; drv_data->adapter.algo = &mv64xxx_i2c_algo; drv_data->adapter.owner = THIS_MODULE; From 579f8983c4597ccb0011fa7c5a388c322f4b46ef Mon Sep 17 00:00:00 2001 From: Khalil Blaiech Date: Fri, 20 Nov 2020 18:06:06 -0500 Subject: [PATCH 071/102] dt-bindings: i2c: mellanox,i2c-mlxbf: convert txt to YAML schema Write the devicetree binding text file associated with the Mellanox BlueField I2C controller in schema file, JSON compatible subset of YAML. Besides, add an entry within MAINTAINERS file. Signed-off-by: Khalil Blaiech Reviewed-by: Rob Herring Signed-off-by: Wolfram Sang --- .../bindings/i2c/mellanox,i2c-mlxbf.txt | 42 ---------- .../bindings/i2c/mellanox,i2c-mlxbf.yaml | 78 +++++++++++++++++++ MAINTAINERS | 1 + 3 files changed, 79 insertions(+), 42 deletions(-) delete mode 100644 Documentation/devicetree/bindings/i2c/mellanox,i2c-mlxbf.txt create mode 100644 Documentation/devicetree/bindings/i2c/mellanox,i2c-mlxbf.yaml diff --git a/Documentation/devicetree/bindings/i2c/mellanox,i2c-mlxbf.txt b/Documentation/devicetree/bindings/i2c/mellanox,i2c-mlxbf.txt deleted file mode 100644 index 566ea861aa00..000000000000 --- a/Documentation/devicetree/bindings/i2c/mellanox,i2c-mlxbf.txt +++ /dev/null @@ -1,42 +0,0 @@ -Device tree configuration for the Mellanox I2C SMBus on BlueField SoCs - -Required Properties: - -- compatible : should be "mellanox,i2c-mlxbf1" or "mellanox,i2c-mlxbf2". - -- reg : address offset and length of the device registers. The - registers consist of the following set of resources: - 1) Smbus block registers. - 2) Cause master registers. - 3) Cause slave registers. - 4) Cause coalesce registers (if compatible isn't set - to "mellanox,i2c-mlxbf1"). - -- interrupts : interrupt number. - -Optional Properties: - -- clock-frequency : bus frequency used to configure timing registers; - allowed values are 100000, 400000 and 1000000; - those are expressed in Hz. Default is 100000. - -Example: - -i2c@2804000 { - compatible = "mellanox,i2c-mlxbf1"; - reg = <0x02804000 0x800>, - <0x02801200 0x020>, - <0x02801260 0x020>; - interrupts = <57>; - clock-frequency = <100000>; -}; - -i2c@2808800 { - compatible = "mellanox,i2c-mlxbf2"; - reg = <0x02808800 0x600>, - <0x02808e00 0x020>, - <0x02808e20 0x020>, - <0x02808e40 0x010>; - interrupts = <57>; - clock-frequency = <400000>; -}; diff --git a/Documentation/devicetree/bindings/i2c/mellanox,i2c-mlxbf.yaml b/Documentation/devicetree/bindings/i2c/mellanox,i2c-mlxbf.yaml new file mode 100644 index 000000000000..d2b401d062b9 --- /dev/null +++ b/Documentation/devicetree/bindings/i2c/mellanox,i2c-mlxbf.yaml @@ -0,0 +1,78 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/i2c/mellanox,i2c-mlxbf.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Mellanox I2C SMBus on BlueField SoCs + +maintainers: + - Khalil Blaiech + +allOf: + - $ref: /schemas/i2c/i2c-controller.yaml# + +properties: + compatible: + enum: + - mellanox,i2c-mlxbf1 + - mellanox,i2c-mlxbf2 + + reg: + minItems: 3 + maxItems: 4 + items: + - description: Smbus block registers + - description: Cause master registers + - description: Cause slave registers + - description: Cause coalesce registers + + interrupts: + maxItems: 1 + + clock-frequency: + enum: [ 100000, 400000, 1000000 ] + description: + bus frequency used to configure timing registers; + The frequency is expressed in Hz. Default is 100000. + +required: + - compatible + - reg + - interrupts + +unevaluatedProperties: false + +if: + properties: + compatible: + contains: + enum: + - mellanox,i2c-mlxbf1 + +then: + properties: + reg: + maxItems: 3 + +examples: + - | + i2c@2804000 { + compatible = "mellanox,i2c-mlxbf1"; + reg = <0x02804000 0x800>, + <0x02801200 0x020>, + <0x02801260 0x020>; + interrupts = <57>; + clock-frequency = <100000>; + }; + + - | + i2c@2808800 { + compatible = "mellanox,i2c-mlxbf2"; + reg = <0x02808800 0x600>, + <0x02808e00 0x020>, + <0x02808e20 0x020>, + <0x02808e40 0x010>; + interrupts = <57>; + clock-frequency = <400000>; + }; diff --git a/MAINTAINERS b/MAINTAINERS index b516bb34a8d5..b2b505ff31f5 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -11166,6 +11166,7 @@ MELLANOX BLUEFIELD I2C DRIVER M: Khalil Blaiech L: linux-i2c@vger.kernel.org S: Supported +F: Documentation/devicetree/bindings/i2c/mellanox,i2c-mlxbf.yaml F: drivers/i2c/busses/i2c-mlxbf.c MELLANOX ETHERNET DRIVER (mlx4_en) From b4ff421f123ebc16b4c8cb4474485be29812b5ed Mon Sep 17 00:00:00 2001 From: Vaibhav Gupta Date: Sat, 7 Nov 2020 13:51:51 +0530 Subject: [PATCH 072/102] i2c: nvidia-gpu: drop empty stub for runtime pm After the commit c5eb1190074c ("PCI / PM: Allow runtime PM without callback functions") we no more need empty stubs for runtime-pm to work. The driver has no device specific task(s) for .suspend() . The stub was placed just for runtime-pm, which can be dropped now. Reported-by: Bjorn Helgaas Signed-off-by: Vaibhav Gupta Reviewed-by: Jarkko Nikula Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-nvidia-gpu.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/drivers/i2c/busses/i2c-nvidia-gpu.c b/drivers/i2c/busses/i2c-nvidia-gpu.c index f9a69b109e5c..6b20601ffb13 100644 --- a/drivers/i2c/busses/i2c-nvidia-gpu.c +++ b/drivers/i2c/busses/i2c-nvidia-gpu.c @@ -353,15 +353,7 @@ static void gpu_i2c_remove(struct pci_dev *pdev) pci_free_irq_vectors(pdev); } -/* - * We need gpu_i2c_suspend() even if it is stub, for runtime pm to work - * correctly. Without it, lspci shows runtime pm status as "D0" for the card. - * Documentation/power/pci.rst also insists for driver to provide this. - */ -static __maybe_unused int gpu_i2c_suspend(struct device *dev) -{ - return 0; -} +#define gpu_i2c_suspend NULL static __maybe_unused int gpu_i2c_resume(struct device *dev) { From c610199cd392e6e2d41811ef83d85355c1b862b3 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Mon, 16 Nov 2020 17:29:10 -0300 Subject: [PATCH 073/102] i2c: imx: Remove unused .id_table support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since 5.10-rc1 i.MX is a devicetree-only platform and the existing .id_table support in this driver was only useful for old non-devicetree platforms. Signed-off-by: Fabio Estevam Acked-by: Uwe Kleine-König Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-imx.c | 20 +------------------- 1 file changed, 1 insertion(+), 19 deletions(-) diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c index c98529c76348..ebf66120c51e 100644 --- a/drivers/i2c/busses/i2c-imx.c +++ b/drivers/i2c/busses/i2c-imx.c @@ -233,19 +233,6 @@ static struct imx_i2c_hwdata vf610_i2c_hwdata = { }; -static const struct platform_device_id imx_i2c_devtype[] = { - { - .name = "imx1-i2c", - .driver_data = (kernel_ulong_t)&imx1_i2c_hwdata, - }, { - .name = "imx21-i2c", - .driver_data = (kernel_ulong_t)&imx21_i2c_hwdata, - }, { - /* sentinel */ - } -}; -MODULE_DEVICE_TABLE(platform, imx_i2c_devtype); - static const struct of_device_id i2c_imx_dt_ids[] = { { .compatible = "fsl,imx1-i2c", .data = &imx1_i2c_hwdata, }, { .compatible = "fsl,imx21-i2c", .data = &imx21_i2c_hwdata, }, @@ -1141,11 +1128,7 @@ static int i2c_imx_probe(struct platform_device *pdev) return -ENOMEM; match = device_get_match_data(&pdev->dev); - if (match) - i2c_imx->hwdata = match; - else - i2c_imx->hwdata = (struct imx_i2c_hwdata *) - platform_get_device_id(pdev)->driver_data; + i2c_imx->hwdata = match; /* Setup i2c_imx driver structure */ strlcpy(i2c_imx->adapter.name, pdev->name, sizeof(i2c_imx->adapter.name)); @@ -1316,7 +1299,6 @@ static struct platform_driver i2c_imx_driver = { .of_match_table = i2c_imx_dt_ids, .acpi_match_table = i2c_imx_acpi_ids, }, - .id_table = imx_i2c_devtype, }; static int __init i2c_adap_imx_init(void) From 83eb65b6ac7cd17ba87e5ebd15cd44f4034ccf3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Mon, 23 Nov 2020 21:27:46 +0100 Subject: [PATCH 074/102] i2c: pca-platform: drop two members from driver data that are assigned to only MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit io_base and io_size are assigned to only in .probe() and otherwise unused. Signed-off-by: Uwe Kleine-König Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-pca-platform.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/i2c/busses/i2c-pca-platform.c b/drivers/i2c/busses/i2c-pca-platform.c index 546426a470cc..86d4f75ef8d3 100644 --- a/drivers/i2c/busses/i2c-pca-platform.c +++ b/drivers/i2c/busses/i2c-pca-platform.c @@ -33,8 +33,6 @@ struct i2c_pca_pf_data { wait_queue_head_t wait; struct i2c_adapter adap; struct i2c_algo_pca_data algo_data; - unsigned long io_base; - unsigned long io_size; }; /* Read/Write functions for different register alignments */ @@ -156,8 +154,6 @@ static int i2c_pca_pf_probe(struct platform_device *pdev) init_waitqueue_head(&i2c->wait); - i2c->io_base = res->start; - i2c->io_size = resource_size(res); i2c->irq = irq; i2c->adap.nr = pdev->id; From c32abd8b569144b20c9c9b6dd7232828c612452f Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Mon, 23 Nov 2020 21:28:49 -0300 Subject: [PATCH 075/102] i2c: mxs: Remove unneeded platform_device_id The i2c-mxs driver only runs on DT-platform and there is no need to use the platform_device_id structure to pass the driver data. Get rid of it to make the code simpler. Signed-off-by: Fabio Estevam Reported-by: kernel test robot Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-mxs.c | 22 +++------------------- 1 file changed, 3 insertions(+), 19 deletions(-) diff --git a/drivers/i2c/busses/i2c-mxs.c b/drivers/i2c/busses/i2c-mxs.c index c4b08a924461..f97243f02231 100644 --- a/drivers/i2c/busses/i2c-mxs.c +++ b/drivers/i2c/busses/i2c-mxs.c @@ -781,28 +781,15 @@ static int mxs_i2c_get_ofdata(struct mxs_i2c_dev *i2c) return 0; } -static const struct platform_device_id mxs_i2c_devtype[] = { - { - .name = "imx23-i2c", - .driver_data = MXS_I2C_V1, - }, { - .name = "imx28-i2c", - .driver_data = MXS_I2C_V2, - }, { /* sentinel */ } -}; -MODULE_DEVICE_TABLE(platform, mxs_i2c_devtype); - static const struct of_device_id mxs_i2c_dt_ids[] = { - { .compatible = "fsl,imx23-i2c", .data = &mxs_i2c_devtype[0], }, - { .compatible = "fsl,imx28-i2c", .data = &mxs_i2c_devtype[1], }, + { .compatible = "fsl,imx23-i2c", .data = (void *)MXS_I2C_V1, }, + { .compatible = "fsl,imx28-i2c", .data = (void *)MXS_I2C_V2, }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, mxs_i2c_dt_ids); static int mxs_i2c_probe(struct platform_device *pdev) { - const struct of_device_id *of_id = - of_match_device(mxs_i2c_dt_ids, &pdev->dev); struct device *dev = &pdev->dev; struct mxs_i2c_dev *i2c; struct i2c_adapter *adap; @@ -812,10 +799,7 @@ static int mxs_i2c_probe(struct platform_device *pdev) if (!i2c) return -ENOMEM; - if (of_id) { - const struct platform_device_id *device_id = of_id->data; - i2c->dev_type = device_id->driver_data; - } + i2c->dev_type = (enum mxs_i2c_devtype)of_device_get_match_data(&pdev->dev); i2c->regs = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(i2c->regs)) From 70f16fab5272bfc5b83c24bc1a8e877697bf17cc Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Tue, 24 Nov 2020 12:57:43 -0600 Subject: [PATCH 076/102] Revert "i2c: qcom-geni: Disable DMA processing on the Lenovo Yoga C630" A combination of recent bug fixes by Doug Anderson and the proper definition of iommu streams means that this hack is no longer needed. Let's clean up the code by reverting '127068abe85b ("i2c: qcom-geni: Disable DMA processing on the Lenovo Yoga C630")'. Signed-off-by: Bjorn Andersson Acked-by: Shawn Guo Acked-by: Caleb Connolly Tested-by: Steev Klimaszewski Reviewed-by: Akash Asthana Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-qcom-geni.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/drivers/i2c/busses/i2c-qcom-geni.c b/drivers/i2c/busses/i2c-qcom-geni.c index dce75b85253c..046d241183c5 100644 --- a/drivers/i2c/busses/i2c-qcom-geni.c +++ b/drivers/i2c/busses/i2c-qcom-geni.c @@ -353,13 +353,11 @@ static int geni_i2c_rx_one_msg(struct geni_i2c_dev *gi2c, struct i2c_msg *msg, { dma_addr_t rx_dma; unsigned long time_left; - void *dma_buf = NULL; + void *dma_buf; struct geni_se *se = &gi2c->se; size_t len = msg->len; - if (!of_machine_is_compatible("lenovo,yoga-c630")) - dma_buf = i2c_get_dma_safe_msg_buf(msg, 32); - + dma_buf = i2c_get_dma_safe_msg_buf(msg, 32); if (dma_buf) geni_se_select_mode(se, GENI_SE_DMA); else @@ -394,13 +392,11 @@ static int geni_i2c_tx_one_msg(struct geni_i2c_dev *gi2c, struct i2c_msg *msg, { dma_addr_t tx_dma; unsigned long time_left; - void *dma_buf = NULL; + void *dma_buf; struct geni_se *se = &gi2c->se; size_t len = msg->len; - if (!of_machine_is_compatible("lenovo,yoga-c630")) - dma_buf = i2c_get_dma_safe_msg_buf(msg, 32); - + dma_buf = i2c_get_dma_safe_msg_buf(msg, 32); if (dma_buf) geni_se_select_mode(se, GENI_SE_DMA); else From dc4e10b62695558a39aafa65210f5980125285b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20L=C3=A4sser?= Date: Thu, 3 Dec 2020 16:02:52 +0100 Subject: [PATCH 077/102] i2c: ocores: Avoid false-positive error log message. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since commit 7723f4c5ecdb ("driver core: platform: Add an error message to platform_get_irq*()"), platform_get_irq() will call dev_err() on an error. In case of i2c ocores this leads to a false-positive error being logged: [ 4.173989] 007: ocores-i2c ocores-i2c: IRQ index 0 not found i2c ocores already handles the case when the IRQ cannot be found and therefore there is no benefit in having this error message being logged. This commit switches to platform_get_irq_optional(), which does not log in case the IRQ cannot be found. Signed-off-by: Stefan Lässer Reviewed-by: Andrew Lunn Reviewed-by: Peter Korsgaard Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-ocores.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/i2c/busses/i2c-ocores.c b/drivers/i2c/busses/i2c-ocores.c index a97cbaabd308..273222e38056 100644 --- a/drivers/i2c/busses/i2c-ocores.c +++ b/drivers/i2c/busses/i2c-ocores.c @@ -682,7 +682,7 @@ static int ocores_i2c_probe(struct platform_device *pdev) init_waitqueue_head(&i2c->wait); - irq = platform_get_irq(pdev, 0); + irq = platform_get_irq_optional(pdev, 0); /* * Since the SoC does have an interrupt, its DT has an interrupt * property - But this should be bypassed as the IRQ logic in this From 5e9a97b1f4491b8b65874901ad084348fcaba327 Mon Sep 17 00:00:00 2001 From: Mario Alejandro Posso Escobar Date: Mon, 16 Nov 2020 17:32:45 +0200 Subject: [PATCH 078/102] i2c: ismt: Adding support for I2C_SMBUS_BLOCK_PROC_CALL Expand the driver to support I2C_SMBUS_BLOCK_PROC_CALL since HW supports it already. Co-developed-by: Andy Shevchenko Signed-off-by: Andy Shevchenko Signed-off-by: Mario Alejandro Posso Escobar Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-ismt.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/drivers/i2c/busses/i2c-ismt.c b/drivers/i2c/busses/i2c-ismt.c index a35a27c320e7..a6187cbec2c9 100644 --- a/drivers/i2c/busses/i2c-ismt.c +++ b/drivers/i2c/busses/i2c-ismt.c @@ -53,7 +53,7 @@ * Features supported by this driver: * Hardware PEC yes * Block buffer yes - * Block process call transaction no + * Block process call transaction yes * Slave mode no */ @@ -332,7 +332,8 @@ static int ismt_process_desc(const struct ismt_desc *desc, if (desc->status & ISMT_DESC_SCS) { if (read_write == I2C_SMBUS_WRITE && - size != I2C_SMBUS_PROC_CALL) + size != I2C_SMBUS_PROC_CALL && + size != I2C_SMBUS_BLOCK_PROC_CALL) return 0; switch (size) { @@ -345,6 +346,7 @@ static int ismt_process_desc(const struct ismt_desc *desc, data->word = dma_buffer[0] | (dma_buffer[1] << 8); break; case I2C_SMBUS_BLOCK_DATA: + case I2C_SMBUS_BLOCK_PROC_CALL: if (desc->rxbytes != dma_buffer[0] + 1) return -EMSGSIZE; @@ -518,6 +520,18 @@ static int ismt_access(struct i2c_adapter *adap, u16 addr, } break; + case I2C_SMBUS_BLOCK_PROC_CALL: + dev_dbg(dev, "I2C_SMBUS_BLOCK_PROC_CALL\n"); + dma_size = I2C_SMBUS_BLOCK_MAX; + desc->tgtaddr_rw = ISMT_DESC_ADDR_RW(addr, 1); + desc->wr_len_cmd = data->block[0] + 1; + desc->rd_len = dma_size; + desc->control |= ISMT_DESC_BLK; + dma_direction = DMA_BIDIRECTIONAL; + dma_buffer[0] = command; + memcpy(&dma_buffer[1], &data->block[1], data->block[0]); + break; + case I2C_SMBUS_I2C_BLOCK_DATA: /* Make sure the length is valid */ if (data->block[0] < 1) @@ -624,6 +638,7 @@ static u32 ismt_func(struct i2c_adapter *adap) I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | I2C_FUNC_SMBUS_PROC_CALL | + I2C_FUNC_SMBUS_BLOCK_PROC_CALL | I2C_FUNC_SMBUS_BLOCK_DATA | I2C_FUNC_SMBUS_I2C_BLOCK | I2C_FUNC_SMBUS_PEC; From db29d3d1c2451e673e29c7257471e3ce9d50383a Mon Sep 17 00:00:00 2001 From: Jing Xiangfeng Date: Wed, 25 Nov 2020 09:47:18 +0800 Subject: [PATCH 079/102] memstick: r592: Fix error return in r592_probe() Fix to return a error code from the error handling case instead of 0. Fixes: 926341250102 ("memstick: add driver for Ricoh R5C592 card reader") Signed-off-by: Jing Xiangfeng Link: https://lore.kernel.org/r/20201125014718.153563-1-jingxiangfeng@huawei.com Signed-off-by: Ulf Hansson --- drivers/memstick/host/r592.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/memstick/host/r592.c b/drivers/memstick/host/r592.c index dd3a1f3dcc19..d2ef46337191 100644 --- a/drivers/memstick/host/r592.c +++ b/drivers/memstick/host/r592.c @@ -759,8 +759,10 @@ static int r592_probe(struct pci_dev *pdev, const struct pci_device_id *id) goto error3; dev->mmio = pci_ioremap_bar(pdev, 0); - if (!dev->mmio) + if (!dev->mmio) { + error = -ENOMEM; goto error4; + } dev->irq = pdev->irq; spin_lock_init(&dev->irq_lock); @@ -786,12 +788,14 @@ static int r592_probe(struct pci_dev *pdev, const struct pci_device_id *id) &dev->dummy_dma_page_physical_address, GFP_KERNEL); r592_stop_dma(dev , 0); - if (request_irq(dev->irq, &r592_irq, IRQF_SHARED, - DRV_NAME, dev)) + error = request_irq(dev->irq, &r592_irq, IRQF_SHARED, + DRV_NAME, dev); + if (error) goto error6; r592_update_card_detect(dev); - if (memstick_add_host(host)) + error = memstick_add_host(host); + if (error) goto error7; message("driver successfully loaded"); From cb80a7e917483150ca592bc7e15163341e7d4150 Mon Sep 17 00:00:00 2001 From: Jeremy Linton Date: Tue, 24 Nov 2020 21:36:30 -0600 Subject: [PATCH 080/102] mmc: sdhci: Use more concise device_property_read_u64 Since we only need a single u64 the _array form is unnecessarily. Use device_property_read_u64 instead. Signed-off-by: Jeremy Linton Acked-by: Adrian Hunter Link: https://lore.kernel.org/r/20201125033630.603863-1-jeremy.linton@arm.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 6edf9fffd934..646823ddd317 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -3994,10 +3994,10 @@ void __sdhci_read_caps(struct sdhci_host *host, const u16 *ver, if (host->v4_mode) sdhci_do_enable_v4_mode(host); - device_property_read_u64_array(mmc_dev(host->mmc), - "sdhci-caps-mask", &dt_caps_mask, 1); - device_property_read_u64_array(mmc_dev(host->mmc), - "sdhci-caps", &dt_caps, 1); + device_property_read_u64(mmc_dev(host->mmc), + "sdhci-caps-mask", &dt_caps_mask); + device_property_read_u64(mmc_dev(host->mmc), + "sdhci-caps", &dt_caps); v = ver ? *ver : sdhci_readw(host, SDHCI_HOST_VERSION); host->version = (v & SDHCI_SPEC_VER_MASK) >> SDHCI_SPEC_VER_SHIFT; From 98991b1853ab699451afcc2223c5f1173a0aade9 Mon Sep 17 00:00:00 2001 From: Ben Chuang Date: Wed, 25 Nov 2020 19:01:45 +0800 Subject: [PATCH 081/102] mmc: sdhci-pci-gli: Disable slow mode in HS400 mode for GL9763E The GL9763E uses 150Mhz (slow mode) by default in HS400 mode. In order to make HS400 mode run at 200Mhz, the slow mode needs to be turned off. Signed-off-by: Ben Chuang Link: https://lore.kernel.org/r/20201125110145.2824-1-benchuanggli@gmail.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci-pci-gli.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/mmc/host/sdhci-pci-gli.c b/drivers/mmc/host/sdhci-pci-gli.c index f10bdfbfce36..b85edd62e7f0 100644 --- a/drivers/mmc/host/sdhci-pci-gli.c +++ b/drivers/mmc/host/sdhci-pci-gli.c @@ -87,6 +87,9 @@ #define PCIE_GLI_9763E_SCR 0x8E0 #define GLI_9763E_SCR_AXI_REQ BIT(9) +#define PCIE_GLI_9763E_MMC_CTRL 0x960 +#define GLI_9763E_HS400_SLOW BIT(3) + #define SDHCI_GLI_9763E_CQE_BASE_ADDR 0x200 #define GLI_9763E_CQE_TRNS_MODE (SDHCI_TRNS_MULTI | \ SDHCI_TRNS_BLK_CNT_EN | \ @@ -784,6 +787,10 @@ static void gli_set_gl9763e(struct sdhci_pci_slot *slot) value |= GLI_9763E_SCR_AXI_REQ; pci_write_config_dword(pdev, PCIE_GLI_9763E_SCR, value); + pci_read_config_dword(pdev, PCIE_GLI_9763E_MMC_CTRL, &value); + value &= ~GLI_9763E_HS400_SLOW; + pci_write_config_dword(pdev, PCIE_GLI_9763E_MMC_CTRL, value); + pci_read_config_dword(pdev, PCIE_GLI_9763E_VHS, &value); value &= ~GLI_9763E_VHS_REV; value |= FIELD_PREP(GLI_9763E_VHS_REV, GLI_9763E_VHS_REV_R); From 9d348477ddbbc7e2d16032a945a841a7624fef25 Mon Sep 17 00:00:00 2001 From: Dong Aisheng Date: Thu, 26 Nov 2020 18:58:43 +0800 Subject: [PATCH 082/102] dt-bindings: mmc: imx: fix the wrongly dropped imx8qm compatible string The compatible string "fsl,imx8qm-usdhc" was wrongly dropped in commit 80fd350b9590 ("dt-bindings: mmc: fsl-imx-esdhc: Fix i.MX 8 compatible matching"), let's add it back. Cc: Haibo Chen Cc: Krzysztof Kozlowski Cc: Ulf Hansson Fixes: 80fd350b9590 ("dt-bindings: mmc: fsl-imx-esdhc: Fix i.MX 8 compatible matching") Signed-off-by: Dong Aisheng Reviewed-by: Krzysztof Kozlowski Acked-by: Rob Herring Link: https://lore.kernel.org/r/20201126105900.26658-2-aisheng.dong@nxp.com Signed-off-by: Ulf Hansson --- Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.yaml b/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.yaml index e71d13c2d109..802c9df23752 100644 --- a/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.yaml +++ b/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.yaml @@ -39,6 +39,7 @@ properties: - fsl,imx8mn-usdhc - fsl,imx8mp-usdhc - fsl,imx8mq-usdhc + - fsl,imx8qm-usdhc - fsl,imx8qxp-usdhc - const: fsl,imx7d-usdhc From 30ae3e13caeaa47884c222ebf5711ce27ed25f19 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Wed, 25 Nov 2020 22:29:59 +0100 Subject: [PATCH 083/102] mmc: tmio: set max_busy_timeout Set max_busy_timeouts for variants known to support the TOPxx bits in the SD_OPTION register. The timeout mechanism was running in the background but not yet properly handled in the driver. So, let the MMC core know when to not use R1B to avoid unhandled timeouts. My datasheets for older variants (tmio_mmc.c) suggest that they support it, too. However, actual bit descriptions are lacking, so I chose an opt-in approach. Signed-off-by: Wolfram Sang Reviewed-by: Yoshihiro Shimoda Tested-by: Yoshihiro Shimoda Link: https://lore.kernel.org/r/20201125213001.15003-2-wsa+renesas@sang-engineering.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/renesas_sdhi_core.c | 3 +++ drivers/mmc/host/tmio_mmc.h | 2 ++ drivers/mmc/host/tmio_mmc_core.c | 15 +++++++++++++++ drivers/mmc/host/uniphier-sd.c | 1 + include/linux/mfd/tmio.h | 7 ++++++- 5 files changed, 27 insertions(+), 1 deletion(-) diff --git a/drivers/mmc/host/renesas_sdhi_core.c b/drivers/mmc/host/renesas_sdhi_core.c index bb937411c2ec..153767054c05 100644 --- a/drivers/mmc/host/renesas_sdhi_core.c +++ b/drivers/mmc/host/renesas_sdhi_core.c @@ -1041,6 +1041,9 @@ int renesas_sdhi_probe(struct platform_device *pdev, /* All SDHI have SDIO status bits which must be 1 */ mmc_data->flags |= TMIO_MMC_SDIO_STATUS_SETBITS; + /* All SDHI support HW busy detection */ + mmc_data->flags |= TMIO_MMC_USE_BUSY_TIMEOUT; + dev_pm_domain_start(&pdev->dev); ret = renesas_sdhi_clk_enable(host); diff --git a/drivers/mmc/host/tmio_mmc.h b/drivers/mmc/host/tmio_mmc.h index 7ff41185896a..819198af17f4 100644 --- a/drivers/mmc/host/tmio_mmc.h +++ b/drivers/mmc/host/tmio_mmc.h @@ -80,6 +80,8 @@ #define CLK_CTL_SCLKEN BIT(8) /* Definitions for values the CTL_SD_MEM_CARD_OPT register can take */ +#define CARD_OPT_TOP_MASK 0xf0 +#define CARD_OPT_TOP_SHIFT 4 #define CARD_OPT_WIDTH8 BIT(13) #define CARD_OPT_WIDTH BIT(15) diff --git a/drivers/mmc/host/tmio_mmc_core.c b/drivers/mmc/host/tmio_mmc_core.c index a89547f5d733..7d2da5befe6b 100644 --- a/drivers/mmc/host/tmio_mmc_core.c +++ b/drivers/mmc/host/tmio_mmc_core.c @@ -887,6 +887,18 @@ static void tmio_mmc_set_bus_width(struct tmio_mmc_host *host, sd_ctrl_write16(host, CTL_SD_MEM_CARD_OPT, reg); } +static void tmio_mmc_max_busy_timeout(struct tmio_mmc_host *host) +{ + u16 val = sd_ctrl_read16(host, CTL_SD_MEM_CARD_OPT); + unsigned int clk_rate = host->mmc->actual_clock ?: host->mmc->f_max; + unsigned int cycles; + + val = (val & CARD_OPT_TOP_MASK) >> CARD_OPT_TOP_SHIFT; + cycles = 1 << (13 + val); + + host->mmc->max_busy_timeout = cycles / (clk_rate / MSEC_PER_SEC); +} + /* Set MMC clock / power. * Note: This controller uses a simple divider scheme therefore it cannot * run a MMC card at full speed (20MHz). The max clock is 24MHz on SD, but as @@ -945,6 +957,9 @@ static void tmio_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) break; } + if (host->pdata->flags & TMIO_MMC_USE_BUSY_TIMEOUT) + tmio_mmc_max_busy_timeout(host); + /* Let things settle. delay taken from winCE driver */ usleep_range(140, 200); if (PTR_ERR(host->mrq) == -EINTR) diff --git a/drivers/mmc/host/uniphier-sd.c b/drivers/mmc/host/uniphier-sd.c index 3092466a99ab..a6cd16771d4e 100644 --- a/drivers/mmc/host/uniphier-sd.c +++ b/drivers/mmc/host/uniphier-sd.c @@ -586,6 +586,7 @@ static int uniphier_sd_probe(struct platform_device *pdev) tmio_data = &priv->tmio_data; tmio_data->flags |= TMIO_MMC_32BIT_DATA_PORT; + tmio_data->flags |= TMIO_MMC_USE_BUSY_TIMEOUT; host = tmio_mmc_host_alloc(pdev, tmio_data); if (IS_ERR(host)) diff --git a/include/linux/mfd/tmio.h b/include/linux/mfd/tmio.h index 8ba042430d8e..27264fe4b3b9 100644 --- a/include/linux/mfd/tmio.h +++ b/include/linux/mfd/tmio.h @@ -55,7 +55,12 @@ */ #define TMIO_MMC_HAS_IDLE_WAIT BIT(4) -/* BIT(5) is unused */ +/* + * Use the busy timeout feature. Probably all TMIO versions support it. Yet, + * we don't have documentation for old variants, so we enable only known good + * variants with this flag. Can be removed once all variants are known good. + */ +#define TMIO_MMC_USE_BUSY_TIMEOUT BIT(5) /* * Some controllers have CMD12 automatically From 58959f89dd3d8cc8bedcd2d665496603098b29a2 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Wed, 25 Nov 2020 22:30:00 +0100 Subject: [PATCH 084/102] mmc: tmio: add hook for custom busy_wait calculation Newer SDHI variants can 'wait while busy' longer than the generic TMIO. Provide a hook to get the maximum cycle count to wait for. If the hook is not populated, fall back to a generic version which works well with all older TMIO/SDHI variants. Signed-off-by: Wolfram Sang Reviewed-by: Yoshihiro Shimoda Tested-by: Yoshihiro Shimoda Link: https://lore.kernel.org/r/20201125213001.15003-3-wsa+renesas@sang-engineering.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/tmio_mmc.h | 1 + drivers/mmc/host/tmio_mmc_core.c | 17 ++++++++++++----- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/drivers/mmc/host/tmio_mmc.h b/drivers/mmc/host/tmio_mmc.h index 819198af17f4..f60559bc413a 100644 --- a/drivers/mmc/host/tmio_mmc.h +++ b/drivers/mmc/host/tmio_mmc.h @@ -181,6 +181,7 @@ struct tmio_mmc_host { void (*reset)(struct tmio_mmc_host *host); bool (*check_retune)(struct tmio_mmc_host *host); void (*fixup_request)(struct tmio_mmc_host *host, struct mmc_request *mrq); + unsigned int (*get_timeout_cycles)(struct tmio_mmc_host *host); void (*prepare_hs400_tuning)(struct tmio_mmc_host *host); void (*hs400_downgrade)(struct tmio_mmc_host *host); diff --git a/drivers/mmc/host/tmio_mmc_core.c b/drivers/mmc/host/tmio_mmc_core.c index 7d2da5befe6b..942b8375179c 100644 --- a/drivers/mmc/host/tmio_mmc_core.c +++ b/drivers/mmc/host/tmio_mmc_core.c @@ -887,16 +887,20 @@ static void tmio_mmc_set_bus_width(struct tmio_mmc_host *host, sd_ctrl_write16(host, CTL_SD_MEM_CARD_OPT, reg); } -static void tmio_mmc_max_busy_timeout(struct tmio_mmc_host *host) +static unsigned int tmio_mmc_get_timeout_cycles(struct tmio_mmc_host *host) { u16 val = sd_ctrl_read16(host, CTL_SD_MEM_CARD_OPT); - unsigned int clk_rate = host->mmc->actual_clock ?: host->mmc->f_max; - unsigned int cycles; val = (val & CARD_OPT_TOP_MASK) >> CARD_OPT_TOP_SHIFT; - cycles = 1 << (13 + val); + return 1 << (13 + val); +} - host->mmc->max_busy_timeout = cycles / (clk_rate / MSEC_PER_SEC); +static void tmio_mmc_max_busy_timeout(struct tmio_mmc_host *host) +{ + unsigned int clk_rate = host->mmc->actual_clock ?: host->mmc->f_max; + + host->mmc->max_busy_timeout = host->get_timeout_cycles(host) / + (clk_rate / MSEC_PER_SEC); } /* Set MMC clock / power. @@ -1116,6 +1120,9 @@ int tmio_mmc_host_probe(struct tmio_mmc_host *_host) if (!(pdata->flags & TMIO_MMC_HAS_IDLE_WAIT)) _host->write16_hook = NULL; + if (pdata->flags & TMIO_MMC_USE_BUSY_TIMEOUT && !_host->get_timeout_cycles) + _host->get_timeout_cycles = tmio_mmc_get_timeout_cycles; + _host->set_pwr = pdata->set_pwr; ret = tmio_mmc_init_ocr(_host); From b191deced78a12e26a827db03745b0da6cbc4f0e Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Wed, 25 Nov 2020 22:30:01 +0100 Subject: [PATCH 085/102] mmc: renesas_sdhi: populate hook for longer busy_wait Make use of the EXTOP bit in R-Car Gen3 SoCs to have a twice as large busy wait duration. Signed-off-by: Wolfram Sang Reviewed-by: Yoshihiro Shimoda Tested-by: Yoshihiro Shimoda Link: https://lore.kernel.org/r/20201125213001.15003-4-wsa+renesas@sang-engineering.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/renesas_sdhi_core.c | 20 ++++++++++++++++++++ drivers/mmc/host/tmio_mmc.h | 2 ++ 2 files changed, 22 insertions(+) diff --git a/drivers/mmc/host/renesas_sdhi_core.c b/drivers/mmc/host/renesas_sdhi_core.c index 153767054c05..38f028e70633 100644 --- a/drivers/mmc/host/renesas_sdhi_core.c +++ b/drivers/mmc/host/renesas_sdhi_core.c @@ -561,6 +561,7 @@ static int renesas_sdhi_prepare_hs400_tuning(struct mmc_host *mmc, struct mmc_io static void renesas_sdhi_reset(struct tmio_mmc_host *host) { struct renesas_sdhi *priv = host_to_priv(host); + u16 val; if (priv->scc_ctl) { renesas_sdhi_disable_scc(host->mmc); @@ -573,6 +574,21 @@ static void renesas_sdhi_reset(struct tmio_mmc_host *host) } sd_ctrl_write32_as_16_and_16(host, CTL_IRQ_MASK, TMIO_MASK_INIT_RCAR2); + + if (sd_ctrl_read16(host, CTL_VERSION) >= SDHI_VER_GEN3_SD) { + val = sd_ctrl_read16(host, CTL_SD_MEM_CARD_OPT); + val |= CARD_OPT_EXTOP; + sd_ctrl_write16(host, CTL_SD_MEM_CARD_OPT, val); + } +} + +static unsigned int renesas_sdhi_gen3_get_cycles(struct tmio_mmc_host *host) +{ + u16 num, val = sd_ctrl_read16(host, CTL_SD_MEM_CARD_OPT); + + num = (val & CARD_OPT_TOP_MASK) >> CARD_OPT_TOP_SHIFT; + return 1 << ((val & CARD_OPT_EXTOP ? 14 : 13) + num); + } #define SH_MOBILE_SDHI_MIN_TAP_ROW 3 @@ -1067,6 +1083,10 @@ int renesas_sdhi_probe(struct platform_device *pdev, quirks->hs400_calib_table + 1); } + /* these have an EXTOP bit */ + if (ver >= SDHI_VER_GEN3_SD) + host->get_timeout_cycles = renesas_sdhi_gen3_get_cycles; + /* Enable tuning iff we have an SCC and a supported mode */ if (of_data && of_data->scc_offset && (host->mmc->caps & MMC_CAP_UHS_SDR104 || diff --git a/drivers/mmc/host/tmio_mmc.h b/drivers/mmc/host/tmio_mmc.h index f60559bc413a..784fa6ed5843 100644 --- a/drivers/mmc/host/tmio_mmc.h +++ b/drivers/mmc/host/tmio_mmc.h @@ -82,7 +82,9 @@ /* Definitions for values the CTL_SD_MEM_CARD_OPT register can take */ #define CARD_OPT_TOP_MASK 0xf0 #define CARD_OPT_TOP_SHIFT 4 +#define CARD_OPT_EXTOP BIT(9) /* first appeared on R-Car Gen3 SDHI */ #define CARD_OPT_WIDTH8 BIT(13) +#define CARD_OPT_ALWAYS1 BIT(14) #define CARD_OPT_WIDTH BIT(15) /* Definitions for values the CTL_SDIO_STATUS register can take */ From 2a394808580d847c1af2c1e431255e32bfb0ae33 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Wed, 2 Dec 2020 14:16:31 +0100 Subject: [PATCH 086/102] dt-bindings: mmc: Fix xlnx,mio-bank property values for arasan driver Xilinx ZynqMP has 3 mio banks and all of them are valid. That's why also list the first one which is missing. Property is enumeration not range. Signed-off-by: Michal Simek Link: https://lore.kernel.org/r/5fa17dfe4b42abefd84b4cbb7b8bcd4d31398f40.1606914986.git.michal.simek@xilinx.com Signed-off-by: Ulf Hansson --- Documentation/devicetree/bindings/mmc/arasan,sdhci.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/mmc/arasan,sdhci.yaml b/Documentation/devicetree/bindings/mmc/arasan,sdhci.yaml index 0753289fba84..37a5fe7b26dc 100644 --- a/Documentation/devicetree/bindings/mmc/arasan,sdhci.yaml +++ b/Documentation/devicetree/bindings/mmc/arasan,sdhci.yaml @@ -147,7 +147,7 @@ properties: xlnx,mio-bank: $ref: /schemas/types.yaml#/definitions/uint32 - enum: [0, 2] + enum: [0, 1, 2] default: 0 description: The MIO bank number in which the command and data lines are configured. From f7414cd6923fd7f78e57086fc964ba2dc25db5c1 Mon Sep 17 00:00:00 2001 From: Biwen Li Date: Wed, 11 Nov 2020 19:32:55 +0800 Subject: [PATCH 087/102] i2c: imx: support slave mode for imx I2C driver The patch supports slave mode for imx I2C driver Signed-off-by: Biwen Li Acked-by: Oleksij Rempel Signed-off-by: Wolfram Sang --- drivers/i2c/busses/Kconfig | 1 + drivers/i2c/busses/i2c-imx.c | 219 +++++++++++++++++++++++++++++++---- 2 files changed, 196 insertions(+), 24 deletions(-) diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index a49e0ed4a599..d4d60ad0eda0 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -675,6 +675,7 @@ config I2C_IMG config I2C_IMX tristate "IMX I2C interface" depends on ARCH_MXC || ARCH_LAYERSCAPE || COLDFIRE + select I2C_SLAVE help Say Y here if you want to use the IIC bus controller on the Freescale i.MX/MXC, Layerscape or ColdFire processors. diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c index a04d17c28339..b444fbf1a262 100644 --- a/drivers/i2c/busses/i2c-imx.c +++ b/drivers/i2c/busses/i2c-imx.c @@ -17,6 +17,7 @@ * Copyright (C) 2008 Darius Augulis * * Copyright 2013 Freescale Semiconductor, Inc. + * Copyright 2020 NXP * */ @@ -73,6 +74,11 @@ #define IMX_I2C_I2SR 0x03 /* i2c status */ #define IMX_I2C_I2DR 0x04 /* i2c transfer data */ +/* + * All of the layerscape series SoCs support IBIC register. + */ +#define IMX_I2C_IBIC 0x05 /* i2c bus interrupt config */ + #define IMX_I2C_REGSHIFT 2 #define VF610_I2C_REGSHIFT 0 @@ -91,6 +97,7 @@ #define I2CR_MSTA 0x20 #define I2CR_IIEN 0x40 #define I2CR_IEN 0x80 +#define IBIC_BIIE 0x80 /* Bus idle interrupt enable */ /* register bits different operating codes definition: * 1) I2SR: Interrupt flags clear operation differ between SoCs: @@ -201,6 +208,7 @@ struct imx_i2c_struct { struct pinctrl_state *pinctrl_pins_gpio; struct imx_i2c_dma *dma; + struct i2c_client *slave; }; static const struct imx_i2c_hwdata imx1_i2c_hwdata = { @@ -252,6 +260,11 @@ static inline int is_imx1_i2c(struct imx_i2c_struct *i2c_imx) return i2c_imx->hwdata->devtype == IMX1_I2C; } +static inline int is_vf610_i2c(struct imx_i2c_struct *i2c_imx) +{ + return i2c_imx->hwdata->devtype == VF610_I2C; +} + static inline void imx_i2c_write_reg(unsigned int val, struct imx_i2c_struct *i2c_imx, unsigned int reg) { @@ -264,6 +277,27 @@ static inline unsigned char imx_i2c_read_reg(struct imx_i2c_struct *i2c_imx, return readb(i2c_imx->base + (reg << i2c_imx->hwdata->regshift)); } +static void i2c_imx_clear_irq(struct imx_i2c_struct *i2c_imx, unsigned int bits) +{ + unsigned int temp; + + /* + * i2sr_clr_opcode is the value to clear all interrupts. Here we want to + * clear only , so we write ~i2sr_clr_opcode with just + * toggled. This is required because i.MX needs W0C and Vybrid uses W1C. + */ + temp = ~i2c_imx->hwdata->i2sr_clr_opcode ^ bits; + imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2SR); +} + +/* Set up i2c controller register and i2c status register to default value. */ +static void i2c_imx_reset_regs(struct imx_i2c_struct *i2c_imx) +{ + imx_i2c_write_reg(i2c_imx->hwdata->i2cr_ien_opcode ^ I2CR_IEN, + i2c_imx, IMX_I2C_I2CR); + i2c_imx_clear_irq(i2c_imx, I2SR_IIF | I2SR_IAL); +} + /* Functions for DMA support */ static void i2c_imx_dma_request(struct imx_i2c_struct *i2c_imx, dma_addr_t phy_addr) @@ -399,19 +433,6 @@ static void i2c_imx_dma_free(struct imx_i2c_struct *i2c_imx) dma->chan_using = NULL; } -static void i2c_imx_clear_irq(struct imx_i2c_struct *i2c_imx, unsigned int bits) -{ - unsigned int temp; - - /* - * i2sr_clr_opcode is the value to clear all interrupts. Here we want to - * clear only , so we write ~i2sr_clr_opcode with just - * toggled. This is required because i.MX needs W0C and Vybrid uses W1C. - */ - temp = ~i2c_imx->hwdata->i2sr_clr_opcode ^ bits; - imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2SR); -} - static int i2c_imx_bus_busy(struct imx_i2c_struct *i2c_imx, int for_busy, bool atomic) { unsigned long orig_jiffies = jiffies; @@ -625,18 +646,165 @@ static void i2c_imx_stop(struct imx_i2c_struct *i2c_imx, bool atomic) imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR); } +/* + * Enable bus idle interrupts + * Note: IBIC register will be cleared after disabled i2c module. + * All of layerscape series SoCs support IBIC register. + */ +static void i2c_imx_enable_bus_idle(struct imx_i2c_struct *i2c_imx) +{ + if (is_vf610_i2c(i2c_imx)) { + unsigned int temp; + + temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_IBIC); + temp |= IBIC_BIIE; + imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_IBIC); + } +} + +static irqreturn_t i2c_imx_slave_isr(struct imx_i2c_struct *i2c_imx, + unsigned int status, unsigned int ctl) +{ + u8 value; + + if (status & I2SR_IAL) { /* Arbitration lost */ + i2c_imx_clear_irq(i2c_imx, I2SR_IAL); + if (!(status & I2SR_IAAS)) + return IRQ_HANDLED; + } + + if (status & I2SR_IAAS) { /* Addressed as a slave */ + if (status & I2SR_SRW) { /* Master wants to read from us*/ + dev_dbg(&i2c_imx->adapter.dev, "read requested"); + i2c_slave_event(i2c_imx->slave, I2C_SLAVE_READ_REQUESTED, &value); + + /* Slave transmit */ + ctl |= I2CR_MTX; + imx_i2c_write_reg(ctl, i2c_imx, IMX_I2C_I2CR); + + /* Send data */ + imx_i2c_write_reg(value, i2c_imx, IMX_I2C_I2DR); + } else { /* Master wants to write to us */ + dev_dbg(&i2c_imx->adapter.dev, "write requested"); + i2c_slave_event(i2c_imx->slave, I2C_SLAVE_WRITE_REQUESTED, &value); + + /* Slave receive */ + ctl &= ~I2CR_MTX; + imx_i2c_write_reg(ctl, i2c_imx, IMX_I2C_I2CR); + /* Dummy read */ + imx_i2c_read_reg(i2c_imx, IMX_I2C_I2DR); + } + } else if (!(ctl & I2CR_MTX)) { /* Receive mode */ + if (status & I2SR_IBB) { /* No STOP signal detected */ + value = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2DR); + i2c_slave_event(i2c_imx->slave, I2C_SLAVE_WRITE_RECEIVED, &value); + } else { /* STOP signal is detected */ + dev_dbg(&i2c_imx->adapter.dev, + "STOP signal detected"); + i2c_slave_event(i2c_imx->slave, I2C_SLAVE_STOP, &value); + } + } else if (!(status & I2SR_RXAK)) { /* Transmit mode received ACK */ + ctl |= I2CR_MTX; + imx_i2c_write_reg(ctl, i2c_imx, IMX_I2C_I2CR); + + i2c_slave_event(i2c_imx->slave, I2C_SLAVE_READ_PROCESSED, &value); + + imx_i2c_write_reg(value, i2c_imx, IMX_I2C_I2DR); + } else { /* Transmit mode received NAK */ + ctl &= ~I2CR_MTX; + imx_i2c_write_reg(ctl, i2c_imx, IMX_I2C_I2CR); + imx_i2c_read_reg(i2c_imx, IMX_I2C_I2DR); + } + + return IRQ_HANDLED; +} + +static void i2c_imx_slave_init(struct imx_i2c_struct *i2c_imx) +{ + int temp; + + /* Set slave addr. */ + imx_i2c_write_reg((i2c_imx->slave->addr << 1), i2c_imx, IMX_I2C_IADR); + + i2c_imx_reset_regs(i2c_imx); + + /* Enable module */ + temp = i2c_imx->hwdata->i2cr_ien_opcode; + imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR); + + /* Enable interrupt from i2c module */ + temp |= I2CR_IIEN; + imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR); + + i2c_imx_enable_bus_idle(i2c_imx); +} + +static int i2c_imx_reg_slave(struct i2c_client *client) +{ + struct imx_i2c_struct *i2c_imx = i2c_get_adapdata(client->adapter); + int ret; + + if (i2c_imx->slave) + return -EBUSY; + + i2c_imx->slave = client; + + /* Resume */ + ret = pm_runtime_get_sync(i2c_imx->adapter.dev.parent); + if (ret < 0) { + dev_err(&i2c_imx->adapter.dev, "failed to resume i2c controller"); + return ret; + } + + i2c_imx_slave_init(i2c_imx); + + return 0; +} + +static int i2c_imx_unreg_slave(struct i2c_client *client) +{ + struct imx_i2c_struct *i2c_imx = i2c_get_adapdata(client->adapter); + int ret; + + if (!i2c_imx->slave) + return -EINVAL; + + /* Reset slave address. */ + imx_i2c_write_reg(0, i2c_imx, IMX_I2C_IADR); + + i2c_imx_reset_regs(i2c_imx); + + i2c_imx->slave = NULL; + + /* Suspend */ + ret = pm_runtime_put_sync(i2c_imx->adapter.dev.parent); + if (ret < 0) + dev_err(&i2c_imx->adapter.dev, "failed to suspend i2c controller"); + + return ret; +} + +static irqreturn_t i2c_imx_master_isr(struct imx_i2c_struct *i2c_imx, unsigned int status) +{ + /* save status register */ + i2c_imx->i2csr = status; + wake_up(&i2c_imx->queue); + + return IRQ_HANDLED; +} + static irqreturn_t i2c_imx_isr(int irq, void *dev_id) { struct imx_i2c_struct *i2c_imx = dev_id; - unsigned int temp; + unsigned int ctl, status; - temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2SR); - if (temp & I2SR_IIF) { - /* save status register */ - i2c_imx->i2csr = temp; + status = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2SR); + ctl = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR); + if (status & I2SR_IIF) { i2c_imx_clear_irq(i2c_imx, I2SR_IIF); - wake_up(&i2c_imx->queue); - return IRQ_HANDLED; + if (i2c_imx->slave && !(ctl & I2CR_MSTA)) + return i2c_imx_slave_isr(i2c_imx, status, ctl); + return i2c_imx_master_isr(i2c_imx, status); } return IRQ_NONE; @@ -1014,6 +1182,10 @@ static int i2c_imx_xfer_common(struct i2c_adapter *adapter, dev_dbg(&i2c_imx->adapter.dev, "<%s> exit with: %s: %d\n", __func__, (result < 0) ? "error" : "success msg", (result < 0) ? result : num); + /* After data is transferred, switch to slave mode(as a receiver) */ + if (i2c_imx->slave) + i2c_imx_slave_init(i2c_imx); + return (result < 0) ? result : num; } @@ -1127,6 +1299,8 @@ static const struct i2c_algorithm i2c_imx_algo = { .master_xfer = i2c_imx_xfer, .master_xfer_atomic = i2c_imx_xfer_atomic, .functionality = i2c_imx_func, + .reg_slave = i2c_imx_reg_slave, + .unreg_slave = i2c_imx_unreg_slave, }; static int i2c_imx_probe(struct platform_device *pdev) @@ -1216,10 +1390,7 @@ static int i2c_imx_probe(struct platform_device *pdev) clk_notifier_register(i2c_imx->clk, &i2c_imx->clk_change_nb); i2c_imx_set_clk(i2c_imx, clk_get_rate(i2c_imx->clk)); - /* Set up chip registers to defaults */ - imx_i2c_write_reg(i2c_imx->hwdata->i2cr_ien_opcode ^ I2CR_IEN, - i2c_imx, IMX_I2C_I2CR); - imx_i2c_write_reg(i2c_imx->hwdata->i2sr_clr_opcode, i2c_imx, IMX_I2C_I2SR); + i2c_imx_reset_regs(i2c_imx); /* Init optional bus recovery function */ ret = i2c_imx_init_recovery_info(i2c_imx, pdev); From 730f205190a15439c8896f420cde6bbe50c454c2 Mon Sep 17 00:00:00 2001 From: Cristian Ciocaltea Date: Fri, 20 Nov 2020 01:56:04 +0200 Subject: [PATCH 088/102] dt-bindings: i2c: owl: Convert Actions Semi Owl binding to a schema Convert the Actions Semi Owl I2C DT binding to a YAML schema for enabling DT validation. Additionally, add a new compatible string corresponding to the I2C controller found in the S500 variant of the Actions Semi Owl SoCs family. Signed-off-by: Cristian Ciocaltea Reviewed-by: Rob Herring Signed-off-by: Wolfram Sang --- .../devicetree/bindings/i2c/i2c-owl.txt | 29 --------- .../devicetree/bindings/i2c/i2c-owl.yaml | 62 +++++++++++++++++++ MAINTAINERS | 2 +- 3 files changed, 63 insertions(+), 30 deletions(-) delete mode 100644 Documentation/devicetree/bindings/i2c/i2c-owl.txt create mode 100644 Documentation/devicetree/bindings/i2c/i2c-owl.yaml diff --git a/Documentation/devicetree/bindings/i2c/i2c-owl.txt b/Documentation/devicetree/bindings/i2c/i2c-owl.txt deleted file mode 100644 index 54c05dbdb2e4..000000000000 --- a/Documentation/devicetree/bindings/i2c/i2c-owl.txt +++ /dev/null @@ -1,29 +0,0 @@ -Actions Semiconductor Owl I2C controller - -Required properties: - -- compatible : Should be one of the following: - - "actions,s700-i2c" for S700 SoC - - "actions,s900-i2c" for S900 SoC -- reg : Offset and length of the register set for the device. -- #address-cells : Should be 1. -- #size-cells : Should be 0. -- interrupts : A single interrupt specifier. -- clocks : Phandle of the clock feeding the I2C controller. - -Optional properties: - -- clock-frequency : Desired I2C bus clock frequency in Hz. As only Normal and - Fast modes are supported, possible values are 100000 and - 400000. -Examples: - - i2c0: i2c@e0170000 { - compatible = "actions,s900-i2c"; - reg = <0 0xe0170000 0 0x1000>; - #address-cells = <1>; - #size-cells = <0>; - interrupts = ; - clocks = <&clock CLK_I2C0>; - clock-frequency = <100000>; - }; diff --git a/Documentation/devicetree/bindings/i2c/i2c-owl.yaml b/Documentation/devicetree/bindings/i2c/i2c-owl.yaml new file mode 100644 index 000000000000..d96908badf81 --- /dev/null +++ b/Documentation/devicetree/bindings/i2c/i2c-owl.yaml @@ -0,0 +1,62 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/i2c/i2c-owl.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Actions Semi Owl I2C Controller + +maintainers: + - Manivannan Sadhasivam + +description: | + This I2C controller is found in the Actions Semi Owl SoCs: + S500, S700 and S900. + +allOf: + - $ref: /schemas/i2c/i2c-controller.yaml# + +properties: + compatible: + enum: + - actions,s500-i2c # Actions Semi S500 compatible SoCs + - actions,s700-i2c # Actions Semi S700 compatible SoCs + - actions,s900-i2c # Actions Semi S900 compatible SoCs + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + clocks: + description: Phandle of the clock feeding the I2C controller. + minItems: 1 + + clock-frequency: + description: | + Desired I2C bus clock frequency in Hz. As only Standard and Fast + modes are supported, possible values are 100000 and 400000. + enum: [100000, 400000] + +required: + - compatible + - reg + - interrupts + - clocks + +unevaluatedProperties: false + +examples: + - | + #include + #include + i2c@e0170000 { + compatible = "actions,s900-i2c"; + reg = <0xe0170000 0x1000>; + interrupts = ; + clocks = <&cmu CLK_I2C0>; + clock-frequency = <100000>; + }; + +... diff --git a/MAINTAINERS b/MAINTAINERS index 1d097b9da354..693207a781ab 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1501,7 +1501,7 @@ S: Maintained F: Documentation/devicetree/bindings/arm/actions.yaml F: Documentation/devicetree/bindings/clock/actions,owl-cmu.txt F: Documentation/devicetree/bindings/dma/owl-dma.yaml -F: Documentation/devicetree/bindings/i2c/i2c-owl.txt +F: Documentation/devicetree/bindings/i2c/i2c-owl.yaml F: Documentation/devicetree/bindings/interrupt-controller/actions,owl-sirq.yaml F: Documentation/devicetree/bindings/mmc/owl-mmc.yaml F: Documentation/devicetree/bindings/pinctrl/actions,* From 04fd6f0a9e678b62831104182354e03a5c901280 Mon Sep 17 00:00:00 2001 From: Cristian Ciocaltea Date: Fri, 20 Nov 2020 01:56:06 +0200 Subject: [PATCH 089/102] i2c: owl: Add compatible for the Actions Semi S500 I2C controller Add S500 variant to the list of devices supported by the Actions Semi Owl I2C driver. Signed-off-by: Cristian Ciocaltea Reviewed-by: Manivannan Sadhasivam Reviewed-by: Manivannan Sadhasivam Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-owl.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/i2c/busses/i2c-owl.c b/drivers/i2c/busses/i2c-owl.c index 5cf5a119a6ad..98882fe4e965 100644 --- a/drivers/i2c/busses/i2c-owl.c +++ b/drivers/i2c/busses/i2c-owl.c @@ -508,6 +508,7 @@ static int owl_i2c_probe(struct platform_device *pdev) } static const struct of_device_id owl_i2c_of_match[] = { + { .compatible = "actions,s500-i2c" }, { .compatible = "actions,s700-i2c" }, { .compatible = "actions,s900-i2c" }, { /* sentinel */ } From e8a61e5a7e2abb71168092b403f8524a0af1f1d3 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 13 Oct 2020 16:12:01 +0200 Subject: [PATCH 090/102] i2c: sh_mobile: Mark adapter suspended during suspend When a driver tries to send an I2C message while the adapter is suspended, this typically fails with: i2c-sh_mobile e60b0000.i2c: Transfer request timed out Avoid accessing the adapter while it is suspended by marking it suspended during suspend. This allows the I2C core to catch this, and print a warning: WARNING: CPU: 1 PID: 13 at drivers/i2c/i2c-core.h:54 __i2c_transfer+0x4a4/0x4e4 i2c i2c-6: Transfer while suspended Signed-off-by: Geert Uytterhoeven Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-sh_mobile.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/drivers/i2c/busses/i2c-sh_mobile.c b/drivers/i2c/busses/i2c-sh_mobile.c index bdd60770779a..3ae6ca21a02c 100644 --- a/drivers/i2c/busses/i2c-sh_mobile.c +++ b/drivers/i2c/busses/i2c-sh_mobile.c @@ -956,10 +956,38 @@ static int sh_mobile_i2c_remove(struct platform_device *dev) return 0; } +#ifdef CONFIG_PM_SLEEP +static int sh_mobile_i2c_suspend(struct device *dev) +{ + struct sh_mobile_i2c_data *pd = dev_get_drvdata(dev); + + i2c_mark_adapter_suspended(&pd->adap); + return 0; +} + +static int sh_mobile_i2c_resume(struct device *dev) +{ + struct sh_mobile_i2c_data *pd = dev_get_drvdata(dev); + + i2c_mark_adapter_resumed(&pd->adap); + return 0; +} + +static const struct dev_pm_ops sh_mobile_i2c_pm_ops = { + SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(sh_mobile_i2c_suspend, + sh_mobile_i2c_resume) +}; + +#define DEV_PM_OPS (&sh_mobile_i2c_pm_ops) +#else +#define DEV_PM_OPS NULL +#endif /* CONFIG_PM_SLEEP */ + static struct platform_driver sh_mobile_i2c_driver = { .driver = { .name = "i2c-sh_mobile", .of_match_table = sh_mobile_i2c_dt_ids, + .pm = DEV_PM_OPS, }, .probe = sh_mobile_i2c_probe, .remove = sh_mobile_i2c_remove, From 0b01392c18b9993a584f36ace1d61118772ad0ca Mon Sep 17 00:00:00 2001 From: Codrin Ciubotariu Date: Sun, 4 Oct 2020 13:07:11 +0300 Subject: [PATCH 091/102] i2c: pxa: move to generic GPIO recovery Starting with commit 75820314de26 ("i2c: core: add generic I2C GPIO recovery") GPIO bus recovery is supported by the I2C core, so we can remove the driver implementation and use that one instead. Signed-off-by: Codrin Ciubotariu Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-pxa.c | 76 ++++-------------------------------- 1 file changed, 8 insertions(+), 68 deletions(-) diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c index 35ca2c02c9b9..a636ea0eb50a 100644 --- a/drivers/i2c/busses/i2c-pxa.c +++ b/drivers/i2c/busses/i2c-pxa.c @@ -264,9 +264,6 @@ struct pxa_i2c { u32 hs_mask; struct i2c_bus_recovery_info recovery; - struct pinctrl *pinctrl; - struct pinctrl_state *pinctrl_default; - struct pinctrl_state *pinctrl_recovery; }; #define _IBMR(i2c) ((i2c)->reg_ibmr) @@ -1305,13 +1302,12 @@ static void i2c_pxa_prepare_recovery(struct i2c_adapter *adap) */ gpiod_set_value(i2c->recovery.scl_gpiod, ibmr & IBMR_SCLS); gpiod_set_value(i2c->recovery.sda_gpiod, ibmr & IBMR_SDAS); - - WARN_ON(pinctrl_select_state(i2c->pinctrl, i2c->pinctrl_recovery)); } static void i2c_pxa_unprepare_recovery(struct i2c_adapter *adap) { struct pxa_i2c *i2c = adap->algo_data; + struct i2c_bus_recovery_info *bri = adap->bus_recovery_info; u32 isr; /* @@ -1325,7 +1321,7 @@ static void i2c_pxa_unprepare_recovery(struct i2c_adapter *adap) i2c_pxa_do_reset(i2c); } - WARN_ON(pinctrl_select_state(i2c->pinctrl, i2c->pinctrl_default)); + WARN_ON(pinctrl_select_state(bri->pinctrl, bri->pins_default)); dev_dbg(&i2c->adap.dev, "recovery: IBMR 0x%08x ISR 0x%08x\n", readl(_IBMR(i2c)), readl(_ISR(i2c))); @@ -1347,76 +1343,20 @@ static int i2c_pxa_init_recovery(struct pxa_i2c *i2c) if (IS_ENABLED(CONFIG_I2C_PXA_SLAVE)) return 0; - i2c->pinctrl = devm_pinctrl_get(dev); - if (PTR_ERR(i2c->pinctrl) == -ENODEV) - i2c->pinctrl = NULL; - if (IS_ERR(i2c->pinctrl)) - return PTR_ERR(i2c->pinctrl); - - if (!i2c->pinctrl) - return 0; - - i2c->pinctrl_default = pinctrl_lookup_state(i2c->pinctrl, - PINCTRL_STATE_DEFAULT); - i2c->pinctrl_recovery = pinctrl_lookup_state(i2c->pinctrl, "recovery"); - - if (IS_ERR(i2c->pinctrl_default) || IS_ERR(i2c->pinctrl_recovery)) { - dev_info(dev, "missing pinmux recovery information: %ld %ld\n", - PTR_ERR(i2c->pinctrl_default), - PTR_ERR(i2c->pinctrl_recovery)); - return 0; - } - - /* - * Claiming GPIOs can influence the pinmux state, and may glitch the - * I2C bus. Do this carefully. - */ - bri->scl_gpiod = devm_gpiod_get(dev, "scl", GPIOD_OUT_HIGH_OPEN_DRAIN); - if (bri->scl_gpiod == ERR_PTR(-EPROBE_DEFER)) - return -EPROBE_DEFER; - if (IS_ERR(bri->scl_gpiod)) { - dev_info(dev, "missing scl gpio recovery information: %pe\n", - bri->scl_gpiod); - return 0; - } - - /* - * We have SCL. Pull SCL low and wait a bit so that SDA glitches - * have no effect. - */ - gpiod_direction_output(bri->scl_gpiod, 0); - udelay(10); - bri->sda_gpiod = devm_gpiod_get(dev, "sda", GPIOD_OUT_HIGH_OPEN_DRAIN); - - /* Wait a bit in case of a SDA glitch, and then release SCL. */ - udelay(10); - gpiod_direction_output(bri->scl_gpiod, 1); - - if (bri->sda_gpiod == ERR_PTR(-EPROBE_DEFER)) - return -EPROBE_DEFER; - - if (IS_ERR(bri->sda_gpiod)) { - dev_info(dev, "missing sda gpio recovery information: %pe\n", - bri->sda_gpiod); + bri->pinctrl = devm_pinctrl_get(dev); + if (PTR_ERR(bri->pinctrl) == -ENODEV) { + bri->pinctrl = NULL; return 0; } + if (IS_ERR(bri->pinctrl)) + return PTR_ERR(bri->pinctrl); bri->prepare_recovery = i2c_pxa_prepare_recovery; bri->unprepare_recovery = i2c_pxa_unprepare_recovery; - bri->recover_bus = i2c_generic_scl_recovery; i2c->adap.bus_recovery_info = bri; - /* - * Claiming GPIOs can change the pinmux state, which confuses the - * pinctrl since pinctrl's idea of the current setting is unaffected - * by the pinmux change caused by claiming the GPIO. Work around that - * by switching pinctrl to the GPIO state here. We do it this way to - * avoid glitching the I2C bus. - */ - pinctrl_select_state(i2c->pinctrl, i2c->pinctrl_recovery); - - return pinctrl_select_state(i2c->pinctrl, i2c->pinctrl_default); + return 0; } static int i2c_pxa_probe(struct platform_device *dev) From a5df4c14b9a9c576cd8229deb87da21aeb8aa82c Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 8 Dec 2020 16:03:35 +0200 Subject: [PATCH 092/102] i2c: designware: Switch header to use BIT() and GENMASK() Currently header file uses partially BIT() and GENMASK() macros. Switch it to use those macros in all cases where it's applicable for the sake of consistency. Signed-off-by: Andy Shevchenko Acked-by: Jarkko Nikula Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-designware-core.h | 92 ++++++++++++------------ 1 file changed, 46 insertions(+), 46 deletions(-) diff --git a/drivers/i2c/busses/i2c-designware-core.h b/drivers/i2c/busses/i2c-designware-core.h index eb5ef4d0f463..c129074be63c 100644 --- a/drivers/i2c/busses/i2c-designware-core.h +++ b/drivers/i2c/busses/i2c-designware-core.h @@ -25,18 +25,18 @@ I2C_FUNC_SMBUS_BLOCK_DATA | \ I2C_FUNC_SMBUS_I2C_BLOCK) -#define DW_IC_CON_MASTER 0x1 -#define DW_IC_CON_SPEED_STD 0x2 -#define DW_IC_CON_SPEED_FAST 0x4 -#define DW_IC_CON_SPEED_HIGH 0x6 -#define DW_IC_CON_SPEED_MASK 0x6 -#define DW_IC_CON_10BITADDR_SLAVE 0x8 -#define DW_IC_CON_10BITADDR_MASTER 0x10 -#define DW_IC_CON_RESTART_EN 0x20 -#define DW_IC_CON_SLAVE_DISABLE 0x40 -#define DW_IC_CON_STOP_DET_IFADDRESSED 0x80 -#define DW_IC_CON_TX_EMPTY_CTRL 0x100 -#define DW_IC_CON_RX_FIFO_FULL_HLD_CTRL 0x200 +#define DW_IC_CON_MASTER BIT(0) +#define DW_IC_CON_SPEED_STD (1 << 1) +#define DW_IC_CON_SPEED_FAST (2 << 1) +#define DW_IC_CON_SPEED_HIGH (3 << 1) +#define DW_IC_CON_SPEED_MASK GENMASK(2, 1) +#define DW_IC_CON_10BITADDR_SLAVE BIT(3) +#define DW_IC_CON_10BITADDR_MASTER BIT(4) +#define DW_IC_CON_RESTART_EN BIT(5) +#define DW_IC_CON_SLAVE_DISABLE BIT(6) +#define DW_IC_CON_STOP_DET_IFADDRESSED BIT(7) +#define DW_IC_CON_TX_EMPTY_CTRL BIT(8) +#define DW_IC_CON_RX_FIFO_FULL_HLD_CTRL BIT(9) /* * Registers offset @@ -81,19 +81,19 @@ #define DW_IC_COMP_TYPE 0xfc #define DW_IC_COMP_TYPE_VALUE 0x44570140 -#define DW_IC_INTR_RX_UNDER 0x001 -#define DW_IC_INTR_RX_OVER 0x002 -#define DW_IC_INTR_RX_FULL 0x004 -#define DW_IC_INTR_TX_OVER 0x008 -#define DW_IC_INTR_TX_EMPTY 0x010 -#define DW_IC_INTR_RD_REQ 0x020 -#define DW_IC_INTR_TX_ABRT 0x040 -#define DW_IC_INTR_RX_DONE 0x080 -#define DW_IC_INTR_ACTIVITY 0x100 -#define DW_IC_INTR_STOP_DET 0x200 -#define DW_IC_INTR_START_DET 0x400 -#define DW_IC_INTR_GEN_CALL 0x800 -#define DW_IC_INTR_RESTART_DET 0x1000 +#define DW_IC_INTR_RX_UNDER BIT(0) +#define DW_IC_INTR_RX_OVER BIT(1) +#define DW_IC_INTR_RX_FULL BIT(2) +#define DW_IC_INTR_TX_OVER BIT(3) +#define DW_IC_INTR_TX_EMPTY BIT(4) +#define DW_IC_INTR_RD_REQ BIT(5) +#define DW_IC_INTR_TX_ABRT BIT(6) +#define DW_IC_INTR_RX_DONE BIT(7) +#define DW_IC_INTR_ACTIVITY BIT(8) +#define DW_IC_INTR_STOP_DET BIT(9) +#define DW_IC_INTR_START_DET BIT(10) +#define DW_IC_INTR_GEN_CALL BIT(11) +#define DW_IC_INTR_RESTART_DET BIT(12) #define DW_IC_INTR_DEFAULT_MASK (DW_IC_INTR_RX_FULL | \ DW_IC_INTR_TX_ABRT | \ @@ -105,13 +105,13 @@ DW_IC_INTR_RX_UNDER | \ DW_IC_INTR_RD_REQ) -#define DW_IC_STATUS_ACTIVITY 0x1 +#define DW_IC_STATUS_ACTIVITY BIT(0) #define DW_IC_STATUS_TFE BIT(2) #define DW_IC_STATUS_MASTER_ACTIVITY BIT(5) #define DW_IC_STATUS_SLAVE_ACTIVITY BIT(6) #define DW_IC_SDA_HOLD_RX_SHIFT 16 -#define DW_IC_SDA_HOLD_RX_MASK GENMASK(23, DW_IC_SDA_HOLD_RX_SHIFT) +#define DW_IC_SDA_HOLD_RX_MASK GENMASK(23, 16) #define DW_IC_ERR_TX_ABRT 0x1 @@ -154,20 +154,20 @@ #define ABRT_SLAVE_ARBLOST 14 #define ABRT_SLAVE_RD_INTX 15 -#define DW_IC_TX_ABRT_7B_ADDR_NOACK (1UL << ABRT_7B_ADDR_NOACK) -#define DW_IC_TX_ABRT_10ADDR1_NOACK (1UL << ABRT_10ADDR1_NOACK) -#define DW_IC_TX_ABRT_10ADDR2_NOACK (1UL << ABRT_10ADDR2_NOACK) -#define DW_IC_TX_ABRT_TXDATA_NOACK (1UL << ABRT_TXDATA_NOACK) -#define DW_IC_TX_ABRT_GCALL_NOACK (1UL << ABRT_GCALL_NOACK) -#define DW_IC_TX_ABRT_GCALL_READ (1UL << ABRT_GCALL_READ) -#define DW_IC_TX_ABRT_SBYTE_ACKDET (1UL << ABRT_SBYTE_ACKDET) -#define DW_IC_TX_ABRT_SBYTE_NORSTRT (1UL << ABRT_SBYTE_NORSTRT) -#define DW_IC_TX_ABRT_10B_RD_NORSTRT (1UL << ABRT_10B_RD_NORSTRT) -#define DW_IC_TX_ABRT_MASTER_DIS (1UL << ABRT_MASTER_DIS) -#define DW_IC_TX_ARB_LOST (1UL << ARB_LOST) -#define DW_IC_RX_ABRT_SLAVE_RD_INTX (1UL << ABRT_SLAVE_RD_INTX) -#define DW_IC_RX_ABRT_SLAVE_ARBLOST (1UL << ABRT_SLAVE_ARBLOST) -#define DW_IC_RX_ABRT_SLAVE_FLUSH_TXFIFO (1UL << ABRT_SLAVE_FLUSH_TXFIFO) +#define DW_IC_TX_ABRT_7B_ADDR_NOACK BIT(ABRT_7B_ADDR_NOACK) +#define DW_IC_TX_ABRT_10ADDR1_NOACK BIT(ABRT_10ADDR1_NOACK) +#define DW_IC_TX_ABRT_10ADDR2_NOACK BIT(ABRT_10ADDR2_NOACK) +#define DW_IC_TX_ABRT_TXDATA_NOACK BIT(ABRT_TXDATA_NOACK) +#define DW_IC_TX_ABRT_GCALL_NOACK BIT(ABRT_GCALL_NOACK) +#define DW_IC_TX_ABRT_GCALL_READ BIT(ABRT_GCALL_READ) +#define DW_IC_TX_ABRT_SBYTE_ACKDET BIT(ABRT_SBYTE_ACKDET) +#define DW_IC_TX_ABRT_SBYTE_NORSTRT BIT(ABRT_SBYTE_NORSTRT) +#define DW_IC_TX_ABRT_10B_RD_NORSTRT BIT(ABRT_10B_RD_NORSTRT) +#define DW_IC_TX_ABRT_MASTER_DIS BIT(ABRT_MASTER_DIS) +#define DW_IC_TX_ARB_LOST BIT(ARB_LOST) +#define DW_IC_RX_ABRT_SLAVE_RD_INTX BIT(ABRT_SLAVE_RD_INTX) +#define DW_IC_RX_ABRT_SLAVE_ARBLOST BIT(ABRT_SLAVE_ARBLOST) +#define DW_IC_RX_ABRT_SLAVE_FLUSH_TXFIFO BIT(ABRT_SLAVE_FLUSH_TXFIFO) #define DW_IC_TX_ABRT_NOACK (DW_IC_TX_ABRT_7B_ADDR_NOACK | \ DW_IC_TX_ABRT_10ADDR1_NOACK | \ @@ -288,12 +288,12 @@ struct dw_i2c_dev { bool suspended; }; -#define ACCESS_INTR_MASK 0x00000001 -#define ACCESS_NO_IRQ_SUSPEND 0x00000002 +#define ACCESS_INTR_MASK BIT(0) +#define ACCESS_NO_IRQ_SUSPEND BIT(1) -#define MODEL_MSCC_OCELOT 0x00000100 -#define MODEL_BAIKAL_BT1 0x00000200 -#define MODEL_MASK 0x00000f00 +#define MODEL_MSCC_OCELOT BIT(8) +#define MODEL_BAIKAL_BT1 BIT(9) +#define MODEL_MASK GENMASK(11, 8) int i2c_dw_init_regmap(struct dw_i2c_dev *dev); u32 i2c_dw_scl_hcnt(u32 ic_clk, u32 tSYMBOL, u32 tf, int cond, int offset); From 8f95c13228116b56d42736b0849a55b97267806c Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 8 Dec 2020 16:03:36 +0200 Subject: [PATCH 093/102] i2c: designware: Make register offsets all of the same width For the sake of consistency add leading 0 to first register offsets to make them all of the same width. Signed-off-by: Andy Shevchenko Acked-by: Jarkko Nikula Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-designware-core.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/i2c/busses/i2c-designware-core.h b/drivers/i2c/busses/i2c-designware-core.h index c129074be63c..85307cfa7109 100644 --- a/drivers/i2c/busses/i2c-designware-core.h +++ b/drivers/i2c/busses/i2c-designware-core.h @@ -41,9 +41,9 @@ /* * Registers offset */ -#define DW_IC_CON 0x0 -#define DW_IC_TAR 0x4 -#define DW_IC_SAR 0x8 +#define DW_IC_CON 0x00 +#define DW_IC_TAR 0x04 +#define DW_IC_SAR 0x08 #define DW_IC_DATA_CMD 0x10 #define DW_IC_SS_SCL_HCNT 0x14 #define DW_IC_SS_SCL_LCNT 0x18 From cbfa5b3987c42fe5cd25747aee4fe654b1092fab Mon Sep 17 00:00:00 2001 From: Aswath Govindraju Date: Wed, 9 Dec 2020 22:27:33 +0530 Subject: [PATCH 094/102] dt-bindings: i2c: Add compatible string for AM64 SoC Add compatible string for AM64 SoC in device tree binding of OMAP I2C modules as the same IP is used. Signed-off-by: Aswath Govindraju Acked-by: Rob Herring Signed-off-by: Wolfram Sang --- Documentation/devicetree/bindings/i2c/i2c-omap.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/i2c/i2c-omap.txt b/Documentation/devicetree/bindings/i2c/i2c-omap.txt index a44573d7c118..a425b91af48f 100644 --- a/Documentation/devicetree/bindings/i2c/i2c-omap.txt +++ b/Documentation/devicetree/bindings/i2c/i2c-omap.txt @@ -8,6 +8,7 @@ Required properties : "ti,omap4-i2c" for OMAP4+ SoCs "ti,am654-i2c", "ti,omap4-i2c" for AM654 SoCs "ti,j721e-i2c", "ti,omap4-i2c" for J721E SoCs + "ti,am64-i2c", "ti,omap4-i2c" for AM64 SoCs - ti,hwmods : Must be "i2c", n being the instance number (1-based) - #address-cells = <1>; - #size-cells = <0>; From bfbccd70eee93c059e22d0d233f57cc164f03687 Mon Sep 17 00:00:00 2001 From: Yash Shah Date: Tue, 8 Dec 2020 10:25:38 +0530 Subject: [PATCH 095/102] dt-bindings: i2c: Update DT binding docs to support SiFive FU740 SoC Add new compatible strings to the DT binding documents to support SiFive FU740-C000. Signed-off-by: Yash Shah Reviewed-by: Rob Herring Signed-off-by: Wolfram Sang --- Documentation/devicetree/bindings/i2c/i2c-ocores.txt | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/i2c/i2c-ocores.txt b/Documentation/devicetree/bindings/i2c/i2c-ocores.txt index 6b25a80ae8d3..a37c9455b244 100644 --- a/Documentation/devicetree/bindings/i2c/i2c-ocores.txt +++ b/Documentation/devicetree/bindings/i2c/i2c-ocores.txt @@ -5,8 +5,12 @@ Required properties: "aeroflexgaisler,i2cmst" "sifive,fu540-c000-i2c", "sifive,i2c0" For Opencore based I2C IP block reimplemented in - FU540-C000 SoC. Please refer to sifive-blocks-ip-versioning.txt - for additional details. + FU540-C000 SoC. + "sifive,fu740-c000-i2c", "sifive,i2c0" + For Opencore based I2C IP block reimplemented in + FU740-C000 SoC. + Please refer to sifive-blocks-ip-versioning.txt for + additional details. - reg : bus address start and address range size of device - clocks : handle to the controller clock; see the note below. Mutually exclusive with opencores,ip-clock-frequency From f75fda3730728ea42bd1c210eaed96fb543ff00b Mon Sep 17 00:00:00 2001 From: Marcin Wojtas Date: Fri, 4 Dec 2020 18:16:23 +0100 Subject: [PATCH 096/102] mmc: sdhci-xenon: use match data for controllers variants As a part of the ACPI support preparation resign from checking compatible strings in the driver. Instead of that use a new enum and assign the values to match data accordingly. Signed-off-by: Marcin Wojtas Link: https://lore.kernel.org/r/20201204171626.10935-2-mw@semihalf.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci-xenon-phy.c | 4 +++- drivers/mmc/host/sdhci-xenon.c | 10 ++++++---- drivers/mmc/host/sdhci-xenon.h | 8 ++++++++ 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/drivers/mmc/host/sdhci-xenon-phy.c b/drivers/mmc/host/sdhci-xenon-phy.c index 03ce57ef4585..c33e0cddc81a 100644 --- a/drivers/mmc/host/sdhci-xenon-phy.c +++ b/drivers/mmc/host/sdhci-xenon-phy.c @@ -651,11 +651,13 @@ static int get_dt_pad_ctrl_data(struct sdhci_host *host, struct device_node *np, struct xenon_emmc_phy_params *params) { + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); + struct xenon_priv *priv = sdhci_pltfm_priv(pltfm_host); int ret = 0; const char *name; struct resource iomem; - if (of_device_is_compatible(np, "marvell,armada-3700-sdhci")) + if (priv->hw_version == XENON_A3700) params->pad_ctrl.set_soc_pad = armada_3700_soc_pad_voltage_set; else return 0; diff --git a/drivers/mmc/host/sdhci-xenon.c b/drivers/mmc/host/sdhci-xenon.c index 24c978de2a3f..1e7ce9b1a143 100644 --- a/drivers/mmc/host/sdhci-xenon.c +++ b/drivers/mmc/host/sdhci-xenon.c @@ -418,7 +418,7 @@ static int xenon_probe_dt(struct platform_device *pdev) u32 tuning_count; /* Disable HS200 on Armada AP806 */ - if (of_device_is_compatible(np, "marvell,armada-ap806-sdhci")) + if (priv->hw_version == XENON_AP806) host->quirks2 |= SDHCI_QUIRK2_BROKEN_HS200; sdhc_id = 0x0; @@ -495,6 +495,8 @@ static int xenon_probe(struct platform_device *pdev) pltfm_host = sdhci_priv(host); priv = sdhci_pltfm_priv(pltfm_host); + priv->hw_version = (unsigned long)device_get_match_data(&pdev->dev); + /* * Link Xenon specific mmc_host_ops function, * to replace standard ones in sdhci_ops. @@ -667,9 +669,9 @@ static const struct dev_pm_ops sdhci_xenon_dev_pm_ops = { }; static const struct of_device_id sdhci_xenon_dt_ids[] = { - { .compatible = "marvell,armada-ap806-sdhci",}, - { .compatible = "marvell,armada-cp110-sdhci",}, - { .compatible = "marvell,armada-3700-sdhci",}, + { .compatible = "marvell,armada-ap806-sdhci", .data = (void *)XENON_AP806}, + { .compatible = "marvell,armada-cp110-sdhci", .data = (void *)XENON_CP110}, + { .compatible = "marvell,armada-3700-sdhci", .data = (void *)XENON_A3700}, {} }; MODULE_DEVICE_TABLE(of, sdhci_xenon_dt_ids); diff --git a/drivers/mmc/host/sdhci-xenon.h b/drivers/mmc/host/sdhci-xenon.h index 593b82d7b68a..39e898605937 100644 --- a/drivers/mmc/host/sdhci-xenon.h +++ b/drivers/mmc/host/sdhci-xenon.h @@ -53,6 +53,13 @@ #define XENON_CTRL_HS200 0x5 #define XENON_CTRL_HS400 0x6 +enum xenon_variant { + XENON_A3700, + XENON_AP806, + XENON_AP807, + XENON_CP110 +}; + struct xenon_priv { unsigned char tuning_count; /* idx of SDHC */ @@ -90,6 +97,7 @@ struct xenon_priv { void *phy_params; struct xenon_emmc_phy_regs *emmc_phy_regs; bool restore_needed; + enum xenon_variant hw_version; }; int xenon_phy_adj(struct sdhci_host *host, struct mmc_ios *ios); From f29bf660bf4137ab1c2c3915d89e16818d20d792 Mon Sep 17 00:00:00 2001 From: Marcin Wojtas Date: Fri, 4 Dec 2020 18:16:24 +0100 Subject: [PATCH 097/102] mmc: sdhci-xenon: switch to device_* API In order to support both ACPI and DT, modify the driver to use device_* routines for obtaining the properties values. Signed-off-by: Marcin Wojtas Link: https://lore.kernel.org/r/20201204171626.10935-3-mw@semihalf.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci-xenon-phy.c | 36 ++++++++++++++++-------------- drivers/mmc/host/sdhci-xenon.c | 18 +++++++-------- drivers/mmc/host/sdhci-xenon.h | 4 ++-- 3 files changed, 30 insertions(+), 28 deletions(-) diff --git a/drivers/mmc/host/sdhci-xenon-phy.c b/drivers/mmc/host/sdhci-xenon-phy.c index c33e0cddc81a..8cf3a375de65 100644 --- a/drivers/mmc/host/sdhci-xenon-phy.c +++ b/drivers/mmc/host/sdhci-xenon-phy.c @@ -691,35 +691,37 @@ static int get_dt_pad_ctrl_data(struct sdhci_host *host, return ret; } -static int xenon_emmc_phy_parse_param_dt(struct sdhci_host *host, - struct device_node *np, - struct xenon_emmc_phy_params *params) +static int xenon_emmc_phy_parse_params(struct sdhci_host *host, + struct device *dev, + struct xenon_emmc_phy_params *params) { u32 value; params->slow_mode = false; - if (of_property_read_bool(np, "marvell,xenon-phy-slow-mode")) + if (device_property_read_bool(dev, "marvell,xenon-phy-slow-mode")) params->slow_mode = true; params->znr = XENON_ZNR_DEF_VALUE; - if (!of_property_read_u32(np, "marvell,xenon-phy-znr", &value)) + if (!device_property_read_u32(dev, "marvell,xenon-phy-znr", &value)) params->znr = value & XENON_ZNR_MASK; params->zpr = XENON_ZPR_DEF_VALUE; - if (!of_property_read_u32(np, "marvell,xenon-phy-zpr", &value)) + if (!device_property_read_u32(dev, "marvell,xenon-phy-zpr", &value)) params->zpr = value & XENON_ZPR_MASK; params->nr_tun_times = XENON_TUN_CONSECUTIVE_TIMES; - if (!of_property_read_u32(np, "marvell,xenon-phy-nr-success-tun", - &value)) + if (!device_property_read_u32(dev, "marvell,xenon-phy-nr-success-tun", + &value)) params->nr_tun_times = value & XENON_TUN_CONSECUTIVE_TIMES_MASK; params->tun_step_divider = XENON_TUNING_STEP_DIVIDER; - if (!of_property_read_u32(np, "marvell,xenon-phy-tun-step-divider", - &value)) + if (!device_property_read_u32(dev, "marvell,xenon-phy-tun-step-divider", + &value)) params->tun_step_divider = value & 0xFF; - return get_dt_pad_ctrl_data(host, np, params); + if (dev->of_node) + return get_dt_pad_ctrl_data(host, dev->of_node, params); + return 0; } /* Set SoC PHY Voltage PAD */ @@ -813,7 +815,7 @@ int xenon_phy_adj(struct sdhci_host *host, struct mmc_ios *ios) return ret; } -static int xenon_add_phy(struct device_node *np, struct sdhci_host *host, +static int xenon_add_phy(struct device *dev, struct sdhci_host *host, const char *phy_name) { struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); @@ -832,15 +834,15 @@ static int xenon_add_phy(struct device_node *np, struct sdhci_host *host, if (ret) return ret; - return xenon_emmc_phy_parse_param_dt(host, np, priv->phy_params); + return xenon_emmc_phy_parse_params(host, dev, priv->phy_params); } -int xenon_phy_parse_dt(struct device_node *np, struct sdhci_host *host) +int xenon_phy_parse_params(struct device *dev, struct sdhci_host *host) { const char *phy_type = NULL; - if (!of_property_read_string(np, "marvell,xenon-phy-type", &phy_type)) - return xenon_add_phy(np, host, phy_type); + if (!device_property_read_string(dev, "marvell,xenon-phy-type", &phy_type)) + return xenon_add_phy(dev, host, phy_type); - return xenon_add_phy(np, host, "emmc 5.1 phy"); + return xenon_add_phy(dev, host, "emmc 5.1 phy"); } diff --git a/drivers/mmc/host/sdhci-xenon.c b/drivers/mmc/host/sdhci-xenon.c index 1e7ce9b1a143..bfc76b0e3eaa 100644 --- a/drivers/mmc/host/sdhci-xenon.c +++ b/drivers/mmc/host/sdhci-xenon.c @@ -407,9 +407,9 @@ static void xenon_replace_mmc_host_ops(struct sdhci_host *host) * Refer to XENON_SYS_CFG_INFO register * tun-count: the interval between re-tuning */ -static int xenon_probe_dt(struct platform_device *pdev) +static int xenon_probe_params(struct platform_device *pdev) { - struct device_node *np = pdev->dev.of_node; + struct device *dev = &pdev->dev; struct sdhci_host *host = platform_get_drvdata(pdev); struct mmc_host *mmc = host->mmc; struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); @@ -422,7 +422,7 @@ static int xenon_probe_dt(struct platform_device *pdev) host->quirks2 |= SDHCI_QUIRK2_BROKEN_HS200; sdhc_id = 0x0; - if (!of_property_read_u32(np, "marvell,xenon-sdhc-id", &sdhc_id)) { + if (!device_property_read_u32(dev, "marvell,xenon-sdhc-id", &sdhc_id)) { nr_sdhc = sdhci_readl(host, XENON_SYS_CFG_INFO); nr_sdhc &= XENON_NR_SUPPORTED_SLOT_MASK; if (unlikely(sdhc_id > nr_sdhc)) { @@ -434,8 +434,8 @@ static int xenon_probe_dt(struct platform_device *pdev) priv->sdhc_id = sdhc_id; tuning_count = XENON_DEF_TUNING_COUNT; - if (!of_property_read_u32(np, "marvell,xenon-tun-count", - &tuning_count)) { + if (!device_property_read_u32(dev, "marvell,xenon-tun-count", + &tuning_count)) { if (unlikely(tuning_count >= XENON_TMR_RETUN_NO_PRESENT)) { dev_err(mmc_dev(mmc), "Wrong Re-tuning Count. Set default value %d\n", XENON_DEF_TUNING_COUNT); @@ -444,7 +444,7 @@ static int xenon_probe_dt(struct platform_device *pdev) } priv->tuning_count = tuning_count; - return xenon_phy_parse_dt(np, host); + return xenon_phy_parse_params(dev, host); } static int xenon_sdhc_prepare(struct sdhci_host *host) @@ -528,12 +528,12 @@ static int xenon_probe(struct platform_device *pdev) if (err) goto err_clk_axi; - sdhci_get_of_property(pdev); + sdhci_get_property(pdev); xenon_set_acg(host, false); - /* Xenon specific dt parse */ - err = xenon_probe_dt(pdev); + /* Xenon specific parameters parse */ + err = xenon_probe_params(pdev); if (err) goto err_clk_axi; diff --git a/drivers/mmc/host/sdhci-xenon.h b/drivers/mmc/host/sdhci-xenon.h index 39e898605937..3e9c6c908a79 100644 --- a/drivers/mmc/host/sdhci-xenon.h +++ b/drivers/mmc/host/sdhci-xenon.h @@ -101,8 +101,8 @@ struct xenon_priv { }; int xenon_phy_adj(struct sdhci_host *host, struct mmc_ios *ios); -int xenon_phy_parse_dt(struct device_node *np, - struct sdhci_host *host); +int xenon_phy_parse_params(struct device *dev, + struct sdhci_host *host); void xenon_soc_pad_ctrl(struct sdhci_host *host, unsigned char signal_voltage); #endif From 1542488031deed57e1f0853a07bd4934ce27e599 Mon Sep 17 00:00:00 2001 From: Marcin Wojtas Date: Fri, 4 Dec 2020 18:16:25 +0100 Subject: [PATCH 098/102] mmc: sdhci-xenon: use clk only with DT As a preparation for supporting ACPI, modify the driver to use the clk framework only when booting with DT - otherwise rely on the configuration done by firmware. For that purpose introduce also a custom SDHCI get_max_clock callback. Signed-off-by: Marcin Wojtas Link: https://lore.kernel.org/r/20201204171626.10935-4-mw@semihalf.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci-xenon.c | 51 +++++++++++++++++++++------------- 1 file changed, 32 insertions(+), 19 deletions(-) diff --git a/drivers/mmc/host/sdhci-xenon.c b/drivers/mmc/host/sdhci-xenon.c index bfc76b0e3eaa..7d9335857715 100644 --- a/drivers/mmc/host/sdhci-xenon.c +++ b/drivers/mmc/host/sdhci-xenon.c @@ -247,6 +247,16 @@ static void xenon_voltage_switch(struct sdhci_host *host) sdhci_readw(host, SDHCI_HOST_CONTROL2); } +static unsigned int xenon_get_max_clock(struct sdhci_host *host) +{ + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); + + if (pltfm_host->clk) + return sdhci_pltfm_clk_get_max_clock(host); + else + return pltfm_host->clock; +} + static const struct sdhci_ops sdhci_xenon_ops = { .voltage_switch = xenon_voltage_switch, .set_clock = sdhci_set_clock, @@ -254,7 +264,7 @@ static const struct sdhci_ops sdhci_xenon_ops = { .set_bus_width = sdhci_set_bus_width, .reset = xenon_reset, .set_uhs_signaling = xenon_set_uhs_signaling, - .get_max_clock = sdhci_pltfm_clk_get_max_clock, + .get_max_clock = xenon_get_max_clock, }; static const struct sdhci_pltfm_data sdhci_xenon_pdata = { @@ -483,6 +493,7 @@ static void xenon_sdhc_unprepare(struct sdhci_host *host) static int xenon_probe(struct platform_device *pdev) { struct sdhci_pltfm_host *pltfm_host; + struct device *dev = &pdev->dev; struct sdhci_host *host; struct xenon_priv *priv; int err; @@ -503,25 +514,27 @@ static int xenon_probe(struct platform_device *pdev) */ xenon_replace_mmc_host_ops(host); - pltfm_host->clk = devm_clk_get(&pdev->dev, "core"); - if (IS_ERR(pltfm_host->clk)) { - err = PTR_ERR(pltfm_host->clk); - dev_err(&pdev->dev, "Failed to setup input clk: %d\n", err); - goto free_pltfm; - } - err = clk_prepare_enable(pltfm_host->clk); - if (err) - goto free_pltfm; - - priv->axi_clk = devm_clk_get(&pdev->dev, "axi"); - if (IS_ERR(priv->axi_clk)) { - err = PTR_ERR(priv->axi_clk); - if (err == -EPROBE_DEFER) - goto err_clk; - } else { - err = clk_prepare_enable(priv->axi_clk); + if (dev->of_node) { + pltfm_host->clk = devm_clk_get(&pdev->dev, "core"); + if (IS_ERR(pltfm_host->clk)) { + err = PTR_ERR(pltfm_host->clk); + dev_err(&pdev->dev, "Failed to setup input clk: %d\n", err); + goto free_pltfm; + } + err = clk_prepare_enable(pltfm_host->clk); if (err) - goto err_clk; + goto free_pltfm; + + priv->axi_clk = devm_clk_get(&pdev->dev, "axi"); + if (IS_ERR(priv->axi_clk)) { + err = PTR_ERR(priv->axi_clk); + if (err == -EPROBE_DEFER) + goto err_clk; + } else { + err = clk_prepare_enable(priv->axi_clk); + if (err) + goto err_clk; + } } err = mmc_of_parse(host->mmc); From 471cf4548e191b69a9737021c8e7d216957e384f Mon Sep 17 00:00:00 2001 From: Marcin Wojtas Date: Fri, 4 Dec 2020 18:16:26 +0100 Subject: [PATCH 099/102] mmc: sdhci-xenon: introduce ACPI support Previous patches dropped the strict dependency on the OF_* in the sdhci-xenon driver. As a result the ACPI support can be introduced (except for the XENON_A3700 variant) by adding the necessary ID's in the acpi_match_table. Signed-off-by: Marcin Wojtas Link: https://lore.kernel.org/r/20201204171626.10935-5-mw@semihalf.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci-xenon.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/mmc/host/sdhci-xenon.c b/drivers/mmc/host/sdhci-xenon.c index 7d9335857715..c67611fdaa8a 100644 --- a/drivers/mmc/host/sdhci-xenon.c +++ b/drivers/mmc/host/sdhci-xenon.c @@ -11,6 +11,7 @@ * Special thanks to Video BG4 project team. */ +#include #include #include #include @@ -689,11 +690,22 @@ static const struct of_device_id sdhci_xenon_dt_ids[] = { }; MODULE_DEVICE_TABLE(of, sdhci_xenon_dt_ids); +#ifdef CONFIG_ACPI +static const struct acpi_device_id sdhci_xenon_acpi_ids[] = { + { .id = "MRVL0002", XENON_AP806}, + { .id = "MRVL0003", XENON_AP807}, + { .id = "MRVL0004", XENON_CP110}, + {} +}; +MODULE_DEVICE_TABLE(acpi, sdhci_xenon_acpi_ids); +#endif + static struct platform_driver sdhci_xenon_driver = { .driver = { .name = "xenon-sdhci", .probe_type = PROBE_PREFER_ASYNCHRONOUS, .of_match_table = sdhci_xenon_dt_ids, + .acpi_match_table = ACPI_PTR(sdhci_xenon_acpi_ids), .pm = &sdhci_xenon_dev_pm_ops, }, .probe = xenon_probe, From 72b248cfbf3fd308807afe7cc30d05fefeff7fb1 Mon Sep 17 00:00:00 2001 From: Zhen Lei Date: Mon, 7 Dec 2020 11:26:26 +0800 Subject: [PATCH 100/102] dt-bindings: mmc: eliminate yamllint warnings Eliminate the following yamllint warnings: ./Documentation/devicetree/bindings/mmc/mtk-sd.yaml :20:9: [warning] wrong indentation: expected 10 but found 8 (indentation) :30:9: [warning] wrong indentation: expected 10 but found 8 (indentation) :33:9: [warning] wrong indentation: expected 10 but found 8 (indentation) Signed-off-by: Zhen Lei Reviewed-by: Rob Herring Link: https://lore.kernel.org/r/20201207032626.1445-2-thunder.leizhen@huawei.com Signed-off-by: Ulf Hansson --- .../devicetree/bindings/mmc/mtk-sd.yaml | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/Documentation/devicetree/bindings/mmc/mtk-sd.yaml b/Documentation/devicetree/bindings/mmc/mtk-sd.yaml index 030e3fdce492..01630b0ecea7 100644 --- a/Documentation/devicetree/bindings/mmc/mtk-sd.yaml +++ b/Documentation/devicetree/bindings/mmc/mtk-sd.yaml @@ -17,21 +17,21 @@ properties: compatible: oneOf: - enum: - - mediatek,mt2701-mmc - - mediatek,mt2712-mmc - - mediatek,mt6779-mmc - - mediatek,mt7620-mmc - - mediatek,mt7622-mmc - - mediatek,mt8135-mmc - - mediatek,mt8173-mmc - - mediatek,mt8183-mmc - - mediatek,mt8516-mmc + - mediatek,mt2701-mmc + - mediatek,mt2712-mmc + - mediatek,mt6779-mmc + - mediatek,mt7620-mmc + - mediatek,mt7622-mmc + - mediatek,mt8135-mmc + - mediatek,mt8173-mmc + - mediatek,mt8183-mmc + - mediatek,mt8516-mmc - items: - - const: mediatek,mt7623-mmc - - const: mediatek,mt2701-mmc + - const: mediatek,mt7623-mmc + - const: mediatek,mt2701-mmc - items: - - const: mediatek,mt8192-mmc - - const: mediatek,mt8183-mmc + - const: mediatek,mt8192-mmc + - const: mediatek,mt8183-mmc clocks: description: From 71637c620a826434ca6f888b0364a036faa27ffa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Thu, 26 Nov 2020 08:23:30 +0100 Subject: [PATCH 101/102] i2c: Warn when device removing fails MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The driver core ignores the return value of struct bus_type::remove. So warn if there is an error that went unnoticed before and return 0 unconditionally in i2c_device_remove(). This prepares changing struct bus_type::remove to return void. Signed-off-by: Uwe Kleine-König [wsa: added a comment and removed unneeded initializtion] Signed-off-by: Wolfram Sang --- drivers/i2c/i2c-core-base.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/i2c/i2c-core-base.c b/drivers/i2c/i2c-core-base.c index 573b5da145d1..6528d9e8f3ae 100644 --- a/drivers/i2c/i2c-core-base.c +++ b/drivers/i2c/i2c-core-base.c @@ -551,15 +551,19 @@ static int i2c_device_remove(struct device *dev) { struct i2c_client *client = i2c_verify_client(dev); struct i2c_driver *driver; - int status = 0; if (!client || !dev->driver) return 0; driver = to_i2c_driver(dev->driver); if (driver->remove) { + int status; + dev_dbg(dev, "remove\n"); + status = driver->remove(client); + if (status) + dev_warn(dev, "remove failed (%pe), will be ignored\n", ERR_PTR(status)); } dev_pm_domain_detach(&client->dev, true); @@ -571,7 +575,8 @@ static int i2c_device_remove(struct device *dev) if (client->flags & I2C_CLIENT_HOST_NOTIFY) pm_runtime_put(&client->adapter->dev); - return status; + /* return always 0 because there is WIP to make remove-functions void */ + return 0; } static void i2c_device_shutdown(struct device *dev) From 4e970a0ada5299d017a4263074f725227c2d2852 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Thu, 26 Nov 2020 08:23:31 +0100 Subject: [PATCH 102/102] i2c: remove check that can never be true MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A driver remove callback is only called if the device was bound before. So it's sure that both dev and dev->driver are valid and dev is an i2c device. If the check fails something louder than "return 0" might be appropriate because the problem is grave (something like memory corruption), otherwise the check is useless. Signed-off-by: Uwe Kleine-König Signed-off-by: Wolfram Sang --- drivers/i2c/i2c-core-base.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/i2c/i2c-core-base.c b/drivers/i2c/i2c-core-base.c index 6528d9e8f3ae..63ebf722a424 100644 --- a/drivers/i2c/i2c-core-base.c +++ b/drivers/i2c/i2c-core-base.c @@ -549,12 +549,9 @@ static int i2c_device_probe(struct device *dev) static int i2c_device_remove(struct device *dev) { - struct i2c_client *client = i2c_verify_client(dev); + struct i2c_client *client = to_i2c_client(dev); struct i2c_driver *driver; - if (!client || !dev->driver) - return 0; - driver = to_i2c_driver(dev->driver); if (driver->remove) { int status;