Commit f3a5b56c authored by Victor Shih's avatar Victor Shih Committed by Ulf Hansson
Browse files

mmc: sdhci-pci-gli: Add Genesys Logic GL9767 support



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: default avatarBen Chuang <ben.chuang@genesyslogic.com.tw>
Signed-off-by: default avatarVictor Shih <victor.shih@genesyslogic.com.tw>
Acked-by: default avatarAdrian Hunter <adrian.hunter@intel.com>
Link: https://lore.kernel.org/r/20230609071441.451464-2-victorshihgli@gmail.com


Signed-off-by: default avatarUlf Hansson <ulf.hansson@linaro.org>
parent f2764e1f
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -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)},
+160 −0
Original line number Diff line number Diff line
@@ -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,89 @@ static void gl9755_hw_setting(struct sdhci_pci_slot *slot)
	gl9755_wt_off(pdev);
}

static inline void gl9767_vhs_read(struct pci_dev *pdev)
{
	u32 vhs_enable;
	u32 vhs_value;

	pci_read_config_dword(pdev, PCIE_GLI_9767_VHS, &vhs_value);
	vhs_enable = FIELD_GET(GLI_9767_VHS_REV, vhs_value);

	if (vhs_enable == GLI_9767_VHS_REV_R)
		return;

	vhs_value &= ~GLI_9767_VHS_REV;
	vhs_value |= FIELD_PREP(GLI_9767_VHS_REV, GLI_9767_VHS_REV_R);

	pci_write_config_dword(pdev, PCIE_GLI_9767_VHS, vhs_value);
}

static inline void gl9767_vhs_write(struct pci_dev *pdev)
{
	u32 vhs_enable;
	u32 vhs_value;

	pci_read_config_dword(pdev, PCIE_GLI_9767_VHS, &vhs_value);
	vhs_enable = FIELD_GET(GLI_9767_VHS_REV, vhs_value);

	if (vhs_enable == GLI_9767_VHS_REV_W)
		return;

	vhs_value &= ~GLI_9767_VHS_REV;
	vhs_value |= FIELD_PREP(GLI_9767_VHS_REV, GLI_9767_VHS_REV_W);

	pci_write_config_dword(pdev, PCIE_GLI_9767_VHS, vhs_value);
}

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;

	gl9767_vhs_write(pdev);

	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);

	gl9767_vhs_read(pdev);
}

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 +826,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 +862,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 +1291,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
};
+2 −0
Original line number Diff line number Diff line
@@ -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 */