* [PATCH V6 1/3] mmc: sdhci: Add support for O2 eMMC HS200 mode
@ 2018-06-26 15:46 ernest.zhang
2018-06-26 15:46 ` [PATCH V6 2/3] mmc: sdhci: Add support for O2 hardware tuning ernest.zhang
` (2 more replies)
0 siblings, 3 replies; 6+ messages in thread
From: ernest.zhang @ 2018-06-26 15:46 UTC (permalink / raw)
To: Adrian Hunter, Ulf Hansson, linux-mmc, linux-kernel
Cc: ernest.zhang, chuanjin.pang, mike.li, chevron.li, shirley.her,
xiaoguang.yu, bobby.wu
When use eMMC as boot device, the eMMC signaling voltage is tied to 1.8v
fixed output voltage, bios can set o2 sd host controller PCI configuration
register 0x308 bit4 to 1 to let driver skip 3.3v signaling voltage and
direct use 1.8v singling voltage in eMMC initialize process.
Signed-off-by: ernest.zhang <ernest.zhang@bayhubtech.com>
---
Changes in V6:
1.Move change log to correct place.
2.Change HS200 mode clock frequency from 208MHz to 200MHz to meet
Specification.
Changes in V5:
Modify code format to pass checkpatch.pl check and add a summary
of what has changed in each version.
Changes in V4:
Skip SDIO and SD initalization when register 0x308 bit 4 is set,
and modify some typo.
Changes in V3:
Rebase the patch on the mmc tree 'next' branch.
Changes in V2:
Modify code format, and delete unused code path.
Changes in V1:
Check PCIe register 0x308 bit 4 and skip eMMC 3.3v initialization
process if it is set to 1.
---
drivers/mmc/host/sdhci-pci-o2micro.c | 22 ++++++++++++++++++++--
1 file changed, 20 insertions(+), 2 deletions(-)
diff --git a/drivers/mmc/host/sdhci-pci-o2micro.c b/drivers/mmc/host/sdhci-pci-o2micro.c
index 555970a..94cf3cd 100644
--- a/drivers/mmc/host/sdhci-pci-o2micro.c
+++ b/drivers/mmc/host/sdhci-pci-o2micro.c
@@ -3,6 +3,7 @@
*
* Authors: Peter Guo <peter.guo@bayhubtech.com>
* Adam Lee <adam.lee@canonical.com>
+ * Ernest Zhang <ernest.zhang@bayhubtech.com>
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -39,6 +40,7 @@
#define O2_SD_MISC_CTRL4 0xFC
#define O2_SD_TUNING_CTRL 0x300
#define O2_SD_PLL_SETTING 0x304
+#define O2_SD_MISC_SETTING 0x308
#define O2_SD_CLK_SETTING 0x328
#define O2_SD_CAP_REG2 0x330
#define O2_SD_CAP_REG0 0x334
@@ -184,6 +186,7 @@ int sdhci_pci_o2_probe_slot(struct sdhci_pci_slot *slot)
struct sdhci_pci_chip *chip;
struct sdhci_host *host;
u32 reg;
+ int ret;
chip = slot->chip;
host = slot->host;
@@ -197,6 +200,21 @@ int sdhci_pci_o2_probe_slot(struct sdhci_pci_slot *slot)
if (reg & 0x1)
host->quirks |= SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12;
+ if (chip->pdev->device == PCI_DEVICE_ID_O2_SEABIRD0) {
+ ret = pci_read_config_dword(chip->pdev,
+ O2_SD_MISC_SETTING, ®);
+ if (ret)
+ return -EIO;
+ if (reg & (1 << 4)) {
+ pr_info("%s: emmc 1.8v flag is set, force 1.8v signaling voltage\n",
+ mmc_hostname(host->mmc));
+ host->flags &= ~SDHCI_SIGNALING_330;
+ host->flags |= SDHCI_SIGNALING_180;
+ host->mmc->caps2 |= MMC_CAP2_NO_SD;
+ host->mmc->caps2 |= MMC_CAP2_NO_SDIO;
+ }
+ }
+
if (chip->pdev->device != PCI_DEVICE_ID_O2_FUJIN2)
break;
/* set dll watch dog timer */
@@ -293,7 +311,7 @@ int sdhci_pci_o2_probe(struct sdhci_pci_chip *chip)
/* Check Whether subId is 0x11 or 0x12 */
if ((scratch_32 == 0x11) || (scratch_32 == 0x12)) {
- scratch_32 = 0x2c280000;
+ scratch_32 = 0x25100000;
/* Set Base Clock to 208MZ */
o2_pci_set_baseclk(chip, scratch_32);
@@ -388,7 +406,7 @@ int sdhci_pci_o2_probe(struct sdhci_pci_chip *chip)
O2_SD_PLL_SETTING, scratch_32);
} else {
scratch_32 &= 0x0000FFFF;
- scratch_32 |= 0x2c280000;
+ scratch_32 |= 0x25100000;
pci_write_config_dword(chip->pdev,
O2_SD_PLL_SETTING, scratch_32);
--
2.7.4
^ permalink raw reply related [flat|nested] 6+ messages in thread* [PATCH V6 2/3] mmc: sdhci: Add support for O2 hardware tuning 2018-06-26 15:46 [PATCH V6 1/3] mmc: sdhci: Add support for O2 eMMC HS200 mode ernest.zhang @ 2018-06-26 15:46 ` ernest.zhang 2018-07-10 12:43 ` Adrian Hunter 2018-06-26 15:46 ` [PATCH V6 3/3] mmc: sdhci: Add MSI interrupt support for O2 SD host ernest.zhang 2018-07-10 12:23 ` [PATCH V6 1/3] mmc: sdhci: Add support for O2 eMMC HS200 mode Adrian Hunter 2 siblings, 1 reply; 6+ messages in thread From: ernest.zhang @ 2018-06-26 15:46 UTC (permalink / raw) To: Adrian Hunter, Ulf Hansson, linux-mmc, linux-kernel Cc: ernest.zhang, chuanjin.pang, mike.li, chevron.li, shirley.her, xiaoguang.yu, bobby.wu Add hardware tuning function instead of software tuning because O2/Bayhub SD host controller support hardware tuning. Signed-off-by: ernest.zhang <ernest.zhang@bayhubtech.com> --- Changes in V6: 1. From module 'sdhci' export the symbols 'sdhci_start_tuning', 'sdhci_end_tuning','sdhci_send_tuning' and 'sdhci_reset_tuning'. 2. Remove local tuning related functions in sdhci-pci-o2-micro.c instead of above function exported in sdhci module. 3. Remove unneeded braces in function sdhci_set_transfer_mode. 4. Move change log to correct place. Changes in V5: In function sdhci_o2_send_tuning, mrq.data should set to NULL for cmd.data has been set to NULL. Changes in V4: Patch V3 delete register SDHCI_TRANSFER_MODE write operation before send hardware tuning command in function sdhci_o2_send_tuning. This is a mistake. The write operation is essential for tuning command. Add it back. Changes in V3: Rebase the patch on the mmc tree 'next' branch. Changes in V2: Modify code format, and delete unused code path. Changes in V1: Add many functions to execute hardware tuning for eMMC 1.8V HS200 mode, the hardware tuning procedure is based on O2/Bayhub hardware tuning spec. --- drivers/mmc/host/sdhci-pci-o2micro.c | 81 ++++++++++++++++++++++++++++++++++++ drivers/mmc/host/sdhci.c | 16 ++++--- drivers/mmc/host/sdhci.h | 5 +++ 3 files changed, 97 insertions(+), 5 deletions(-) diff --git a/drivers/mmc/host/sdhci-pci-o2micro.c b/drivers/mmc/host/sdhci-pci-o2micro.c index 94cf3cd..7747e8b 100644 --- a/drivers/mmc/host/sdhci-pci-o2micro.c +++ b/drivers/mmc/host/sdhci-pci-o2micro.c @@ -17,6 +17,9 @@ */ #include <linux/pci.h> +#include <linux/mmc/host.h> +#include <linux/mmc/mmc.h> +#include <linux/delay.h> #include "sdhci.h" #include "sdhci-pci.h" @@ -55,6 +58,82 @@ #define O2_SD_VENDOR_SETTING 0x110 #define O2_SD_VENDOR_SETTING2 0x1C8 +#define O2_SD_HW_TUNING_DISABLE BIT(4) + +static void sdhci_o2_set_tuning_mode(struct sdhci_host *host) +{ + u16 reg; + + /* enable hardware tuning */ + reg = sdhci_readw(host, O2_SD_VENDOR_SETTING); + reg &= ~O2_SD_HW_TUNING_DISABLE; + sdhci_writew(host, reg, O2_SD_VENDOR_SETTING); +} + +static void __sdhci_o2_execute_tuning(struct sdhci_host *host, u32 opcode) +{ + int i; + + sdhci_send_tuning(host, MMC_SEND_TUNING_BLOCK_HS200); + + for (i = 0; i < 150; i++) { + u16 ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); + + if (!(ctrl & SDHCI_CTRL_EXEC_TUNING)) { + if (ctrl & SDHCI_CTRL_TUNED_CLK) { + host->tuning_done = true; + return; + } + pr_warn("%s: HW tuning failed !\n", + mmc_hostname(host->mmc)); + break; + } + + mdelay(1); + } + + pr_info("%s: Tuning failed, falling back to fixed sampling clock\n", + mmc_hostname(host->mmc)); + sdhci_reset_tuning(host); +} + +static int sdhci_o2_execute_tuning(struct mmc_host *mmc, u32 opcode) +{ + struct sdhci_host *host = mmc_priv(mmc); + int current_bus_width = 0; + + /* + * This handler only implements the eMMC tuning that is specific to + * this controller. Fall back to the standard method for other TIMING. + */ + if (host->timing != MMC_TIMING_MMC_HS200) + return sdhci_execute_tuning(mmc, opcode); + + if (WARN_ON(opcode != MMC_SEND_TUNING_BLOCK_HS200)) + return -EINVAL; + + /* + * o2 sdhci host didn't support 8bit emmc tuning + */ + if (mmc->ios.bus_width == MMC_BUS_WIDTH_8) { + current_bus_width = mmc->ios.bus_width; + sdhci_set_bus_width(host, MMC_BUS_WIDTH_4); + } + + sdhci_o2_set_tuning_mode(host); + + sdhci_start_tuning(host); + + __sdhci_o2_execute_tuning(host, opcode); + + sdhci_end_tuning(host); + + if (current_bus_width == MMC_BUS_WIDTH_8) + sdhci_set_bus_width(host, current_bus_width); + + host->flags &= ~SDHCI_HS400_TUNING; + return 0; +} static void o2_pci_set_baseclk(struct sdhci_pci_chip *chip, u32 value) { @@ -215,6 +294,8 @@ int sdhci_pci_o2_probe_slot(struct sdhci_pci_slot *slot) } } + host->mmc_host_ops.execute_tuning = sdhci_o2_execute_tuning; + if (chip->pdev->device != PCI_DEVICE_ID_O2_FUJIN2) break; /* set dll watch dog timer */ diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 1c828e0..4f3e3c2 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -1029,7 +1029,9 @@ static void sdhci_set_transfer_mode(struct sdhci_host *host, if (data == NULL) { if (host->quirks2 & SDHCI_QUIRK2_CLEAR_TRANSFERMODE_REG_BEFORE_CMD) { - sdhci_writew(host, 0x0, SDHCI_TRANSFER_MODE); + /* must not clear SDHCI_TRANSFER_MODE when tuning */ + if (cmd->opcode != MMC_SEND_TUNING_BLOCK_HS200) + sdhci_writew(host, 0x0, SDHCI_TRANSFER_MODE); } else { /* clear Auto CMD settings for no data CMDs */ mode = sdhci_readw(host, SDHCI_TRANSFER_MODE); @@ -2103,7 +2105,7 @@ static int sdhci_prepare_hs400_tuning(struct mmc_host *mmc, struct mmc_ios *ios) return 0; } -static void sdhci_start_tuning(struct sdhci_host *host) +void sdhci_start_tuning(struct sdhci_host *host) { u16 ctrl; @@ -2126,14 +2128,16 @@ static void sdhci_start_tuning(struct sdhci_host *host) sdhci_writel(host, SDHCI_INT_DATA_AVAIL, SDHCI_INT_ENABLE); sdhci_writel(host, SDHCI_INT_DATA_AVAIL, SDHCI_SIGNAL_ENABLE); } +EXPORT_SYMBOL_GPL(sdhci_start_tuning); -static void sdhci_end_tuning(struct sdhci_host *host) +void sdhci_end_tuning(struct sdhci_host *host) { sdhci_writel(host, host->ier, SDHCI_INT_ENABLE); sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); } +EXPORT_SYMBOL_GPL(sdhci_end_tuning); -static void sdhci_reset_tuning(struct sdhci_host *host) +void sdhci_reset_tuning(struct sdhci_host *host) { u16 ctrl; @@ -2142,6 +2146,7 @@ static void sdhci_reset_tuning(struct sdhci_host *host) ctrl &= ~SDHCI_CTRL_EXEC_TUNING; sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2); } +EXPORT_SYMBOL_GPL(sdhci_reset_tuning); static void sdhci_abort_tuning(struct sdhci_host *host, u32 opcode) { @@ -2162,7 +2167,7 @@ static void sdhci_abort_tuning(struct sdhci_host *host, u32 opcode) * interrupt setup is different to other commands and there is no timeout * interrupt so special handling is needed. */ -static void sdhci_send_tuning(struct sdhci_host *host, u32 opcode) +void sdhci_send_tuning(struct sdhci_host *host, u32 opcode) { struct mmc_host *mmc = host->mmc; struct mmc_command cmd = {}; @@ -2212,6 +2217,7 @@ static void sdhci_send_tuning(struct sdhci_host *host, u32 opcode) msecs_to_jiffies(50)); } +EXPORT_SYMBOL_GPL(sdhci_send_tuning); static void __sdhci_execute_tuning(struct sdhci_host *host, u32 opcode) { diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h index 23966f8..2a09c0a 100644 --- a/drivers/mmc/host/sdhci.h +++ b/drivers/mmc/host/sdhci.h @@ -748,4 +748,9 @@ bool sdhci_cqe_irq(struct sdhci_host *host, u32 intmask, int *cmd_error, void sdhci_dumpregs(struct sdhci_host *host); +void sdhci_start_tuning(struct sdhci_host *host); +void sdhci_end_tuning(struct sdhci_host *host); +void sdhci_send_tuning(struct sdhci_host *host, u32 opcode); +void sdhci_reset_tuning(struct sdhci_host *host); + #endif /* __SDHCI_HW_H */ -- 2.7.4 ^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH V6 2/3] mmc: sdhci: Add support for O2 hardware tuning 2018-06-26 15:46 ` [PATCH V6 2/3] mmc: sdhci: Add support for O2 hardware tuning ernest.zhang @ 2018-07-10 12:43 ` Adrian Hunter 0 siblings, 0 replies; 6+ messages in thread From: Adrian Hunter @ 2018-07-10 12:43 UTC (permalink / raw) To: ernest.zhang, Ulf Hansson, linux-mmc, linux-kernel Cc: chuanjin.pang, mike.li, chevron.li, shirley.her, xiaoguang.yu, bobby.wu On 26/06/18 18:46, ernest.zhang wrote: > Add hardware tuning function instead of software tuning because O2/Bayhub > SD host controller support hardware tuning. > > Signed-off-by: ernest.zhang <ernest.zhang@bayhubtech.com> > --- > Changes in V6: > 1. From module 'sdhci' export the symbols 'sdhci_start_tuning', > 'sdhci_end_tuning','sdhci_send_tuning' and 'sdhci_reset_tuning'. > 2. Remove local tuning related functions in sdhci-pci-o2-micro.c > instead of above function exported in sdhci module. > 3. Remove unneeded braces in function sdhci_set_transfer_mode. > 4. Move change log to correct place. > > Changes in V5: > In function sdhci_o2_send_tuning, mrq.data should set to NULL for > cmd.data has been set to NULL. > > Changes in V4: > Patch V3 delete register SDHCI_TRANSFER_MODE write operation before > send hardware tuning command in function sdhci_o2_send_tuning. This > is a mistake. The write operation is essential for tuning command. > Add it back. > > Changes in V3: > Rebase the patch on the mmc tree 'next' branch. > > Changes in V2: > Modify code format, and delete unused code path. > > Changes in V1: > Add many functions to execute hardware tuning for eMMC 1.8V HS200 > mode, the hardware tuning procedure is based on O2/Bayhub hardware > tuning spec. > --- > drivers/mmc/host/sdhci-pci-o2micro.c | 81 ++++++++++++++++++++++++++++++++++++ > drivers/mmc/host/sdhci.c | 16 ++++--- > drivers/mmc/host/sdhci.h | 5 +++ > 3 files changed, 97 insertions(+), 5 deletions(-) > > diff --git a/drivers/mmc/host/sdhci-pci-o2micro.c b/drivers/mmc/host/sdhci-pci-o2micro.c > index 94cf3cd..7747e8b 100644 > --- a/drivers/mmc/host/sdhci-pci-o2micro.c > +++ b/drivers/mmc/host/sdhci-pci-o2micro.c > @@ -17,6 +17,9 @@ > */ > > #include <linux/pci.h> > +#include <linux/mmc/host.h> > +#include <linux/mmc/mmc.h> > +#include <linux/delay.h> > > #include "sdhci.h" > #include "sdhci-pci.h" > @@ -55,6 +58,82 @@ > > #define O2_SD_VENDOR_SETTING 0x110 > #define O2_SD_VENDOR_SETTING2 0x1C8 > +#define O2_SD_HW_TUNING_DISABLE BIT(4) > + > +static void sdhci_o2_set_tuning_mode(struct sdhci_host *host) > +{ > + u16 reg; > + > + /* enable hardware tuning */ > + reg = sdhci_readw(host, O2_SD_VENDOR_SETTING); > + reg &= ~O2_SD_HW_TUNING_DISABLE; > + sdhci_writew(host, reg, O2_SD_VENDOR_SETTING); > +} > + > +static void __sdhci_o2_execute_tuning(struct sdhci_host *host, u32 opcode) > +{ > + int i; > + > + sdhci_send_tuning(host, MMC_SEND_TUNING_BLOCK_HS200); > + > + for (i = 0; i < 150; i++) { > + u16 ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); > + > + if (!(ctrl & SDHCI_CTRL_EXEC_TUNING)) { > + if (ctrl & SDHCI_CTRL_TUNED_CLK) { > + host->tuning_done = true; > + return; > + } > + pr_warn("%s: HW tuning failed !\n", > + mmc_hostname(host->mmc)); > + break; > + } > + > + mdelay(1); > + } > + > + pr_info("%s: Tuning failed, falling back to fixed sampling clock\n", > + mmc_hostname(host->mmc)); > + sdhci_reset_tuning(host); > +} > + > +static int sdhci_o2_execute_tuning(struct mmc_host *mmc, u32 opcode) > +{ > + struct sdhci_host *host = mmc_priv(mmc); > + int current_bus_width = 0; > + > + /* > + * This handler only implements the eMMC tuning that is specific to > + * this controller. Fall back to the standard method for other TIMING. > + */ > + if (host->timing != MMC_TIMING_MMC_HS200) > + return sdhci_execute_tuning(mmc, opcode); > + > + if (WARN_ON(opcode != MMC_SEND_TUNING_BLOCK_HS200)) > + return -EINVAL; > + > + /* > + * o2 sdhci host didn't support 8bit emmc tuning > + */ > + if (mmc->ios.bus_width == MMC_BUS_WIDTH_8) { > + current_bus_width = mmc->ios.bus_width; > + sdhci_set_bus_width(host, MMC_BUS_WIDTH_4); > + } > + > + sdhci_o2_set_tuning_mode(host); > + > + sdhci_start_tuning(host); > + > + __sdhci_o2_execute_tuning(host, opcode); > + > + sdhci_end_tuning(host); > + > + if (current_bus_width == MMC_BUS_WIDTH_8) > + sdhci_set_bus_width(host, current_bus_width); > + > + host->flags &= ~SDHCI_HS400_TUNING; > + return 0; > +} > > static void o2_pci_set_baseclk(struct sdhci_pci_chip *chip, u32 value) > { > @@ -215,6 +294,8 @@ int sdhci_pci_o2_probe_slot(struct sdhci_pci_slot *slot) > } > } > > + host->mmc_host_ops.execute_tuning = sdhci_o2_execute_tuning; > + > if (chip->pdev->device != PCI_DEVICE_ID_O2_FUJIN2) > break; > /* set dll watch dog timer */ > diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c > index 1c828e0..4f3e3c2 100644 > --- a/drivers/mmc/host/sdhci.c > +++ b/drivers/mmc/host/sdhci.c > @@ -1029,7 +1029,9 @@ static void sdhci_set_transfer_mode(struct sdhci_host *host, > if (data == NULL) { > if (host->quirks2 & > SDHCI_QUIRK2_CLEAR_TRANSFERMODE_REG_BEFORE_CMD) { > - sdhci_writew(host, 0x0, SDHCI_TRANSFER_MODE); > + /* must not clear SDHCI_TRANSFER_MODE when tuning */ > + if (cmd->opcode != MMC_SEND_TUNING_BLOCK_HS200) > + sdhci_writew(host, 0x0, SDHCI_TRANSFER_MODE); > } else { > /* clear Auto CMD settings for no data CMDs */ > mode = sdhci_readw(host, SDHCI_TRANSFER_MODE); > @@ -2103,7 +2105,7 @@ static int sdhci_prepare_hs400_tuning(struct mmc_host *mmc, struct mmc_ios *ios) > return 0; > } > Please put the export changes below into a separate patch. > -static void sdhci_start_tuning(struct sdhci_host *host) > +void sdhci_start_tuning(struct sdhci_host *host) > { > u16 ctrl; > > @@ -2126,14 +2128,16 @@ static void sdhci_start_tuning(struct sdhci_host *host) > sdhci_writel(host, SDHCI_INT_DATA_AVAIL, SDHCI_INT_ENABLE); > sdhci_writel(host, SDHCI_INT_DATA_AVAIL, SDHCI_SIGNAL_ENABLE); > } > +EXPORT_SYMBOL_GPL(sdhci_start_tuning); > > -static void sdhci_end_tuning(struct sdhci_host *host) > +void sdhci_end_tuning(struct sdhci_host *host) > { > sdhci_writel(host, host->ier, SDHCI_INT_ENABLE); > sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); > } > +EXPORT_SYMBOL_GPL(sdhci_end_tuning); > > -static void sdhci_reset_tuning(struct sdhci_host *host) > +void sdhci_reset_tuning(struct sdhci_host *host) > { > u16 ctrl; > > @@ -2142,6 +2146,7 @@ static void sdhci_reset_tuning(struct sdhci_host *host) > ctrl &= ~SDHCI_CTRL_EXEC_TUNING; > sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2); > } > +EXPORT_SYMBOL_GPL(sdhci_reset_tuning); > > static void sdhci_abort_tuning(struct sdhci_host *host, u32 opcode) > { > @@ -2162,7 +2167,7 @@ static void sdhci_abort_tuning(struct sdhci_host *host, u32 opcode) > * interrupt setup is different to other commands and there is no timeout > * interrupt so special handling is needed. > */ > -static void sdhci_send_tuning(struct sdhci_host *host, u32 opcode) > +void sdhci_send_tuning(struct sdhci_host *host, u32 opcode) > { > struct mmc_host *mmc = host->mmc; > struct mmc_command cmd = {}; > @@ -2212,6 +2217,7 @@ static void sdhci_send_tuning(struct sdhci_host *host, u32 opcode) > msecs_to_jiffies(50)); > > } > +EXPORT_SYMBOL_GPL(sdhci_send_tuning); > > static void __sdhci_execute_tuning(struct sdhci_host *host, u32 opcode) > { > diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h > index 23966f8..2a09c0a 100644 > --- a/drivers/mmc/host/sdhci.h > +++ b/drivers/mmc/host/sdhci.h > @@ -748,4 +748,9 @@ bool sdhci_cqe_irq(struct sdhci_host *host, u32 intmask, int *cmd_error, > > void sdhci_dumpregs(struct sdhci_host *host); > > +void sdhci_start_tuning(struct sdhci_host *host); > +void sdhci_end_tuning(struct sdhci_host *host); > +void sdhci_send_tuning(struct sdhci_host *host, u32 opcode); > +void sdhci_reset_tuning(struct sdhci_host *host); > + > #endif /* __SDHCI_HW_H */ > ^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH V6 3/3] mmc: sdhci: Add MSI interrupt support for O2 SD host 2018-06-26 15:46 [PATCH V6 1/3] mmc: sdhci: Add support for O2 eMMC HS200 mode ernest.zhang 2018-06-26 15:46 ` [PATCH V6 2/3] mmc: sdhci: Add support for O2 hardware tuning ernest.zhang @ 2018-06-26 15:46 ` ernest.zhang 2018-07-10 12:44 ` Adrian Hunter 2018-07-10 12:23 ` [PATCH V6 1/3] mmc: sdhci: Add support for O2 eMMC HS200 mode Adrian Hunter 2 siblings, 1 reply; 6+ messages in thread From: ernest.zhang @ 2018-06-26 15:46 UTC (permalink / raw) To: Adrian Hunter, Ulf Hansson, linux-mmc, linux-kernel Cc: ernest.zhang, chuanjin.pang, mike.li, chevron.li, shirley.her, xiaoguang.yu, bobby.wu Add MSI interrupt support if the SD host device can support MSI interrupt. Signed-off-by: ernest.zhang <ernest.zhang@bayhubtech.com> --- Changes in V6: 1. Move change log to correct place. 2. Reduce unneeded pr_info prints. 3. In function sdhci_pci_o2_probe_slot, remove using local variable 'mmc' instead of using 'host->mmc'. 3. Make the msi enable code a sperate function. Changes in V5: 1. Because pci_enable_msi is marked as deprecated and should not be used in new code, use pci_alloc_irq_vectors instead. 2. Remove unneeded CONFIG_PCI_MSI macro check. Changes in V4: Enable MSI interrupt if the MSI capability bit is set in capability register. --- drivers/mmc/host/sdhci-pci-o2micro.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/drivers/mmc/host/sdhci-pci-o2micro.c b/drivers/mmc/host/sdhci-pci-o2micro.c index 7747e8b..56bc717 100644 --- a/drivers/mmc/host/sdhci-pci-o2micro.c +++ b/drivers/mmc/host/sdhci-pci-o2micro.c @@ -260,6 +260,29 @@ static void sdhci_pci_o2_fujin2_pci_init(struct sdhci_pci_chip *chip) pci_write_config_dword(chip->pdev, O2_SD_MISC_CTRL4, scratch_32); } +static void sdhci_pci_o2_enable_msi(struct sdhci_pci_chip *chip, + struct sdhci_host *host) +{ + int ret; + + ret = pci_find_capability(chip->pdev, PCI_CAP_ID_MSI); + if (!ret) { + pr_info("%s: unsupport msi, use INTx irq\n", + mmc_hostname(host->mmc)); + return; + } + + ret = pci_alloc_irq_vectors(chip->pdev, 1, 1, + PCI_IRQ_MSI | PCI_IRQ_MSIX); + if (ret < 0) { + pr_err("%s: enable PCI MSI failed, err=%d\n", + mmc_hostname(host->mmc), ret); + return; + } + + host->irq = pci_irq_vector(chip->pdev, 0); +} + int sdhci_pci_o2_probe_slot(struct sdhci_pci_slot *slot) { struct sdhci_pci_chip *chip; @@ -279,6 +302,8 @@ int sdhci_pci_o2_probe_slot(struct sdhci_pci_slot *slot) if (reg & 0x1) host->quirks |= SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12; + sdhci_pci_o2_enable_msi(chip, host); + if (chip->pdev->device == PCI_DEVICE_ID_O2_SEABIRD0) { ret = pci_read_config_dword(chip->pdev, O2_SD_MISC_SETTING, ®); -- 2.7.4 ^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH V6 3/3] mmc: sdhci: Add MSI interrupt support for O2 SD host 2018-06-26 15:46 ` [PATCH V6 3/3] mmc: sdhci: Add MSI interrupt support for O2 SD host ernest.zhang @ 2018-07-10 12:44 ` Adrian Hunter 0 siblings, 0 replies; 6+ messages in thread From: Adrian Hunter @ 2018-07-10 12:44 UTC (permalink / raw) To: ernest.zhang, Ulf Hansson, linux-mmc, linux-kernel Cc: chuanjin.pang, mike.li, chevron.li, shirley.her, xiaoguang.yu, bobby.wu On 26/06/18 18:46, ernest.zhang wrote: > Add MSI interrupt support if the SD host device can support MSI interrupt. > > Signed-off-by: ernest.zhang <ernest.zhang@bayhubtech.com> Acked-by: Adrian Hunter <adrian.hunter@intel.com> > --- > Changes in V6: > 1. Move change log to correct place. > 2. Reduce unneeded pr_info prints. > 3. In function sdhci_pci_o2_probe_slot, remove using local > variable 'mmc' instead of using 'host->mmc'. > 3. Make the msi enable code a sperate function. > > Changes in V5: > 1. Because pci_enable_msi is marked as deprecated and should not be > used in new code, use pci_alloc_irq_vectors instead. > 2. Remove unneeded CONFIG_PCI_MSI macro check. > > Changes in V4: > Enable MSI interrupt if the MSI capability bit is set in > capability register. > --- > drivers/mmc/host/sdhci-pci-o2micro.c | 25 +++++++++++++++++++++++++ > 1 file changed, 25 insertions(+) > > diff --git a/drivers/mmc/host/sdhci-pci-o2micro.c b/drivers/mmc/host/sdhci-pci-o2micro.c > index 7747e8b..56bc717 100644 > --- a/drivers/mmc/host/sdhci-pci-o2micro.c > +++ b/drivers/mmc/host/sdhci-pci-o2micro.c > @@ -260,6 +260,29 @@ static void sdhci_pci_o2_fujin2_pci_init(struct sdhci_pci_chip *chip) > pci_write_config_dword(chip->pdev, O2_SD_MISC_CTRL4, scratch_32); > } > > +static void sdhci_pci_o2_enable_msi(struct sdhci_pci_chip *chip, > + struct sdhci_host *host) > +{ > + int ret; > + > + ret = pci_find_capability(chip->pdev, PCI_CAP_ID_MSI); > + if (!ret) { > + pr_info("%s: unsupport msi, use INTx irq\n", > + mmc_hostname(host->mmc)); > + return; > + } > + > + ret = pci_alloc_irq_vectors(chip->pdev, 1, 1, > + PCI_IRQ_MSI | PCI_IRQ_MSIX); > + if (ret < 0) { > + pr_err("%s: enable PCI MSI failed, err=%d\n", > + mmc_hostname(host->mmc), ret); > + return; > + } > + > + host->irq = pci_irq_vector(chip->pdev, 0); > +} > + > int sdhci_pci_o2_probe_slot(struct sdhci_pci_slot *slot) > { > struct sdhci_pci_chip *chip; > @@ -279,6 +302,8 @@ int sdhci_pci_o2_probe_slot(struct sdhci_pci_slot *slot) > if (reg & 0x1) > host->quirks |= SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12; > > + sdhci_pci_o2_enable_msi(chip, host); > + > if (chip->pdev->device == PCI_DEVICE_ID_O2_SEABIRD0) { > ret = pci_read_config_dword(chip->pdev, > O2_SD_MISC_SETTING, ®); > ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH V6 1/3] mmc: sdhci: Add support for O2 eMMC HS200 mode 2018-06-26 15:46 [PATCH V6 1/3] mmc: sdhci: Add support for O2 eMMC HS200 mode ernest.zhang 2018-06-26 15:46 ` [PATCH V6 2/3] mmc: sdhci: Add support for O2 hardware tuning ernest.zhang 2018-06-26 15:46 ` [PATCH V6 3/3] mmc: sdhci: Add MSI interrupt support for O2 SD host ernest.zhang @ 2018-07-10 12:23 ` Adrian Hunter 2 siblings, 0 replies; 6+ messages in thread From: Adrian Hunter @ 2018-07-10 12:23 UTC (permalink / raw) To: ernest.zhang, Ulf Hansson, linux-mmc, linux-kernel Cc: chuanjin.pang, mike.li, chevron.li, shirley.her, xiaoguang.yu, bobby.wu On 26/06/18 18:46, ernest.zhang wrote: > When use eMMC as boot device, the eMMC signaling voltage is tied to 1.8v > fixed output voltage, bios can set o2 sd host controller PCI configuration > register 0x308 bit4 to 1 to let driver skip 3.3v signaling voltage and > direct use 1.8v singling voltage in eMMC initialize process. > > Signed-off-by: ernest.zhang <ernest.zhang@bayhubtech.com> > --- > Changes in V6: > 1.Move change log to correct place. > 2.Change HS200 mode clock frequency from 208MHz to 200MHz to meet > Specification. That 2nd change should be a separate patch. > > Changes in V5: > Modify code format to pass checkpatch.pl check and add a summary > of what has changed in each version. > > Changes in V4: > Skip SDIO and SD initalization when register 0x308 bit 4 is set, > and modify some typo. > > Changes in V3: > Rebase the patch on the mmc tree 'next' branch. > > Changes in V2: > Modify code format, and delete unused code path. > > Changes in V1: > Check PCIe register 0x308 bit 4 and skip eMMC 3.3v initialization > process if it is set to 1. > --- > drivers/mmc/host/sdhci-pci-o2micro.c | 22 ++++++++++++++++++++-- > 1 file changed, 20 insertions(+), 2 deletions(-) > > diff --git a/drivers/mmc/host/sdhci-pci-o2micro.c b/drivers/mmc/host/sdhci-pci-o2micro.c > index 555970a..94cf3cd 100644 > --- a/drivers/mmc/host/sdhci-pci-o2micro.c > +++ b/drivers/mmc/host/sdhci-pci-o2micro.c > @@ -3,6 +3,7 @@ > * > * Authors: Peter Guo <peter.guo@bayhubtech.com> > * Adam Lee <adam.lee@canonical.com> > + * Ernest Zhang <ernest.zhang@bayhubtech.com> > * > * This software is licensed under the terms of the GNU General Public > * License version 2, as published by the Free Software Foundation, and > @@ -39,6 +40,7 @@ > #define O2_SD_MISC_CTRL4 0xFC > #define O2_SD_TUNING_CTRL 0x300 > #define O2_SD_PLL_SETTING 0x304 > +#define O2_SD_MISC_SETTING 0x308 > #define O2_SD_CLK_SETTING 0x328 > #define O2_SD_CAP_REG2 0x330 > #define O2_SD_CAP_REG0 0x334 > @@ -184,6 +186,7 @@ int sdhci_pci_o2_probe_slot(struct sdhci_pci_slot *slot) > struct sdhci_pci_chip *chip; > struct sdhci_host *host; > u32 reg; > + int ret; > > chip = slot->chip; > host = slot->host; > @@ -197,6 +200,21 @@ int sdhci_pci_o2_probe_slot(struct sdhci_pci_slot *slot) > if (reg & 0x1) > host->quirks |= SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12; > > + if (chip->pdev->device == PCI_DEVICE_ID_O2_SEABIRD0) { > + ret = pci_read_config_dword(chip->pdev, > + O2_SD_MISC_SETTING, ®); > + if (ret) > + return -EIO; > + if (reg & (1 << 4)) { > + pr_info("%s: emmc 1.8v flag is set, force 1.8v signaling voltage\n", > + mmc_hostname(host->mmc)); > + host->flags &= ~SDHCI_SIGNALING_330; > + host->flags |= SDHCI_SIGNALING_180; > + host->mmc->caps2 |= MMC_CAP2_NO_SD; > + host->mmc->caps2 |= MMC_CAP2_NO_SDIO; > + } > + } > + > if (chip->pdev->device != PCI_DEVICE_ID_O2_FUJIN2) > break; > /* set dll watch dog timer */ > @@ -293,7 +311,7 @@ int sdhci_pci_o2_probe(struct sdhci_pci_chip *chip) > > /* Check Whether subId is 0x11 or 0x12 */ > if ((scratch_32 == 0x11) || (scratch_32 == 0x12)) { > - scratch_32 = 0x2c280000; > + scratch_32 = 0x25100000; > > /* Set Base Clock to 208MZ */ Need to change the comment too i.e. 208MZ -> 200 MHz > o2_pci_set_baseclk(chip, scratch_32); > @@ -388,7 +406,7 @@ int sdhci_pci_o2_probe(struct sdhci_pci_chip *chip) > O2_SD_PLL_SETTING, scratch_32); > } else { > scratch_32 &= 0x0000FFFF; > - scratch_32 |= 0x2c280000; > + scratch_32 |= 0x25100000; > > pci_write_config_dword(chip->pdev, > O2_SD_PLL_SETTING, scratch_32); > ^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2018-07-10 12:44 UTC | newest] Thread overview: 6+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2018-06-26 15:46 [PATCH V6 1/3] mmc: sdhci: Add support for O2 eMMC HS200 mode ernest.zhang 2018-06-26 15:46 ` [PATCH V6 2/3] mmc: sdhci: Add support for O2 hardware tuning ernest.zhang 2018-07-10 12:43 ` Adrian Hunter 2018-06-26 15:46 ` [PATCH V6 3/3] mmc: sdhci: Add MSI interrupt support for O2 SD host ernest.zhang 2018-07-10 12:44 ` Adrian Hunter 2018-07-10 12:23 ` [PATCH V6 1/3] mmc: sdhci: Add support for O2 eMMC HS200 mode Adrian Hunter
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).