* [PATCH V1 0/3] Add Genesys Logic GL9767 support
@ 2023-05-12 10:45 Victor Shih
2023-05-12 10:45 ` [PATCH V1 1/3] mmc: sdhci-pci-gli: " Victor Shih
` (2 more replies)
0 siblings, 3 replies; 9+ messages in thread
From: Victor Shih @ 2023-05-12 10:45 UTC (permalink / raw)
To: ulf.hansson, adrian.hunter
Cc: linux-mmc, linux-kernel, benchuanggli, HL.Liu, Greg.tu,
takahiro.akashi, dlunev, Victor Shih
These patches support for the GL9767 chipset and add support SD3/SD Express
mode for the GL9767.
Changes in v1 (May. 12, 2023)
* rebased to the linux-kernel-v6.4.0-rc1 in Ulf Hansson next branch.
* enable MSI interrupt for the GL9767.
* add support SDR mode for the GL9767.
* export sdhci_check_ro() function.
* add support SD Express mode for the GL9767.
Victor Shih (3):
mmc: sdhci-pci-gli: Add Genesys Logic GL9767 support
mmc: sdhci: Export sdhci_check_ro function symbol
mmc: sdhci-pci-gli: Add support SD Express card for GL9767
drivers/mmc/host/sdhci-pci-core.c | 1 +
drivers/mmc/host/sdhci-pci-gli.c | 247 ++++++++++++++++++++++++++++++
drivers/mmc/host/sdhci-pci.h | 2 +
drivers/mmc/host/sdhci.c | 3 +-
drivers/mmc/host/sdhci.h | 1 +
5 files changed, 253 insertions(+), 1 deletion(-)
--
2.25.1
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH V1 1/3] mmc: sdhci-pci-gli: Add Genesys Logic GL9767 support
2023-05-12 10:45 [PATCH V1 0/3] Add Genesys Logic GL9767 support Victor Shih
@ 2023-05-12 10:45 ` Victor Shih
2023-05-15 0:01 ` Ben Chuang
2023-05-12 10:45 ` [PATCH V1 2/3] mmc: sdhci: Export sdhci_check_ro function symbol Victor Shih
2023-05-12 10:45 ` [PATCH V1 3/3] mmc: sdhci-pci-gli: Add support SD Express card for GL9767 Victor Shih
2 siblings, 1 reply; 9+ messages in thread
From: Victor Shih @ 2023-05-12 10:45 UTC (permalink / raw)
To: ulf.hansson, adrian.hunter
Cc: linux-mmc, linux-kernel, benchuanggli, HL.Liu, Greg.tu,
takahiro.akashi, dlunev, Victor Shih, Ben Chuang
Add support for the GL9767 chipset. GL9767 supports
SD3 mode likes UHS-I SDR50, SDR104.
Enable MSI interrupt for GL9767. Some platform do not
support PCI INTx and devices can not work without
interrupt.
Signed-off-by: Ben Chuang <ben.chuang@genesyslogic.com.tw>
Signed-off-by: Victor Shih <victor.shih@genesyslogic.com.tw>
---
drivers/mmc/host/sdhci-pci-core.c | 1 +
drivers/mmc/host/sdhci-pci-gli.c | 132 ++++++++++++++++++++++++++++++
drivers/mmc/host/sdhci-pci.h | 2 +
3 files changed, 135 insertions(+)
diff --git a/drivers/mmc/host/sdhci-pci-core.c b/drivers/mmc/host/sdhci-pci-core.c
index 01975d145200..1c2572c0f012 100644
--- a/drivers/mmc/host/sdhci-pci-core.c
+++ b/drivers/mmc/host/sdhci-pci-core.c
@@ -1903,6 +1903,7 @@ static const struct pci_device_id pci_ids[] = {
SDHCI_PCI_DEVICE(GLI, 9750, gl9750),
SDHCI_PCI_DEVICE(GLI, 9755, gl9755),
SDHCI_PCI_DEVICE(GLI, 9763E, gl9763e),
+ SDHCI_PCI_DEVICE(GLI, 9767, gl9767),
SDHCI_PCI_DEVICE_CLASS(AMD, SYSTEM_SDHCI, PCI_CLASS_MASK, amd),
/* Generic SD host controller */
{PCI_DEVICE_CLASS(SYSTEM_SDHCI, PCI_CLASS_MASK)},
diff --git a/drivers/mmc/host/sdhci-pci-gli.c b/drivers/mmc/host/sdhci-pci-gli.c
index 633a8ee8f8c5..300512740cb0 100644
--- a/drivers/mmc/host/sdhci-pci-gli.c
+++ b/drivers/mmc/host/sdhci-pci-gli.c
@@ -149,6 +149,32 @@
#define PCI_GLI_9755_PM_CTRL 0xFC
#define PCI_GLI_9755_PM_STATE GENMASK(1, 0)
+#define SDHCI_GLI_9767_GM_BURST_SIZE 0x510
+#define SDHCI_GLI_9767_GM_BURST_SIZE_AXI_ALWAYS_SET BIT(8)
+
+#define PCIE_GLI_9767_VHS 0x884
+#define GLI_9767_VHS_REV GENMASK(19, 16)
+#define GLI_9767_VHS_REV_R 0x0
+#define GLI_9767_VHS_REV_M 0x1
+#define GLI_9767_VHS_REV_W 0x2
+
+#define PCIE_GLI_9767_PWR_MACRO_CTL 0x8D0
+#define PCIE_GLI_9767_PWR_MACRO_CTL_LOW_VOLTAGE GENMASK(3, 0)
+#define PCIE_GLI_9767_PWR_MACRO_CTL_LD0_LOW_OUTPUT_VOLTAGE GENMASK(15, 12)
+#define PCIE_GLI_9767_PWR_MACRO_CTL_LD0_LOW_OUTPUT_VOLTAGE_VALUE 0x7
+#define PCIE_GLI_9767_PWR_MACRO_CTL_RCLK_AMPLITUDE_CTL GENMASK(29, 28)
+#define PCIE_GLI_9767_PWR_MACRO_CTL_RCLK_AMPLITUDE_CTL_VALUE 0x3
+
+#define PCIE_GLI_9767_SCR 0x8E0
+#define PCIE_GLI_9767_SCR_AUTO_AXI_W_BURST BIT(6)
+#define PCIE_GLI_9767_SCR_AUTO_AXI_R_BURST BIT(7)
+#define PCIE_GLI_9767_SCR_AXI_REQ BIT(9)
+#define PCIE_GLI_9767_SCR_CARD_DET_PWR_SAVING_EN BIT(10)
+#define PCIE_GLI_9767_SCR_SYSTEM_CLK_SELECT_MODE0 BIT(16)
+#define PCIE_GLI_9767_SCR_SYSTEM_CLK_SELECT_MODE1 BIT(17)
+#define PCIE_GLI_9767_SCR_CORE_PWR_D3_OFF BIT(21)
+#define PCIE_GLI_9767_SCR_CFG_RST_DATA_LINK_DOWN BIT(30)
+
#define GLI_MAX_TUNING_LOOP 40
/* Genesys Logic chipset */
@@ -693,6 +719,61 @@ static void gl9755_hw_setting(struct sdhci_pci_slot *slot)
gl9755_wt_off(pdev);
}
+static void gli_set_9767(struct sdhci_host *host)
+{
+ u32 value;
+
+ value = sdhci_readl(host, SDHCI_GLI_9767_GM_BURST_SIZE);
+ value &= ~SDHCI_GLI_9767_GM_BURST_SIZE_AXI_ALWAYS_SET;
+ sdhci_writel(host, value, SDHCI_GLI_9767_GM_BURST_SIZE);
+}
+
+static void gl9767_hw_setting(struct sdhci_pci_slot *slot)
+{
+ struct pci_dev *pdev = slot->chip->pdev;
+ u32 value;
+
+ pci_read_config_dword(pdev, PCIE_GLI_9767_VHS, &value);
+ value &= ~GLI_9767_VHS_REV;
+ value |= FIELD_PREP(GLI_9767_VHS_REV, GLI_9767_VHS_REV_W);
+ pci_write_config_dword(pdev, PCIE_GLI_9767_VHS, value);
+
+ pci_read_config_dword(pdev, PCIE_GLI_9767_PWR_MACRO_CTL, &value);
+ value &= ~(PCIE_GLI_9767_PWR_MACRO_CTL_LOW_VOLTAGE |
+ PCIE_GLI_9767_PWR_MACRO_CTL_LD0_LOW_OUTPUT_VOLTAGE |
+ PCIE_GLI_9767_PWR_MACRO_CTL_RCLK_AMPLITUDE_CTL);
+
+ value |= PCIE_GLI_9767_PWR_MACRO_CTL_LOW_VOLTAGE |
+ FIELD_PREP(PCIE_GLI_9767_PWR_MACRO_CTL_LD0_LOW_OUTPUT_VOLTAGE,
+ PCIE_GLI_9767_PWR_MACRO_CTL_LD0_LOW_OUTPUT_VOLTAGE_VALUE) |
+ FIELD_PREP(PCIE_GLI_9767_PWR_MACRO_CTL_RCLK_AMPLITUDE_CTL,
+ PCIE_GLI_9767_PWR_MACRO_CTL_RCLK_AMPLITUDE_CTL_VALUE);
+ pci_write_config_dword(pdev, PCIE_GLI_9767_PWR_MACRO_CTL, value);
+
+ pci_read_config_dword(pdev, PCIE_GLI_9767_SCR, &value);
+ value &= ~(PCIE_GLI_9767_SCR_SYSTEM_CLK_SELECT_MODE0 |
+ PCIE_GLI_9767_SCR_SYSTEM_CLK_SELECT_MODE1 |
+ PCIE_GLI_9767_SCR_CFG_RST_DATA_LINK_DOWN);
+
+ value |= PCIE_GLI_9767_SCR_AUTO_AXI_W_BURST |
+ PCIE_GLI_9767_SCR_AUTO_AXI_R_BURST |
+ PCIE_GLI_9767_SCR_AXI_REQ |
+ PCIE_GLI_9767_SCR_CARD_DET_PWR_SAVING_EN |
+ PCIE_GLI_9767_SCR_CORE_PWR_D3_OFF;
+ pci_write_config_dword(pdev, PCIE_GLI_9767_SCR, value);
+
+ pci_read_config_dword(pdev, PCIE_GLI_9767_VHS, &value);
+ value &= ~GLI_9767_VHS_REV;
+ value |= FIELD_PREP(GLI_9767_VHS_REV, GLI_9767_VHS_REV_R);
+ pci_write_config_dword(pdev, PCIE_GLI_9767_VHS, value);
+}
+
+static void sdhci_gl9767_reset(struct sdhci_host *host, u8 mask)
+{
+ sdhci_reset(host, mask);
+ gli_set_9767(host);
+}
+
static int gli_probe_slot_gl9750(struct sdhci_pci_slot *slot)
{
struct sdhci_host *host = slot->host;
@@ -717,6 +798,19 @@ static int gli_probe_slot_gl9755(struct sdhci_pci_slot *slot)
return 0;
}
+static int gli_probe_slot_gl9767(struct sdhci_pci_slot *slot)
+{
+ struct sdhci_host *host = slot->host;
+
+ gli_set_9767(host);
+ gl9767_hw_setting(slot);
+ gli_pcie_enable_msi(slot);
+ slot->host->mmc->caps2 |= MMC_CAP2_NO_SDIO;
+ sdhci_enable_v4_mode(host);
+
+ return 0;
+}
+
static void sdhci_gli_voltage_switch(struct sdhci_host *host)
{
/*
@@ -740,6 +834,25 @@ static void sdhci_gli_voltage_switch(struct sdhci_host *host)
usleep_range(100000, 110000);
}
+static void sdhci_gl9767_voltage_switch(struct sdhci_host *host)
+{
+ /*
+ * According to Section 3.6.1 signal voltage switch procedure in
+ * SD Host Controller Simplified Spec. 4.20, steps 6~8 are as
+ * follows:
+ * (6) Set 1.8V Signal Enable in the Host Control 2 register.
+ * (7) Wait 5ms. 1.8V voltage regulator shall be stable within this
+ * period.
+ * (8) If 1.8V Signal Enable is cleared by Host Controller, go to
+ * step (12).
+ *
+ * Wait 5ms after set 1.8V signal enable in Host Control 2 register
+ * to ensure 1.8V signal enable bit is set by GL9767.
+ *
+ */
+ usleep_range(5000, 5500);
+}
+
static void sdhci_gl9750_reset(struct sdhci_host *host, u8 mask)
{
sdhci_reset(host, mask);
@@ -1150,3 +1263,22 @@ const struct sdhci_pci_fixes sdhci_gl9763e = {
#endif
.add_host = gl9763e_add_host,
};
+
+static const struct sdhci_ops sdhci_gl9767_ops = {
+ .set_clock = sdhci_set_clock,
+ .enable_dma = sdhci_pci_enable_dma,
+ .set_bus_width = sdhci_set_bus_width,
+ .reset = sdhci_gl9767_reset,
+ .set_uhs_signaling = sdhci_set_uhs_signaling,
+ .voltage_switch = sdhci_gl9767_voltage_switch,
+};
+
+const struct sdhci_pci_fixes sdhci_gl9767 = {
+ .quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC,
+ .quirks2 = SDHCI_QUIRK2_BROKEN_DDR50,
+ .probe_slot = gli_probe_slot_gl9767,
+ .ops = &sdhci_gl9767_ops,
+#ifdef CONFIG_PM_SLEEP
+ .resume = sdhci_pci_gli_resume,
+#endif
+};
diff --git a/drivers/mmc/host/sdhci-pci.h b/drivers/mmc/host/sdhci-pci.h
index 3661a224fb04..9c8863956381 100644
--- a/drivers/mmc/host/sdhci-pci.h
+++ b/drivers/mmc/host/sdhci-pci.h
@@ -76,6 +76,7 @@
#define PCI_DEVICE_ID_GLI_9755 0x9755
#define PCI_DEVICE_ID_GLI_9750 0x9750
#define PCI_DEVICE_ID_GLI_9763E 0xe763
+#define PCI_DEVICE_ID_GLI_9767 0x9767
/*
* PCI device class and mask
@@ -195,5 +196,6 @@ extern const struct sdhci_pci_fixes sdhci_o2;
extern const struct sdhci_pci_fixes sdhci_gl9750;
extern const struct sdhci_pci_fixes sdhci_gl9755;
extern const struct sdhci_pci_fixes sdhci_gl9763e;
+extern const struct sdhci_pci_fixes sdhci_gl9767;
#endif /* __SDHCI_PCI_H */
--
2.25.1
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH V1 2/3] mmc: sdhci: Export sdhci_check_ro function symbol
2023-05-12 10:45 [PATCH V1 0/3] Add Genesys Logic GL9767 support Victor Shih
2023-05-12 10:45 ` [PATCH V1 1/3] mmc: sdhci-pci-gli: " Victor Shih
@ 2023-05-12 10:45 ` Victor Shih
2023-05-12 10:45 ` [PATCH V1 3/3] mmc: sdhci-pci-gli: Add support SD Express card for GL9767 Victor Shih
2 siblings, 0 replies; 9+ messages in thread
From: Victor Shih @ 2023-05-12 10:45 UTC (permalink / raw)
To: ulf.hansson, adrian.hunter
Cc: linux-mmc, linux-kernel, benchuanggli, HL.Liu, Greg.tu,
takahiro.akashi, dlunev, Victor Shih, Ben Chuang
Export sdhci_check_ro() function symbols which are used by other
SD Host controller drivers modules.
Signed-off-by: Ben Chuang <ben.chuang@genesyslogic.com.tw>
Signed-off-by: Victor Shih <victor.shih@genesyslogic.com.tw>
---
drivers/mmc/host/sdhci.c | 3 ++-
drivers/mmc/host/sdhci.h | 1 +
2 files changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 3241916141d7..0c9b2006e24a 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -2513,7 +2513,7 @@ int sdhci_get_cd_nogpio(struct mmc_host *mmc)
}
EXPORT_SYMBOL_GPL(sdhci_get_cd_nogpio);
-static int sdhci_check_ro(struct sdhci_host *host)
+int sdhci_check_ro(struct sdhci_host *host)
{
unsigned long flags;
int is_readonly;
@@ -2536,6 +2536,7 @@ static int sdhci_check_ro(struct sdhci_host *host)
return host->quirks & SDHCI_QUIRK_INVERTED_WRITE_PROTECT ?
!is_readonly : is_readonly;
}
+EXPORT_SYMBOL_GPL(sdhci_check_ro);
#define SAMPLE_COUNT 5
diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
index f4f2085c274c..54e9e13108e3 100644
--- a/drivers/mmc/host/sdhci.h
+++ b/drivers/mmc/host/sdhci.h
@@ -780,6 +780,7 @@ void sdhci_set_power_and_bus_voltage(struct sdhci_host *host,
void sdhci_set_power_noreg(struct sdhci_host *host, unsigned char mode,
unsigned short vdd);
int sdhci_get_cd_nogpio(struct mmc_host *mmc);
+int sdhci_check_ro(struct sdhci_host *host);
void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq);
int sdhci_request_atomic(struct mmc_host *mmc, struct mmc_request *mrq);
void sdhci_set_bus_width(struct sdhci_host *host, int width);
--
2.25.1
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH V1 3/3] mmc: sdhci-pci-gli: Add support SD Express card for GL9767
2023-05-12 10:45 [PATCH V1 0/3] Add Genesys Logic GL9767 support Victor Shih
2023-05-12 10:45 ` [PATCH V1 1/3] mmc: sdhci-pci-gli: " Victor Shih
2023-05-12 10:45 ` [PATCH V1 2/3] mmc: sdhci: Export sdhci_check_ro function symbol Victor Shih
@ 2023-05-12 10:45 ` Victor Shih
2023-05-15 0:14 ` Ben Chuang
2023-05-29 9:36 ` Adrian Hunter
2 siblings, 2 replies; 9+ messages in thread
From: Victor Shih @ 2023-05-12 10:45 UTC (permalink / raw)
To: ulf.hansson, adrian.hunter
Cc: linux-mmc, linux-kernel, benchuanggli, HL.Liu, Greg.tu,
takahiro.akashi, dlunev, Victor Shih, Ben Chuang
Add support SD Express card for GL9767. The workflow of the
SD Express card in GL9767 is as below.
1. GL9767 operates in SD mode and set MMC_CAP2_SD_EXP flag.
2. If card is inserted, Host send CMD8 to ask the capabilities
of the card.
3. If the card has PCIe capability and write protect is not
enable, then init_sd_express() will be invoked.
4. GL9767 switch from SD mode to PCIe/NVMe mode and mmc driver
handover control to NVMe driver.
5. If card is removed, GL9767 will return to SD mode.
Signed-off-by: Ben Chuang <ben.chuang@genesyslogic.com.tw>
Signed-off-by: Victor Shih <victor.shih@genesyslogic.com.tw>
---
drivers/mmc/host/sdhci-pci-gli.c | 115 +++++++++++++++++++++++++++++++
1 file changed, 115 insertions(+)
diff --git a/drivers/mmc/host/sdhci-pci-gli.c b/drivers/mmc/host/sdhci-pci-gli.c
index 300512740cb0..a0f9c24439be 100644
--- a/drivers/mmc/host/sdhci-pci-gli.c
+++ b/drivers/mmc/host/sdhci-pci-gli.c
@@ -158,6 +158,13 @@
#define GLI_9767_VHS_REV_M 0x1
#define GLI_9767_VHS_REV_W 0x2
+#define PCIE_GLI_9767_CFG 0x8A0
+#define PCIE_GLI_9767_CFG_LOW_PWR_OFF BIT(12)
+
+#define PCIE_GLI_9767_COMBO_MUX_CTL 0x8C8
+#define PCIE_GLI_9767_COMBO_MUX_CTL_RST_EN BIT(6)
+#define PCIE_GLI_9767_COMBO_MUX_CTL_WAIT_PERST_EN BIT(10)
+
#define PCIE_GLI_9767_PWR_MACRO_CTL 0x8D0
#define PCIE_GLI_9767_PWR_MACRO_CTL_LOW_VOLTAGE GENMASK(3, 0)
#define PCIE_GLI_9767_PWR_MACRO_CTL_LD0_LOW_OUTPUT_VOLTAGE GENMASK(15, 12)
@@ -175,6 +182,27 @@
#define PCIE_GLI_9767_SCR_CORE_PWR_D3_OFF BIT(21)
#define PCIE_GLI_9767_SCR_CFG_RST_DATA_LINK_DOWN BIT(30)
+#define PCIE_GLI_9767_SDHC_CAP 0x91C
+#define PCIE_GLI_9767_SDHC_CAP_SDEI_RESULT BIT(5)
+
+#define PCIE_GLI_9767_SD_EXPRESS_CTL 0x940
+#define PCIE_GLI_9767_SD_EXPRESS_CTL_SDEI_EXE BIT(0)
+#define PCIE_GLI_9767_SD_EXPRESS_CTL_SD_EXPRESS_MODE BIT(1)
+
+#define PCIE_GLI_9767_SD_DATA_MULTI_CTL 0x944
+#define PCIE_GLI_9767_SD_DATA_MULTI_CTL_DISCONNECT_TIME GENMASK(23, 16)
+#define PCIE_GLI_9767_SD_DATA_MULTI_CTL_DISCONNECT_TIME_VALUE 0x64
+
+#define PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_REG2 0x950
+#define PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_REG2_SDEI_COMPLETE BIT(0)
+#define PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_REG2_SDEI_GEN_TIMER GENMASK(1, 0)
+
+#define PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_EN_REG2 0x954
+#define PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_EN_REG2_SDEI_COMPLETE_STATUS_EN GENMASK(1, 0)
+
+#define PCIE_GLI_9767_NORMAL_ERR_INT_SIGNAL_EN_REG2 0x958
+#define PCIE_GLI_9767_NORMAL_ERR_INT_SIGNAL_EN_REG2_SDEI_COMPLETE_SIGNAL_EN GENMASK(1, 0)
+
#define GLI_MAX_TUNING_LOOP 40
/* Genesys Logic chipset */
@@ -774,6 +802,91 @@ static void sdhci_gl9767_reset(struct sdhci_host *host, u8 mask)
gli_set_9767(host);
}
+static int gl9767_init_sd_express(struct mmc_host *mmc, struct mmc_ios *ios)
+{
+ struct sdhci_host *host = mmc_priv(mmc);
+ struct sdhci_pci_slot *slot = sdhci_priv(host);
+ struct pci_dev *pdev;
+ u32 value;
+ int i;
+
+ pdev = slot->chip->pdev;
+
+ if (sdhci_check_ro(host)) {
+ mmc->ios.timing &= ~(MMC_TIMING_SD_EXP | MMC_TIMING_SD_EXP_1_2V);
+ return 0;
+ }
+
+ pci_read_config_dword(pdev, PCIE_GLI_9767_VHS, &value);
+ value &= ~GLI_9767_VHS_REV;
+ value |= FIELD_PREP(GLI_9767_VHS_REV, GLI_9767_VHS_REV_W);
+ pci_write_config_dword(pdev, PCIE_GLI_9767_VHS, value);
+
+ pci_read_config_dword(pdev, PCIE_GLI_9767_COMBO_MUX_CTL, &value);
+ value &= ~(PCIE_GLI_9767_COMBO_MUX_CTL_RST_EN | PCIE_GLI_9767_COMBO_MUX_CTL_WAIT_PERST_EN);
+ pci_write_config_dword(pdev, PCIE_GLI_9767_COMBO_MUX_CTL, value);
+
+ pci_read_config_dword(pdev, PCIE_GLI_9767_SD_DATA_MULTI_CTL, &value);
+ value &= ~PCIE_GLI_9767_SD_DATA_MULTI_CTL_DISCONNECT_TIME;
+ value |= FIELD_PREP(PCIE_GLI_9767_SD_DATA_MULTI_CTL_DISCONNECT_TIME,
+ PCIE_GLI_9767_SD_DATA_MULTI_CTL_DISCONNECT_TIME_VALUE);
+ pci_write_config_dword(pdev, PCIE_GLI_9767_SD_DATA_MULTI_CTL, value);
+
+ pci_read_config_dword(pdev, PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_REG2, &value);
+ value |= PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_REG2_SDEI_GEN_TIMER;
+ pci_write_config_dword(pdev, PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_REG2, value);
+
+ pci_read_config_dword(pdev, PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_EN_REG2, &value);
+ value |= PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_EN_REG2_SDEI_COMPLETE_STATUS_EN;
+ pci_write_config_dword(pdev, PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_EN_REG2, value);
+
+ pci_read_config_dword(pdev, PCIE_GLI_9767_NORMAL_ERR_INT_SIGNAL_EN_REG2, &value);
+ value |= PCIE_GLI_9767_NORMAL_ERR_INT_SIGNAL_EN_REG2_SDEI_COMPLETE_SIGNAL_EN;
+ pci_write_config_dword(pdev, PCIE_GLI_9767_NORMAL_ERR_INT_SIGNAL_EN_REG2, value);
+
+ pci_read_config_dword(pdev, PCIE_GLI_9767_CFG, &value);
+ value |= PCIE_GLI_9767_CFG_LOW_PWR_OFF;
+ pci_write_config_dword(pdev, PCIE_GLI_9767_CFG, value);
+
+ value = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
+ value &= ~(SDHCI_CLOCK_CARD_EN | SDHCI_CLOCK_PLL_EN);
+ sdhci_writew(host, value, SDHCI_CLOCK_CONTROL);
+
+ value = sdhci_readb(host, SDHCI_POWER_CONTROL);
+ value |= ((SDHCI_POWER_180 | SDHCI_POWER_ON) << 4);
+ sdhci_writeb(host, value, SDHCI_POWER_CONTROL);
+
+ pci_read_config_dword(pdev, PCIE_GLI_9767_SD_EXPRESS_CTL, &value);
+ value |= PCIE_GLI_9767_SD_EXPRESS_CTL_SDEI_EXE;
+ pci_write_config_dword(pdev, PCIE_GLI_9767_SD_EXPRESS_CTL, value);
+
+ for (i = 0; i < 10; i++) {
+ mdelay(10);
+ pci_read_config_dword(pdev, PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_REG2, &value);
+ if (value & PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_REG2_SDEI_COMPLETE) {
+ pci_write_config_dword(pdev, PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_REG2,
+ value);
+ break;
+ }
+ }
+
+ pci_read_config_dword(pdev, PCIE_GLI_9767_SDHC_CAP, &value);
+ if ((value & PCIE_GLI_9767_SDHC_CAP_SDEI_RESULT) == PCIE_GLI_9767_SDHC_CAP_SDEI_RESULT) {
+ pci_read_config_dword(pdev, PCIE_GLI_9767_SD_EXPRESS_CTL, &value);
+ value |= PCIE_GLI_9767_SD_EXPRESS_CTL_SD_EXPRESS_MODE;
+ pci_write_config_dword(pdev, PCIE_GLI_9767_SD_EXPRESS_CTL, value);
+ } else {
+ mmc->ios.timing &= ~(MMC_TIMING_SD_EXP | MMC_TIMING_SD_EXP_1_2V);
+ }
+
+ pci_read_config_dword(pdev, PCIE_GLI_9767_VHS, &value);
+ value &= ~GLI_9767_VHS_REV;
+ value |= FIELD_PREP(GLI_9767_VHS_REV, GLI_9767_VHS_REV_R);
+ pci_write_config_dword(pdev, PCIE_GLI_9767_VHS, value);
+
+ return 0;
+}
+
static int gli_probe_slot_gl9750(struct sdhci_pci_slot *slot)
{
struct sdhci_host *host = slot->host;
@@ -806,6 +919,8 @@ static int gli_probe_slot_gl9767(struct sdhci_pci_slot *slot)
gl9767_hw_setting(slot);
gli_pcie_enable_msi(slot);
slot->host->mmc->caps2 |= MMC_CAP2_NO_SDIO;
+ host->mmc->caps2 |= MMC_CAP2_SD_EXP;
+ host->mmc_host_ops.init_sd_express = gl9767_init_sd_express;
sdhci_enable_v4_mode(host);
return 0;
--
2.25.1
^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH V1 1/3] mmc: sdhci-pci-gli: Add Genesys Logic GL9767 support
2023-05-12 10:45 ` [PATCH V1 1/3] mmc: sdhci-pci-gli: " Victor Shih
@ 2023-05-15 0:01 ` Ben Chuang
0 siblings, 0 replies; 9+ messages in thread
From: Ben Chuang @ 2023-05-15 0:01 UTC (permalink / raw)
To: Victor Shih
Cc: ulf.hansson, adrian.hunter, linux-mmc, linux-kernel, HL.Liu,
Greg.tu, takahiro.akashi, dlunev, Victor Shih, Ben Chuang
Hi Victor,
One thing, get in the habit of running checkpatch.pl before submitting patches.
checkpatch.pl says.
"From:/Signed-off-by: email address mismatch: 'From: Victor Shih
<victorshihgli@gmail.com>' != 'Signed-off-by: Victor Shih
<victor.shih@genesyslogic.com.tw>'"
It reminds you that maybe the first line of the email body needs a
line "Form: Victor Shih <victor.shih@genesyslogic.com.tw>'".
man git-format-patch and see --form option
Best regards,
Ben
On Fri, May 12, 2023 at 6:47 PM Victor Shih <victorshihgli@gmail.com> wrote:
>
> Add support for the GL9767 chipset. GL9767 supports
> SD3 mode likes UHS-I SDR50, SDR104.
> Enable MSI interrupt for GL9767. Some platform do not
> support PCI INTx and devices can not work without
> interrupt.
>
> Signed-off-by: Ben Chuang <ben.chuang@genesyslogic.com.tw>
> Signed-off-by: Victor Shih <victor.shih@genesyslogic.com.tw>
> ---
> drivers/mmc/host/sdhci-pci-core.c | 1 +
> drivers/mmc/host/sdhci-pci-gli.c | 132 ++++++++++++++++++++++++++++++
> drivers/mmc/host/sdhci-pci.h | 2 +
> 3 files changed, 135 insertions(+)
>
> diff --git a/drivers/mmc/host/sdhci-pci-core.c b/drivers/mmc/host/sdhci-pci-core.c
> index 01975d145200..1c2572c0f012 100644
> --- a/drivers/mmc/host/sdhci-pci-core.c
> +++ b/drivers/mmc/host/sdhci-pci-core.c
> @@ -1903,6 +1903,7 @@ static const struct pci_device_id pci_ids[] = {
> SDHCI_PCI_DEVICE(GLI, 9750, gl9750),
> SDHCI_PCI_DEVICE(GLI, 9755, gl9755),
> SDHCI_PCI_DEVICE(GLI, 9763E, gl9763e),
> + SDHCI_PCI_DEVICE(GLI, 9767, gl9767),
> SDHCI_PCI_DEVICE_CLASS(AMD, SYSTEM_SDHCI, PCI_CLASS_MASK, amd),
> /* Generic SD host controller */
> {PCI_DEVICE_CLASS(SYSTEM_SDHCI, PCI_CLASS_MASK)},
> diff --git a/drivers/mmc/host/sdhci-pci-gli.c b/drivers/mmc/host/sdhci-pci-gli.c
> index 633a8ee8f8c5..300512740cb0 100644
> --- a/drivers/mmc/host/sdhci-pci-gli.c
> +++ b/drivers/mmc/host/sdhci-pci-gli.c
> @@ -149,6 +149,32 @@
> #define PCI_GLI_9755_PM_CTRL 0xFC
> #define PCI_GLI_9755_PM_STATE GENMASK(1, 0)
>
> +#define SDHCI_GLI_9767_GM_BURST_SIZE 0x510
> +#define SDHCI_GLI_9767_GM_BURST_SIZE_AXI_ALWAYS_SET BIT(8)
> +
> +#define PCIE_GLI_9767_VHS 0x884
> +#define GLI_9767_VHS_REV GENMASK(19, 16)
> +#define GLI_9767_VHS_REV_R 0x0
> +#define GLI_9767_VHS_REV_M 0x1
> +#define GLI_9767_VHS_REV_W 0x2
> +
> +#define PCIE_GLI_9767_PWR_MACRO_CTL 0x8D0
> +#define PCIE_GLI_9767_PWR_MACRO_CTL_LOW_VOLTAGE GENMASK(3, 0)
> +#define PCIE_GLI_9767_PWR_MACRO_CTL_LD0_LOW_OUTPUT_VOLTAGE GENMASK(15, 12)
> +#define PCIE_GLI_9767_PWR_MACRO_CTL_LD0_LOW_OUTPUT_VOLTAGE_VALUE 0x7
> +#define PCIE_GLI_9767_PWR_MACRO_CTL_RCLK_AMPLITUDE_CTL GENMASK(29, 28)
> +#define PCIE_GLI_9767_PWR_MACRO_CTL_RCLK_AMPLITUDE_CTL_VALUE 0x3
> +
> +#define PCIE_GLI_9767_SCR 0x8E0
> +#define PCIE_GLI_9767_SCR_AUTO_AXI_W_BURST BIT(6)
> +#define PCIE_GLI_9767_SCR_AUTO_AXI_R_BURST BIT(7)
> +#define PCIE_GLI_9767_SCR_AXI_REQ BIT(9)
> +#define PCIE_GLI_9767_SCR_CARD_DET_PWR_SAVING_EN BIT(10)
> +#define PCIE_GLI_9767_SCR_SYSTEM_CLK_SELECT_MODE0 BIT(16)
> +#define PCIE_GLI_9767_SCR_SYSTEM_CLK_SELECT_MODE1 BIT(17)
> +#define PCIE_GLI_9767_SCR_CORE_PWR_D3_OFF BIT(21)
> +#define PCIE_GLI_9767_SCR_CFG_RST_DATA_LINK_DOWN BIT(30)
> +
> #define GLI_MAX_TUNING_LOOP 40
>
> /* Genesys Logic chipset */
> @@ -693,6 +719,61 @@ static void gl9755_hw_setting(struct sdhci_pci_slot *slot)
> gl9755_wt_off(pdev);
> }
>
> +static void gli_set_9767(struct sdhci_host *host)
> +{
> + u32 value;
> +
> + value = sdhci_readl(host, SDHCI_GLI_9767_GM_BURST_SIZE);
> + value &= ~SDHCI_GLI_9767_GM_BURST_SIZE_AXI_ALWAYS_SET;
> + sdhci_writel(host, value, SDHCI_GLI_9767_GM_BURST_SIZE);
> +}
> +
> +static void gl9767_hw_setting(struct sdhci_pci_slot *slot)
> +{
> + struct pci_dev *pdev = slot->chip->pdev;
> + u32 value;
> +
> + pci_read_config_dword(pdev, PCIE_GLI_9767_VHS, &value);
> + value &= ~GLI_9767_VHS_REV;
> + value |= FIELD_PREP(GLI_9767_VHS_REV, GLI_9767_VHS_REV_W);
> + pci_write_config_dword(pdev, PCIE_GLI_9767_VHS, value);
> +
> + pci_read_config_dword(pdev, PCIE_GLI_9767_PWR_MACRO_CTL, &value);
> + value &= ~(PCIE_GLI_9767_PWR_MACRO_CTL_LOW_VOLTAGE |
> + PCIE_GLI_9767_PWR_MACRO_CTL_LD0_LOW_OUTPUT_VOLTAGE |
> + PCIE_GLI_9767_PWR_MACRO_CTL_RCLK_AMPLITUDE_CTL);
> +
> + value |= PCIE_GLI_9767_PWR_MACRO_CTL_LOW_VOLTAGE |
> + FIELD_PREP(PCIE_GLI_9767_PWR_MACRO_CTL_LD0_LOW_OUTPUT_VOLTAGE,
> + PCIE_GLI_9767_PWR_MACRO_CTL_LD0_LOW_OUTPUT_VOLTAGE_VALUE) |
> + FIELD_PREP(PCIE_GLI_9767_PWR_MACRO_CTL_RCLK_AMPLITUDE_CTL,
> + PCIE_GLI_9767_PWR_MACRO_CTL_RCLK_AMPLITUDE_CTL_VALUE);
> + pci_write_config_dword(pdev, PCIE_GLI_9767_PWR_MACRO_CTL, value);
> +
> + pci_read_config_dword(pdev, PCIE_GLI_9767_SCR, &value);
> + value &= ~(PCIE_GLI_9767_SCR_SYSTEM_CLK_SELECT_MODE0 |
> + PCIE_GLI_9767_SCR_SYSTEM_CLK_SELECT_MODE1 |
> + PCIE_GLI_9767_SCR_CFG_RST_DATA_LINK_DOWN);
> +
> + value |= PCIE_GLI_9767_SCR_AUTO_AXI_W_BURST |
> + PCIE_GLI_9767_SCR_AUTO_AXI_R_BURST |
> + PCIE_GLI_9767_SCR_AXI_REQ |
> + PCIE_GLI_9767_SCR_CARD_DET_PWR_SAVING_EN |
> + PCIE_GLI_9767_SCR_CORE_PWR_D3_OFF;
> + pci_write_config_dword(pdev, PCIE_GLI_9767_SCR, value);
> +
> + pci_read_config_dword(pdev, PCIE_GLI_9767_VHS, &value);
> + value &= ~GLI_9767_VHS_REV;
> + value |= FIELD_PREP(GLI_9767_VHS_REV, GLI_9767_VHS_REV_R);
> + pci_write_config_dword(pdev, PCIE_GLI_9767_VHS, value);
> +}
> +
> +static void sdhci_gl9767_reset(struct sdhci_host *host, u8 mask)
> +{
> + sdhci_reset(host, mask);
> + gli_set_9767(host);
> +}
> +
> static int gli_probe_slot_gl9750(struct sdhci_pci_slot *slot)
> {
> struct sdhci_host *host = slot->host;
> @@ -717,6 +798,19 @@ static int gli_probe_slot_gl9755(struct sdhci_pci_slot *slot)
> return 0;
> }
>
> +static int gli_probe_slot_gl9767(struct sdhci_pci_slot *slot)
> +{
> + struct sdhci_host *host = slot->host;
> +
> + gli_set_9767(host);
> + gl9767_hw_setting(slot);
> + gli_pcie_enable_msi(slot);
> + slot->host->mmc->caps2 |= MMC_CAP2_NO_SDIO;
> + sdhci_enable_v4_mode(host);
> +
> + return 0;
> +}
> +
> static void sdhci_gli_voltage_switch(struct sdhci_host *host)
> {
> /*
> @@ -740,6 +834,25 @@ static void sdhci_gli_voltage_switch(struct sdhci_host *host)
> usleep_range(100000, 110000);
> }
>
> +static void sdhci_gl9767_voltage_switch(struct sdhci_host *host)
> +{
> + /*
> + * According to Section 3.6.1 signal voltage switch procedure in
> + * SD Host Controller Simplified Spec. 4.20, steps 6~8 are as
> + * follows:
> + * (6) Set 1.8V Signal Enable in the Host Control 2 register.
> + * (7) Wait 5ms. 1.8V voltage regulator shall be stable within this
> + * period.
> + * (8) If 1.8V Signal Enable is cleared by Host Controller, go to
> + * step (12).
> + *
> + * Wait 5ms after set 1.8V signal enable in Host Control 2 register
> + * to ensure 1.8V signal enable bit is set by GL9767.
> + *
> + */
> + usleep_range(5000, 5500);
> +}
> +
> static void sdhci_gl9750_reset(struct sdhci_host *host, u8 mask)
> {
> sdhci_reset(host, mask);
> @@ -1150,3 +1263,22 @@ const struct sdhci_pci_fixes sdhci_gl9763e = {
> #endif
> .add_host = gl9763e_add_host,
> };
> +
> +static const struct sdhci_ops sdhci_gl9767_ops = {
> + .set_clock = sdhci_set_clock,
> + .enable_dma = sdhci_pci_enable_dma,
> + .set_bus_width = sdhci_set_bus_width,
> + .reset = sdhci_gl9767_reset,
> + .set_uhs_signaling = sdhci_set_uhs_signaling,
> + .voltage_switch = sdhci_gl9767_voltage_switch,
> +};
> +
> +const struct sdhci_pci_fixes sdhci_gl9767 = {
> + .quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC,
> + .quirks2 = SDHCI_QUIRK2_BROKEN_DDR50,
> + .probe_slot = gli_probe_slot_gl9767,
> + .ops = &sdhci_gl9767_ops,
> +#ifdef CONFIG_PM_SLEEP
> + .resume = sdhci_pci_gli_resume,
> +#endif
> +};
> diff --git a/drivers/mmc/host/sdhci-pci.h b/drivers/mmc/host/sdhci-pci.h
> index 3661a224fb04..9c8863956381 100644
> --- a/drivers/mmc/host/sdhci-pci.h
> +++ b/drivers/mmc/host/sdhci-pci.h
> @@ -76,6 +76,7 @@
> #define PCI_DEVICE_ID_GLI_9755 0x9755
> #define PCI_DEVICE_ID_GLI_9750 0x9750
> #define PCI_DEVICE_ID_GLI_9763E 0xe763
> +#define PCI_DEVICE_ID_GLI_9767 0x9767
>
> /*
> * PCI device class and mask
> @@ -195,5 +196,6 @@ extern const struct sdhci_pci_fixes sdhci_o2;
> extern const struct sdhci_pci_fixes sdhci_gl9750;
> extern const struct sdhci_pci_fixes sdhci_gl9755;
> extern const struct sdhci_pci_fixes sdhci_gl9763e;
> +extern const struct sdhci_pci_fixes sdhci_gl9767;
>
> #endif /* __SDHCI_PCI_H */
> --
> 2.25.1
>
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH V1 3/3] mmc: sdhci-pci-gli: Add support SD Express card for GL9767
2023-05-12 10:45 ` [PATCH V1 3/3] mmc: sdhci-pci-gli: Add support SD Express card for GL9767 Victor Shih
@ 2023-05-15 0:14 ` Ben Chuang
2023-05-30 9:51 ` Victor Shih
2023-05-29 9:36 ` Adrian Hunter
1 sibling, 1 reply; 9+ messages in thread
From: Ben Chuang @ 2023-05-15 0:14 UTC (permalink / raw)
To: Victor Shih
Cc: ulf.hansson, adrian.hunter, linux-mmc, linux-kernel, HL.Liu,
Greg.tu, takahiro.akashi, dlunev, Victor Shih, Ben Chuang
Hi Victor,
On Fri, May 12, 2023 at 6:47 PM Victor Shih <victorshihgli@gmail.com> wrote:
>
> Add support SD Express card for GL9767. The workflow of the
> SD Express card in GL9767 is as below.
> 1. GL9767 operates in SD mode and set MMC_CAP2_SD_EXP flag.
> 2. If card is inserted, Host send CMD8 to ask the capabilities
> of the card.
> 3. If the card has PCIe capability and write protect is not
> enable, then init_sd_express() will be invoked.
> 4. GL9767 switch from SD mode to PCIe/NVMe mode and mmc driver
> handover control to NVMe driver.
> 5. If card is removed, GL9767 will return to SD mode.
>
> Signed-off-by: Ben Chuang <ben.chuang@genesyslogic.com.tw>
> Signed-off-by: Victor Shih <victor.shih@genesyslogic.com.tw>
> ---
> drivers/mmc/host/sdhci-pci-gli.c | 115 +++++++++++++++++++++++++++++++
> 1 file changed, 115 insertions(+)
>
> diff --git a/drivers/mmc/host/sdhci-pci-gli.c b/drivers/mmc/host/sdhci-pci-gli.c
> index 300512740cb0..a0f9c24439be 100644
> --- a/drivers/mmc/host/sdhci-pci-gli.c
> +++ b/drivers/mmc/host/sdhci-pci-gli.c
> @@ -158,6 +158,13 @@
> #define GLI_9767_VHS_REV_M 0x1
> #define GLI_9767_VHS_REV_W 0x2
>
> +#define PCIE_GLI_9767_CFG 0x8A0
> +#define PCIE_GLI_9767_CFG_LOW_PWR_OFF BIT(12)
> +
> +#define PCIE_GLI_9767_COMBO_MUX_CTL 0x8C8
> +#define PCIE_GLI_9767_COMBO_MUX_CTL_RST_EN BIT(6)
> +#define PCIE_GLI_9767_COMBO_MUX_CTL_WAIT_PERST_EN BIT(10)
> +
> #define PCIE_GLI_9767_PWR_MACRO_CTL 0x8D0
> #define PCIE_GLI_9767_PWR_MACRO_CTL_LOW_VOLTAGE GENMASK(3, 0)
> #define PCIE_GLI_9767_PWR_MACRO_CTL_LD0_LOW_OUTPUT_VOLTAGE GENMASK(15, 12)
> @@ -175,6 +182,27 @@
> #define PCIE_GLI_9767_SCR_CORE_PWR_D3_OFF BIT(21)
> #define PCIE_GLI_9767_SCR_CFG_RST_DATA_LINK_DOWN BIT(30)
>
> +#define PCIE_GLI_9767_SDHC_CAP 0x91C
> +#define PCIE_GLI_9767_SDHC_CAP_SDEI_RESULT BIT(5)
> +
> +#define PCIE_GLI_9767_SD_EXPRESS_CTL 0x940
> +#define PCIE_GLI_9767_SD_EXPRESS_CTL_SDEI_EXE BIT(0)
> +#define PCIE_GLI_9767_SD_EXPRESS_CTL_SD_EXPRESS_MODE BIT(1)
> +
> +#define PCIE_GLI_9767_SD_DATA_MULTI_CTL 0x944
> +#define PCIE_GLI_9767_SD_DATA_MULTI_CTL_DISCONNECT_TIME GENMASK(23, 16)
> +#define PCIE_GLI_9767_SD_DATA_MULTI_CTL_DISCONNECT_TIME_VALUE 0x64
> +
> +#define PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_REG2 0x950
> +#define PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_REG2_SDEI_COMPLETE BIT(0)
> +#define PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_REG2_SDEI_GEN_TIMER GENMASK(1, 0)
> +
> +#define PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_EN_REG2 0x954
> +#define PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_EN_REG2_SDEI_COMPLETE_STATUS_EN GENMASK(1, 0)
> +
> +#define PCIE_GLI_9767_NORMAL_ERR_INT_SIGNAL_EN_REG2 0x958
> +#define PCIE_GLI_9767_NORMAL_ERR_INT_SIGNAL_EN_REG2_SDEI_COMPLETE_SIGNAL_EN GENMASK(1, 0)
> +
> #define GLI_MAX_TUNING_LOOP 40
>
> /* Genesys Logic chipset */
> @@ -774,6 +802,91 @@ static void sdhci_gl9767_reset(struct sdhci_host *host, u8 mask)
> gli_set_9767(host);
> }
>
> +static int gl9767_init_sd_express(struct mmc_host *mmc, struct mmc_ios *ios)
> +{
> + struct sdhci_host *host = mmc_priv(mmc);
> + struct sdhci_pci_slot *slot = sdhci_priv(host);
> + struct pci_dev *pdev;
> + u32 value;
> + int i;
> +
> + pdev = slot->chip->pdev;
> +
> + if (sdhci_check_ro(host)) {
> + mmc->ios.timing &= ~(MMC_TIMING_SD_EXP | MMC_TIMING_SD_EXP_1_2V);
> + return 0;
> + }
> +
> + pci_read_config_dword(pdev, PCIE_GLI_9767_VHS, &value);
> + value &= ~GLI_9767_VHS_REV;
> + value |= FIELD_PREP(GLI_9767_VHS_REV, GLI_9767_VHS_REV_W);
> + pci_write_config_dword(pdev, PCIE_GLI_9767_VHS, value);
> +
> + pci_read_config_dword(pdev, PCIE_GLI_9767_COMBO_MUX_CTL, &value);
> + value &= ~(PCIE_GLI_9767_COMBO_MUX_CTL_RST_EN | PCIE_GLI_9767_COMBO_MUX_CTL_WAIT_PERST_EN);
> + pci_write_config_dword(pdev, PCIE_GLI_9767_COMBO_MUX_CTL, value);
> +
> + pci_read_config_dword(pdev, PCIE_GLI_9767_SD_DATA_MULTI_CTL, &value);
> + value &= ~PCIE_GLI_9767_SD_DATA_MULTI_CTL_DISCONNECT_TIME;
> + value |= FIELD_PREP(PCIE_GLI_9767_SD_DATA_MULTI_CTL_DISCONNECT_TIME,
> + PCIE_GLI_9767_SD_DATA_MULTI_CTL_DISCONNECT_TIME_VALUE);
> + pci_write_config_dword(pdev, PCIE_GLI_9767_SD_DATA_MULTI_CTL, value);
> +
> + pci_read_config_dword(pdev, PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_REG2, &value);
> + value |= PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_REG2_SDEI_GEN_TIMER;
> + pci_write_config_dword(pdev, PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_REG2, value);
> +
> + pci_read_config_dword(pdev, PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_EN_REG2, &value);
> + value |= PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_EN_REG2_SDEI_COMPLETE_STATUS_EN;
> + pci_write_config_dword(pdev, PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_EN_REG2, value);
> +
> + pci_read_config_dword(pdev, PCIE_GLI_9767_NORMAL_ERR_INT_SIGNAL_EN_REG2, &value);
> + value |= PCIE_GLI_9767_NORMAL_ERR_INT_SIGNAL_EN_REG2_SDEI_COMPLETE_SIGNAL_EN;
> + pci_write_config_dword(pdev, PCIE_GLI_9767_NORMAL_ERR_INT_SIGNAL_EN_REG2, value);
> +
> + pci_read_config_dword(pdev, PCIE_GLI_9767_CFG, &value);
> + value |= PCIE_GLI_9767_CFG_LOW_PWR_OFF;
> + pci_write_config_dword(pdev, PCIE_GLI_9767_CFG, value);
> +
> + value = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
> + value &= ~(SDHCI_CLOCK_CARD_EN | SDHCI_CLOCK_PLL_EN);
> + sdhci_writew(host, value, SDHCI_CLOCK_CONTROL);
> +
> + value = sdhci_readb(host, SDHCI_POWER_CONTROL);
> + value |= ((SDHCI_POWER_180 | SDHCI_POWER_ON) << 4);
> + sdhci_writeb(host, value, SDHCI_POWER_CONTROL);
> +
> + pci_read_config_dword(pdev, PCIE_GLI_9767_SD_EXPRESS_CTL, &value);
> + value |= PCIE_GLI_9767_SD_EXPRESS_CTL_SDEI_EXE;
> + pci_write_config_dword(pdev, PCIE_GLI_9767_SD_EXPRESS_CTL, value);
> +
> + for (i = 0; i < 10; i++) {
> + mdelay(10);
A little question.
Can you explain or comment on the reason for up to 10 loops (max. 100 ms wait),
For example "because of asic specs..." or "hardware measurements".
Best regards,
Ben
> + pci_read_config_dword(pdev, PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_REG2, &value);
> + if (value & PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_REG2_SDEI_COMPLETE) {
> + pci_write_config_dword(pdev, PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_REG2,
> + value);
> + break;
> + }
> + }
> +
> + pci_read_config_dword(pdev, PCIE_GLI_9767_SDHC_CAP, &value);
> + if ((value & PCIE_GLI_9767_SDHC_CAP_SDEI_RESULT) == PCIE_GLI_9767_SDHC_CAP_SDEI_RESULT) {
> + pci_read_config_dword(pdev, PCIE_GLI_9767_SD_EXPRESS_CTL, &value);
> + value |= PCIE_GLI_9767_SD_EXPRESS_CTL_SD_EXPRESS_MODE;
> + pci_write_config_dword(pdev, PCIE_GLI_9767_SD_EXPRESS_CTL, value);
> + } else {
> + mmc->ios.timing &= ~(MMC_TIMING_SD_EXP | MMC_TIMING_SD_EXP_1_2V);
> + }
> +
> + pci_read_config_dword(pdev, PCIE_GLI_9767_VHS, &value);
> + value &= ~GLI_9767_VHS_REV;
> + value |= FIELD_PREP(GLI_9767_VHS_REV, GLI_9767_VHS_REV_R);
> + pci_write_config_dword(pdev, PCIE_GLI_9767_VHS, value);
> +
> + return 0;
> +}
> +
> static int gli_probe_slot_gl9750(struct sdhci_pci_slot *slot)
> {
> struct sdhci_host *host = slot->host;
> @@ -806,6 +919,8 @@ static int gli_probe_slot_gl9767(struct sdhci_pci_slot *slot)
> gl9767_hw_setting(slot);
> gli_pcie_enable_msi(slot);
> slot->host->mmc->caps2 |= MMC_CAP2_NO_SDIO;
> + host->mmc->caps2 |= MMC_CAP2_SD_EXP;
> + host->mmc_host_ops.init_sd_express = gl9767_init_sd_express;
> sdhci_enable_v4_mode(host);
>
> return 0;
> --
> 2.25.1
>
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH V1 3/3] mmc: sdhci-pci-gli: Add support SD Express card for GL9767
2023-05-12 10:45 ` [PATCH V1 3/3] mmc: sdhci-pci-gli: Add support SD Express card for GL9767 Victor Shih
2023-05-15 0:14 ` Ben Chuang
@ 2023-05-29 9:36 ` Adrian Hunter
2023-05-30 9:52 ` Victor Shih
1 sibling, 1 reply; 9+ messages in thread
From: Adrian Hunter @ 2023-05-29 9:36 UTC (permalink / raw)
To: Victor Shih, ulf.hansson
Cc: linux-mmc, linux-kernel, benchuanggli, HL.Liu, Greg.tu,
takahiro.akashi, dlunev, Victor Shih, Ben Chuang
On 12/05/23 13:45, Victor Shih wrote:
> Add support SD Express card for GL9767. The workflow of the
> SD Express card in GL9767 is as below.
> 1. GL9767 operates in SD mode and set MMC_CAP2_SD_EXP flag.
> 2. If card is inserted, Host send CMD8 to ask the capabilities
> of the card.
> 3. If the card has PCIe capability and write protect is not
> enable, then init_sd_express() will be invoked.
Could explain about why not write protect
> 4. GL9767 switch from SD mode to PCIe/NVMe mode and mmc driver
> handover control to NVMe driver.
> 5. If card is removed, GL9767 will return to SD mode.
>
> Signed-off-by: Ben Chuang <ben.chuang@genesyslogic.com.tw>
> Signed-off-by: Victor Shih <victor.shih@genesyslogic.com.tw>
As Ben pointed out, please try to use the same email address
for From: and Signed-off-by:
> ---
> drivers/mmc/host/sdhci-pci-gli.c | 115 +++++++++++++++++++++++++++++++
> 1 file changed, 115 insertions(+)
>
> diff --git a/drivers/mmc/host/sdhci-pci-gli.c b/drivers/mmc/host/sdhci-pci-gli.c
> index 300512740cb0..a0f9c24439be 100644
> --- a/drivers/mmc/host/sdhci-pci-gli.c
> +++ b/drivers/mmc/host/sdhci-pci-gli.c
> @@ -158,6 +158,13 @@
> #define GLI_9767_VHS_REV_M 0x1
> #define GLI_9767_VHS_REV_W 0x2
>
> +#define PCIE_GLI_9767_CFG 0x8A0
> +#define PCIE_GLI_9767_CFG_LOW_PWR_OFF BIT(12)
> +
> +#define PCIE_GLI_9767_COMBO_MUX_CTL 0x8C8
> +#define PCIE_GLI_9767_COMBO_MUX_CTL_RST_EN BIT(6)
> +#define PCIE_GLI_9767_COMBO_MUX_CTL_WAIT_PERST_EN BIT(10)
> +
> #define PCIE_GLI_9767_PWR_MACRO_CTL 0x8D0
> #define PCIE_GLI_9767_PWR_MACRO_CTL_LOW_VOLTAGE GENMASK(3, 0)
> #define PCIE_GLI_9767_PWR_MACRO_CTL_LD0_LOW_OUTPUT_VOLTAGE GENMASK(15, 12)
> @@ -175,6 +182,27 @@
> #define PCIE_GLI_9767_SCR_CORE_PWR_D3_OFF BIT(21)
> #define PCIE_GLI_9767_SCR_CFG_RST_DATA_LINK_DOWN BIT(30)
>
> +#define PCIE_GLI_9767_SDHC_CAP 0x91C
> +#define PCIE_GLI_9767_SDHC_CAP_SDEI_RESULT BIT(5)
> +
> +#define PCIE_GLI_9767_SD_EXPRESS_CTL 0x940
> +#define PCIE_GLI_9767_SD_EXPRESS_CTL_SDEI_EXE BIT(0)
> +#define PCIE_GLI_9767_SD_EXPRESS_CTL_SD_EXPRESS_MODE BIT(1)
> +
> +#define PCIE_GLI_9767_SD_DATA_MULTI_CTL 0x944
> +#define PCIE_GLI_9767_SD_DATA_MULTI_CTL_DISCONNECT_TIME GENMASK(23, 16)
> +#define PCIE_GLI_9767_SD_DATA_MULTI_CTL_DISCONNECT_TIME_VALUE 0x64
> +
> +#define PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_REG2 0x950
> +#define PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_REG2_SDEI_COMPLETE BIT(0)
> +#define PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_REG2_SDEI_GEN_TIMER GENMASK(1, 0)
> +
> +#define PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_EN_REG2 0x954
> +#define PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_EN_REG2_SDEI_COMPLETE_STATUS_EN GENMASK(1, 0)
> +
> +#define PCIE_GLI_9767_NORMAL_ERR_INT_SIGNAL_EN_REG2 0x958
> +#define PCIE_GLI_9767_NORMAL_ERR_INT_SIGNAL_EN_REG2_SDEI_COMPLETE_SIGNAL_EN GENMASK(1, 0)
> +
> #define GLI_MAX_TUNING_LOOP 40
>
> /* Genesys Logic chipset */
> @@ -774,6 +802,91 @@ static void sdhci_gl9767_reset(struct sdhci_host *host, u8 mask)
> gli_set_9767(host);
> }
>
> +static int gl9767_init_sd_express(struct mmc_host *mmc, struct mmc_ios *ios)
> +{
> + struct sdhci_host *host = mmc_priv(mmc);
> + struct sdhci_pci_slot *slot = sdhci_priv(host);
> + struct pci_dev *pdev;
> + u32 value;
> + int i;
> +
> + pdev = slot->chip->pdev;
> +
> + if (sdhci_check_ro(host)) {
I think mmc->get_ro(mmc) would be fine here instead.
> + mmc->ios.timing &= ~(MMC_TIMING_SD_EXP | MMC_TIMING_SD_EXP_1_2V);
> + return 0;
> + }
> +
> + pci_read_config_dword(pdev, PCIE_GLI_9767_VHS, &value);
> + value &= ~GLI_9767_VHS_REV;
> + value |= FIELD_PREP(GLI_9767_VHS_REV, GLI_9767_VHS_REV_W);
> + pci_write_config_dword(pdev, PCIE_GLI_9767_VHS, value);
> +
> + pci_read_config_dword(pdev, PCIE_GLI_9767_COMBO_MUX_CTL, &value);
> + value &= ~(PCIE_GLI_9767_COMBO_MUX_CTL_RST_EN | PCIE_GLI_9767_COMBO_MUX_CTL_WAIT_PERST_EN);
> + pci_write_config_dword(pdev, PCIE_GLI_9767_COMBO_MUX_CTL, value);
> +
> + pci_read_config_dword(pdev, PCIE_GLI_9767_SD_DATA_MULTI_CTL, &value);
> + value &= ~PCIE_GLI_9767_SD_DATA_MULTI_CTL_DISCONNECT_TIME;
> + value |= FIELD_PREP(PCIE_GLI_9767_SD_DATA_MULTI_CTL_DISCONNECT_TIME,
> + PCIE_GLI_9767_SD_DATA_MULTI_CTL_DISCONNECT_TIME_VALUE);
> + pci_write_config_dword(pdev, PCIE_GLI_9767_SD_DATA_MULTI_CTL, value);
> +
> + pci_read_config_dword(pdev, PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_REG2, &value);
> + value |= PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_REG2_SDEI_GEN_TIMER;
> + pci_write_config_dword(pdev, PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_REG2, value);
> +
> + pci_read_config_dword(pdev, PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_EN_REG2, &value);
> + value |= PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_EN_REG2_SDEI_COMPLETE_STATUS_EN;
> + pci_write_config_dword(pdev, PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_EN_REG2, value);
> +
> + pci_read_config_dword(pdev, PCIE_GLI_9767_NORMAL_ERR_INT_SIGNAL_EN_REG2, &value);
> + value |= PCIE_GLI_9767_NORMAL_ERR_INT_SIGNAL_EN_REG2_SDEI_COMPLETE_SIGNAL_EN;
> + pci_write_config_dword(pdev, PCIE_GLI_9767_NORMAL_ERR_INT_SIGNAL_EN_REG2, value);
> +
> + pci_read_config_dword(pdev, PCIE_GLI_9767_CFG, &value);
> + value |= PCIE_GLI_9767_CFG_LOW_PWR_OFF;
> + pci_write_config_dword(pdev, PCIE_GLI_9767_CFG, value);
> +
> + value = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
> + value &= ~(SDHCI_CLOCK_CARD_EN | SDHCI_CLOCK_PLL_EN);
> + sdhci_writew(host, value, SDHCI_CLOCK_CONTROL);
> +
> + value = sdhci_readb(host, SDHCI_POWER_CONTROL);
> + value |= ((SDHCI_POWER_180 | SDHCI_POWER_ON) << 4);
> + sdhci_writeb(host, value, SDHCI_POWER_CONTROL);
> +
> + pci_read_config_dword(pdev, PCIE_GLI_9767_SD_EXPRESS_CTL, &value);
> + value |= PCIE_GLI_9767_SD_EXPRESS_CTL_SDEI_EXE;
> + pci_write_config_dword(pdev, PCIE_GLI_9767_SD_EXPRESS_CTL, value);
> +
> + for (i = 0; i < 10; i++) {
> + mdelay(10);
This should be msleep() or usleep_range()
> + pci_read_config_dword(pdev, PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_REG2, &value);
> + if (value & PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_REG2_SDEI_COMPLETE) {
> + pci_write_config_dword(pdev, PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_REG2,
> + value);
> + break;
> + }
> + }
> +
> + pci_read_config_dword(pdev, PCIE_GLI_9767_SDHC_CAP, &value);
> + if ((value & PCIE_GLI_9767_SDHC_CAP_SDEI_RESULT) == PCIE_GLI_9767_SDHC_CAP_SDEI_RESULT) {
> + pci_read_config_dword(pdev, PCIE_GLI_9767_SD_EXPRESS_CTL, &value);
> + value |= PCIE_GLI_9767_SD_EXPRESS_CTL_SD_EXPRESS_MODE;
> + pci_write_config_dword(pdev, PCIE_GLI_9767_SD_EXPRESS_CTL, value);
> + } else {
> + mmc->ios.timing &= ~(MMC_TIMING_SD_EXP | MMC_TIMING_SD_EXP_1_2V);
> + }
> +
> + pci_read_config_dword(pdev, PCIE_GLI_9767_VHS, &value);
> + value &= ~GLI_9767_VHS_REV;
> + value |= FIELD_PREP(GLI_9767_VHS_REV, GLI_9767_VHS_REV_R);
> + pci_write_config_dword(pdev, PCIE_GLI_9767_VHS, value);
> +
> + return 0;
> +}
> +
> static int gli_probe_slot_gl9750(struct sdhci_pci_slot *slot)
> {
> struct sdhci_host *host = slot->host;
> @@ -806,6 +919,8 @@ static int gli_probe_slot_gl9767(struct sdhci_pci_slot *slot)
> gl9767_hw_setting(slot);
> gli_pcie_enable_msi(slot);
> slot->host->mmc->caps2 |= MMC_CAP2_NO_SDIO;
> + host->mmc->caps2 |= MMC_CAP2_SD_EXP;
> + host->mmc_host_ops.init_sd_express = gl9767_init_sd_express;
> sdhci_enable_v4_mode(host);
>
> return 0;
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH V1 3/3] mmc: sdhci-pci-gli: Add support SD Express card for GL9767
2023-05-15 0:14 ` Ben Chuang
@ 2023-05-30 9:51 ` Victor Shih
0 siblings, 0 replies; 9+ messages in thread
From: Victor Shih @ 2023-05-30 9:51 UTC (permalink / raw)
To: Ben Chuang
Cc: ulf.hansson, adrian.hunter, linux-mmc, linux-kernel, HL.Liu,
Greg.tu, Victor Shih, Ben Chuang
Hi, Ben
On Mon, May 15, 2023 at 8:15 AM Ben Chuang <benchuanggli@gmail.com> wrote:
>
> Hi Victor,
>
> On Fri, May 12, 2023 at 6:47 PM Victor Shih <victorshihgli@gmail.com> wrote:
> >
> > Add support SD Express card for GL9767. The workflow of the
> > SD Express card in GL9767 is as below.
> > 1. GL9767 operates in SD mode and set MMC_CAP2_SD_EXP flag.
> > 2. If card is inserted, Host send CMD8 to ask the capabilities
> > of the card.
> > 3. If the card has PCIe capability and write protect is not
> > enable, then init_sd_express() will be invoked.
> > 4. GL9767 switch from SD mode to PCIe/NVMe mode and mmc driver
> > handover control to NVMe driver.
> > 5. If card is removed, GL9767 will return to SD mode.
> >
> > Signed-off-by: Ben Chuang <ben.chuang@genesyslogic.com.tw>
> > Signed-off-by: Victor Shih <victor.shih@genesyslogic.com.tw>
> > ---
> > drivers/mmc/host/sdhci-pci-gli.c | 115 +++++++++++++++++++++++++++++++
> > 1 file changed, 115 insertions(+)
> >
> > diff --git a/drivers/mmc/host/sdhci-pci-gli.c b/drivers/mmc/host/sdhci-pci-gli.c
> > index 300512740cb0..a0f9c24439be 100644
> > --- a/drivers/mmc/host/sdhci-pci-gli.c
> > +++ b/drivers/mmc/host/sdhci-pci-gli.c
> > @@ -158,6 +158,13 @@
> > #define GLI_9767_VHS_REV_M 0x1
> > #define GLI_9767_VHS_REV_W 0x2
> >
> > +#define PCIE_GLI_9767_CFG 0x8A0
> > +#define PCIE_GLI_9767_CFG_LOW_PWR_OFF BIT(12)
> > +
> > +#define PCIE_GLI_9767_COMBO_MUX_CTL 0x8C8
> > +#define PCIE_GLI_9767_COMBO_MUX_CTL_RST_EN BIT(6)
> > +#define PCIE_GLI_9767_COMBO_MUX_CTL_WAIT_PERST_EN BIT(10)
> > +
> > #define PCIE_GLI_9767_PWR_MACRO_CTL 0x8D0
> > #define PCIE_GLI_9767_PWR_MACRO_CTL_LOW_VOLTAGE GENMASK(3, 0)
> > #define PCIE_GLI_9767_PWR_MACRO_CTL_LD0_LOW_OUTPUT_VOLTAGE GENMASK(15, 12)
> > @@ -175,6 +182,27 @@
> > #define PCIE_GLI_9767_SCR_CORE_PWR_D3_OFF BIT(21)
> > #define PCIE_GLI_9767_SCR_CFG_RST_DATA_LINK_DOWN BIT(30)
> >
> > +#define PCIE_GLI_9767_SDHC_CAP 0x91C
> > +#define PCIE_GLI_9767_SDHC_CAP_SDEI_RESULT BIT(5)
> > +
> > +#define PCIE_GLI_9767_SD_EXPRESS_CTL 0x940
> > +#define PCIE_GLI_9767_SD_EXPRESS_CTL_SDEI_EXE BIT(0)
> > +#define PCIE_GLI_9767_SD_EXPRESS_CTL_SD_EXPRESS_MODE BIT(1)
> > +
> > +#define PCIE_GLI_9767_SD_DATA_MULTI_CTL 0x944
> > +#define PCIE_GLI_9767_SD_DATA_MULTI_CTL_DISCONNECT_TIME GENMASK(23, 16)
> > +#define PCIE_GLI_9767_SD_DATA_MULTI_CTL_DISCONNECT_TIME_VALUE 0x64
> > +
> > +#define PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_REG2 0x950
> > +#define PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_REG2_SDEI_COMPLETE BIT(0)
> > +#define PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_REG2_SDEI_GEN_TIMER GENMASK(1, 0)
> > +
> > +#define PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_EN_REG2 0x954
> > +#define PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_EN_REG2_SDEI_COMPLETE_STATUS_EN GENMASK(1, 0)
> > +
> > +#define PCIE_GLI_9767_NORMAL_ERR_INT_SIGNAL_EN_REG2 0x958
> > +#define PCIE_GLI_9767_NORMAL_ERR_INT_SIGNAL_EN_REG2_SDEI_COMPLETE_SIGNAL_EN GENMASK(1, 0)
> > +
> > #define GLI_MAX_TUNING_LOOP 40
> >
> > /* Genesys Logic chipset */
> > @@ -774,6 +802,91 @@ static void sdhci_gl9767_reset(struct sdhci_host *host, u8 mask)
> > gli_set_9767(host);
> > }
> >
> > +static int gl9767_init_sd_express(struct mmc_host *mmc, struct mmc_ios *ios)
> > +{
> > + struct sdhci_host *host = mmc_priv(mmc);
> > + struct sdhci_pci_slot *slot = sdhci_priv(host);
> > + struct pci_dev *pdev;
> > + u32 value;
> > + int i;
> > +
> > + pdev = slot->chip->pdev;
> > +
> > + if (sdhci_check_ro(host)) {
> > + mmc->ios.timing &= ~(MMC_TIMING_SD_EXP | MMC_TIMING_SD_EXP_1_2V);
> > + return 0;
> > + }
> > +
> > + pci_read_config_dword(pdev, PCIE_GLI_9767_VHS, &value);
> > + value &= ~GLI_9767_VHS_REV;
> > + value |= FIELD_PREP(GLI_9767_VHS_REV, GLI_9767_VHS_REV_W);
> > + pci_write_config_dword(pdev, PCIE_GLI_9767_VHS, value);
> > +
> > + pci_read_config_dword(pdev, PCIE_GLI_9767_COMBO_MUX_CTL, &value);
> > + value &= ~(PCIE_GLI_9767_COMBO_MUX_CTL_RST_EN | PCIE_GLI_9767_COMBO_MUX_CTL_WAIT_PERST_EN);
> > + pci_write_config_dword(pdev, PCIE_GLI_9767_COMBO_MUX_CTL, value);
> > +
> > + pci_read_config_dword(pdev, PCIE_GLI_9767_SD_DATA_MULTI_CTL, &value);
> > + value &= ~PCIE_GLI_9767_SD_DATA_MULTI_CTL_DISCONNECT_TIME;
> > + value |= FIELD_PREP(PCIE_GLI_9767_SD_DATA_MULTI_CTL_DISCONNECT_TIME,
> > + PCIE_GLI_9767_SD_DATA_MULTI_CTL_DISCONNECT_TIME_VALUE);
> > + pci_write_config_dword(pdev, PCIE_GLI_9767_SD_DATA_MULTI_CTL, value);
> > +
> > + pci_read_config_dword(pdev, PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_REG2, &value);
> > + value |= PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_REG2_SDEI_GEN_TIMER;
> > + pci_write_config_dword(pdev, PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_REG2, value);
> > +
> > + pci_read_config_dword(pdev, PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_EN_REG2, &value);
> > + value |= PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_EN_REG2_SDEI_COMPLETE_STATUS_EN;
> > + pci_write_config_dword(pdev, PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_EN_REG2, value);
> > +
> > + pci_read_config_dword(pdev, PCIE_GLI_9767_NORMAL_ERR_INT_SIGNAL_EN_REG2, &value);
> > + value |= PCIE_GLI_9767_NORMAL_ERR_INT_SIGNAL_EN_REG2_SDEI_COMPLETE_SIGNAL_EN;
> > + pci_write_config_dword(pdev, PCIE_GLI_9767_NORMAL_ERR_INT_SIGNAL_EN_REG2, value);
> > +
> > + pci_read_config_dword(pdev, PCIE_GLI_9767_CFG, &value);
> > + value |= PCIE_GLI_9767_CFG_LOW_PWR_OFF;
> > + pci_write_config_dword(pdev, PCIE_GLI_9767_CFG, value);
> > +
> > + value = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
> > + value &= ~(SDHCI_CLOCK_CARD_EN | SDHCI_CLOCK_PLL_EN);
> > + sdhci_writew(host, value, SDHCI_CLOCK_CONTROL);
> > +
> > + value = sdhci_readb(host, SDHCI_POWER_CONTROL);
> > + value |= ((SDHCI_POWER_180 | SDHCI_POWER_ON) << 4);
> > + sdhci_writeb(host, value, SDHCI_POWER_CONTROL);
> > +
> > + pci_read_config_dword(pdev, PCIE_GLI_9767_SD_EXPRESS_CTL, &value);
> > + value |= PCIE_GLI_9767_SD_EXPRESS_CTL_SDEI_EXE;
> > + pci_write_config_dword(pdev, PCIE_GLI_9767_SD_EXPRESS_CTL, value);
> > +
> > + for (i = 0; i < 10; i++) {
> > + mdelay(10);
>
> A little question.
> Can you explain or comment on the reason for up to 10 loops (max. 100 ms wait),
> For example "because of asic specs..." or "hardware measurements".
>
> Best regards,
> Ben
>
Because specs define the time between Power valid to CLKREQ at most 1ms.
To be on the safe side I will update to 3 loops(max. 30 ms wait) in Patch v2.
> > + pci_read_config_dword(pdev, PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_REG2, &value);
> > + if (value & PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_REG2_SDEI_COMPLETE) {
> > + pci_write_config_dword(pdev, PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_REG2,
> > + value);
> > + break;
> > + }
> > + }
> > +
> > + pci_read_config_dword(pdev, PCIE_GLI_9767_SDHC_CAP, &value);
> > + if ((value & PCIE_GLI_9767_SDHC_CAP_SDEI_RESULT) == PCIE_GLI_9767_SDHC_CAP_SDEI_RESULT) {
> > + pci_read_config_dword(pdev, PCIE_GLI_9767_SD_EXPRESS_CTL, &value);
> > + value |= PCIE_GLI_9767_SD_EXPRESS_CTL_SD_EXPRESS_MODE;
> > + pci_write_config_dword(pdev, PCIE_GLI_9767_SD_EXPRESS_CTL, value);
> > + } else {
> > + mmc->ios.timing &= ~(MMC_TIMING_SD_EXP | MMC_TIMING_SD_EXP_1_2V);
> > + }
> > +
> > + pci_read_config_dword(pdev, PCIE_GLI_9767_VHS, &value);
> > + value &= ~GLI_9767_VHS_REV;
> > + value |= FIELD_PREP(GLI_9767_VHS_REV, GLI_9767_VHS_REV_R);
> > + pci_write_config_dword(pdev, PCIE_GLI_9767_VHS, value);
> > +
> > + return 0;
> > +}
> > +
> > static int gli_probe_slot_gl9750(struct sdhci_pci_slot *slot)
> > {
> > struct sdhci_host *host = slot->host;
> > @@ -806,6 +919,8 @@ static int gli_probe_slot_gl9767(struct sdhci_pci_slot *slot)
> > gl9767_hw_setting(slot);
> > gli_pcie_enable_msi(slot);
> > slot->host->mmc->caps2 |= MMC_CAP2_NO_SDIO;
> > + host->mmc->caps2 |= MMC_CAP2_SD_EXP;
> > + host->mmc_host_ops.init_sd_express = gl9767_init_sd_express;
> > sdhci_enable_v4_mode(host);
> >
> > return 0;
> > --
> > 2.25.1
> >
Thanks, Victor Shih
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH V1 3/3] mmc: sdhci-pci-gli: Add support SD Express card for GL9767
2023-05-29 9:36 ` Adrian Hunter
@ 2023-05-30 9:52 ` Victor Shih
0 siblings, 0 replies; 9+ messages in thread
From: Victor Shih @ 2023-05-30 9:52 UTC (permalink / raw)
To: Adrian Hunter
Cc: ulf.hansson, linux-mmc, linux-kernel, benchuanggli, HL.Liu,
Greg.tu, Victor Shih, Ben Chuang
Hi, Adrian
On Mon, May 29, 2023 at 5:36 PM Adrian Hunter <adrian.hunter@intel.com> wrote:
>
> On 12/05/23 13:45, Victor Shih wrote:
> > Add support SD Express card for GL9767. The workflow of the
> > SD Express card in GL9767 is as below.
> > 1. GL9767 operates in SD mode and set MMC_CAP2_SD_EXP flag.
> > 2. If card is inserted, Host send CMD8 to ask the capabilities
> > of the card.
> > 3. If the card has PCIe capability and write protect is not
> > enable, then init_sd_express() will be invoked.
>
> Could explain about why not write protect
>
I will update the commit message as below in Patch v2:
If the card has been put in write protect state then the SD features supported
by SD mode but not supported by PCIe mode, therefore GL9767 will switch
to SD mode.
> > 4. GL9767 switch from SD mode to PCIe/NVMe mode and mmc driver
> > handover control to NVMe driver.
> > 5. If card is removed, GL9767 will return to SD mode.
> >
> > Signed-off-by: Ben Chuang <ben.chuang@genesyslogic.com.tw>
> > Signed-off-by: Victor Shih <victor.shih@genesyslogic.com.tw>
>
> As Ben pointed out, please try to use the same email address
> for From: and Signed-off-by:
>
I will be careful about this in the Patch v2.
> > ---
> > drivers/mmc/host/sdhci-pci-gli.c | 115 +++++++++++++++++++++++++++++++
> > 1 file changed, 115 insertions(+)
> >
> > diff --git a/drivers/mmc/host/sdhci-pci-gli.c b/drivers/mmc/host/sdhci-pci-gli.c
> > index 300512740cb0..a0f9c24439be 100644
> > --- a/drivers/mmc/host/sdhci-pci-gli.c
> > +++ b/drivers/mmc/host/sdhci-pci-gli.c
> > @@ -158,6 +158,13 @@
> > #define GLI_9767_VHS_REV_M 0x1
> > #define GLI_9767_VHS_REV_W 0x2
> >
> > +#define PCIE_GLI_9767_CFG 0x8A0
> > +#define PCIE_GLI_9767_CFG_LOW_PWR_OFF BIT(12)
> > +
> > +#define PCIE_GLI_9767_COMBO_MUX_CTL 0x8C8
> > +#define PCIE_GLI_9767_COMBO_MUX_CTL_RST_EN BIT(6)
> > +#define PCIE_GLI_9767_COMBO_MUX_CTL_WAIT_PERST_EN BIT(10)
> > +
> > #define PCIE_GLI_9767_PWR_MACRO_CTL 0x8D0
> > #define PCIE_GLI_9767_PWR_MACRO_CTL_LOW_VOLTAGE GENMASK(3, 0)
> > #define PCIE_GLI_9767_PWR_MACRO_CTL_LD0_LOW_OUTPUT_VOLTAGE GENMASK(15, 12)
> > @@ -175,6 +182,27 @@
> > #define PCIE_GLI_9767_SCR_CORE_PWR_D3_OFF BIT(21)
> > #define PCIE_GLI_9767_SCR_CFG_RST_DATA_LINK_DOWN BIT(30)
> >
> > +#define PCIE_GLI_9767_SDHC_CAP 0x91C
> > +#define PCIE_GLI_9767_SDHC_CAP_SDEI_RESULT BIT(5)
> > +
> > +#define PCIE_GLI_9767_SD_EXPRESS_CTL 0x940
> > +#define PCIE_GLI_9767_SD_EXPRESS_CTL_SDEI_EXE BIT(0)
> > +#define PCIE_GLI_9767_SD_EXPRESS_CTL_SD_EXPRESS_MODE BIT(1)
> > +
> > +#define PCIE_GLI_9767_SD_DATA_MULTI_CTL 0x944
> > +#define PCIE_GLI_9767_SD_DATA_MULTI_CTL_DISCONNECT_TIME GENMASK(23, 16)
> > +#define PCIE_GLI_9767_SD_DATA_MULTI_CTL_DISCONNECT_TIME_VALUE 0x64
> > +
> > +#define PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_REG2 0x950
> > +#define PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_REG2_SDEI_COMPLETE BIT(0)
> > +#define PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_REG2_SDEI_GEN_TIMER GENMASK(1, 0)
> > +
> > +#define PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_EN_REG2 0x954
> > +#define PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_EN_REG2_SDEI_COMPLETE_STATUS_EN GENMASK(1, 0)
> > +
> > +#define PCIE_GLI_9767_NORMAL_ERR_INT_SIGNAL_EN_REG2 0x958
> > +#define PCIE_GLI_9767_NORMAL_ERR_INT_SIGNAL_EN_REG2_SDEI_COMPLETE_SIGNAL_EN GENMASK(1, 0)
> > +
> > #define GLI_MAX_TUNING_LOOP 40
> >
> > /* Genesys Logic chipset */
> > @@ -774,6 +802,91 @@ static void sdhci_gl9767_reset(struct sdhci_host *host, u8 mask)
> > gli_set_9767(host);
> > }
> >
> > +static int gl9767_init_sd_express(struct mmc_host *mmc, struct mmc_ios *ios)
> > +{
> > + struct sdhci_host *host = mmc_priv(mmc);
> > + struct sdhci_pci_slot *slot = sdhci_priv(host);
> > + struct pci_dev *pdev;
> > + u32 value;
> > + int i;
> > +
> > + pdev = slot->chip->pdev;
> > +
> > + if (sdhci_check_ro(host)) {
>
> I think mmc->get_ro(mmc) would be fine here instead.
>
I will update it in Patch v2.
> > + mmc->ios.timing &= ~(MMC_TIMING_SD_EXP | MMC_TIMING_SD_EXP_1_2V);
> > + return 0;
> > + }
> > +
> > + pci_read_config_dword(pdev, PCIE_GLI_9767_VHS, &value);
> > + value &= ~GLI_9767_VHS_REV;
> > + value |= FIELD_PREP(GLI_9767_VHS_REV, GLI_9767_VHS_REV_W);
> > + pci_write_config_dword(pdev, PCIE_GLI_9767_VHS, value);
> > +
> > + pci_read_config_dword(pdev, PCIE_GLI_9767_COMBO_MUX_CTL, &value);
> > + value &= ~(PCIE_GLI_9767_COMBO_MUX_CTL_RST_EN | PCIE_GLI_9767_COMBO_MUX_CTL_WAIT_PERST_EN);
> > + pci_write_config_dword(pdev, PCIE_GLI_9767_COMBO_MUX_CTL, value);
> > +
> > + pci_read_config_dword(pdev, PCIE_GLI_9767_SD_DATA_MULTI_CTL, &value);
> > + value &= ~PCIE_GLI_9767_SD_DATA_MULTI_CTL_DISCONNECT_TIME;
> > + value |= FIELD_PREP(PCIE_GLI_9767_SD_DATA_MULTI_CTL_DISCONNECT_TIME,
> > + PCIE_GLI_9767_SD_DATA_MULTI_CTL_DISCONNECT_TIME_VALUE);
> > + pci_write_config_dword(pdev, PCIE_GLI_9767_SD_DATA_MULTI_CTL, value);
> > +
> > + pci_read_config_dword(pdev, PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_REG2, &value);
> > + value |= PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_REG2_SDEI_GEN_TIMER;
> > + pci_write_config_dword(pdev, PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_REG2, value);
> > +
> > + pci_read_config_dword(pdev, PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_EN_REG2, &value);
> > + value |= PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_EN_REG2_SDEI_COMPLETE_STATUS_EN;
> > + pci_write_config_dword(pdev, PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_EN_REG2, value);
> > +
> > + pci_read_config_dword(pdev, PCIE_GLI_9767_NORMAL_ERR_INT_SIGNAL_EN_REG2, &value);
> > + value |= PCIE_GLI_9767_NORMAL_ERR_INT_SIGNAL_EN_REG2_SDEI_COMPLETE_SIGNAL_EN;
> > + pci_write_config_dword(pdev, PCIE_GLI_9767_NORMAL_ERR_INT_SIGNAL_EN_REG2, value);
> > +
> > + pci_read_config_dword(pdev, PCIE_GLI_9767_CFG, &value);
> > + value |= PCIE_GLI_9767_CFG_LOW_PWR_OFF;
> > + pci_write_config_dword(pdev, PCIE_GLI_9767_CFG, value);
> > +
> > + value = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
> > + value &= ~(SDHCI_CLOCK_CARD_EN | SDHCI_CLOCK_PLL_EN);
> > + sdhci_writew(host, value, SDHCI_CLOCK_CONTROL);
> > +
> > + value = sdhci_readb(host, SDHCI_POWER_CONTROL);
> > + value |= ((SDHCI_POWER_180 | SDHCI_POWER_ON) << 4);
> > + sdhci_writeb(host, value, SDHCI_POWER_CONTROL);
> > +
> > + pci_read_config_dword(pdev, PCIE_GLI_9767_SD_EXPRESS_CTL, &value);
> > + value |= PCIE_GLI_9767_SD_EXPRESS_CTL_SDEI_EXE;
> > + pci_write_config_dword(pdev, PCIE_GLI_9767_SD_EXPRESS_CTL, value);
> > +
> > + for (i = 0; i < 10; i++) {
> > + mdelay(10);
>
> This should be msleep() or usleep_range()
>
I will update this in Patch v2.
> > + pci_read_config_dword(pdev, PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_REG2, &value);
> > + if (value & PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_REG2_SDEI_COMPLETE) {
> > + pci_write_config_dword(pdev, PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_REG2,
> > + value);
> > + break;
> > + }
> > + }
> > +
> > + pci_read_config_dword(pdev, PCIE_GLI_9767_SDHC_CAP, &value);
> > + if ((value & PCIE_GLI_9767_SDHC_CAP_SDEI_RESULT) == PCIE_GLI_9767_SDHC_CAP_SDEI_RESULT) {
> > + pci_read_config_dword(pdev, PCIE_GLI_9767_SD_EXPRESS_CTL, &value);
> > + value |= PCIE_GLI_9767_SD_EXPRESS_CTL_SD_EXPRESS_MODE;
> > + pci_write_config_dword(pdev, PCIE_GLI_9767_SD_EXPRESS_CTL, value);
> > + } else {
> > + mmc->ios.timing &= ~(MMC_TIMING_SD_EXP | MMC_TIMING_SD_EXP_1_2V);
> > + }
> > +
> > + pci_read_config_dword(pdev, PCIE_GLI_9767_VHS, &value);
> > + value &= ~GLI_9767_VHS_REV;
> > + value |= FIELD_PREP(GLI_9767_VHS_REV, GLI_9767_VHS_REV_R);
> > + pci_write_config_dword(pdev, PCIE_GLI_9767_VHS, value);
> > +
> > + return 0;
> > +}
> > +
> > static int gli_probe_slot_gl9750(struct sdhci_pci_slot *slot)
> > {
> > struct sdhci_host *host = slot->host;
> > @@ -806,6 +919,8 @@ static int gli_probe_slot_gl9767(struct sdhci_pci_slot *slot)
> > gl9767_hw_setting(slot);
> > gli_pcie_enable_msi(slot);
> > slot->host->mmc->caps2 |= MMC_CAP2_NO_SDIO;
> > + host->mmc->caps2 |= MMC_CAP2_SD_EXP;
> > + host->mmc_host_ops.init_sd_express = gl9767_init_sd_express;
> > sdhci_enable_v4_mode(host);
> >
> > return 0;
>
Thanks, Victor Shih
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2023-05-30 9:52 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-05-12 10:45 [PATCH V1 0/3] Add Genesys Logic GL9767 support Victor Shih
2023-05-12 10:45 ` [PATCH V1 1/3] mmc: sdhci-pci-gli: " Victor Shih
2023-05-15 0:01 ` Ben Chuang
2023-05-12 10:45 ` [PATCH V1 2/3] mmc: sdhci: Export sdhci_check_ro function symbol Victor Shih
2023-05-12 10:45 ` [PATCH V1 3/3] mmc: sdhci-pci-gli: Add support SD Express card for GL9767 Victor Shih
2023-05-15 0:14 ` Ben Chuang
2023-05-30 9:51 ` Victor Shih
2023-05-29 9:36 ` Adrian Hunter
2023-05-30 9:52 ` Victor Shih
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).