101acf691SAdam Lee /*
201acf691SAdam Lee  * Copyright (C) 2013 BayHub Technology Ltd.
301acf691SAdam Lee  *
401acf691SAdam Lee  * Authors: Peter Guo <peter.guo@bayhubtech.com>
501acf691SAdam Lee  *          Adam Lee <adam.lee@canonical.com>
601acf691SAdam Lee  *
701acf691SAdam Lee  * This software is licensed under the terms of the GNU General Public
801acf691SAdam Lee  * License version 2, as published by the Free Software Foundation, and
901acf691SAdam Lee  * may be copied, distributed, and modified under those terms.
1001acf691SAdam Lee  *
1101acf691SAdam Lee  * This program is distributed in the hope that it will be useful,
1201acf691SAdam Lee  * but WITHOUT ANY WARRANTY; without even the implied warranty of
1301acf691SAdam Lee  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1401acf691SAdam Lee  * GNU General Public License for more details.
1501acf691SAdam Lee  *
1601acf691SAdam Lee  */
1701acf691SAdam Lee 
1801acf691SAdam Lee #include <linux/pci.h>
1901acf691SAdam Lee 
2001acf691SAdam Lee #include "sdhci.h"
2101acf691SAdam Lee #include "sdhci-pci.h"
2201acf691SAdam Lee #include "sdhci-pci-o2micro.h"
2301acf691SAdam Lee 
24706adf6bSPeter Guo static void o2_pci_set_baseclk(struct sdhci_pci_chip *chip, u32 value)
25706adf6bSPeter Guo {
26706adf6bSPeter Guo 	u32 scratch_32;
27706adf6bSPeter Guo 	pci_read_config_dword(chip->pdev,
28706adf6bSPeter Guo 			      O2_SD_PLL_SETTING, &scratch_32);
29706adf6bSPeter Guo 
30706adf6bSPeter Guo 	scratch_32 &= 0x0000FFFF;
31706adf6bSPeter Guo 	scratch_32 |= value;
32706adf6bSPeter Guo 
33706adf6bSPeter Guo 	pci_write_config_dword(chip->pdev,
34706adf6bSPeter Guo 			       O2_SD_PLL_SETTING, scratch_32);
35706adf6bSPeter Guo }
36706adf6bSPeter Guo 
37706adf6bSPeter Guo static void o2_pci_led_enable(struct sdhci_pci_chip *chip)
38706adf6bSPeter Guo {
39706adf6bSPeter Guo 	int ret;
40706adf6bSPeter Guo 	u32 scratch_32;
41706adf6bSPeter Guo 
42706adf6bSPeter Guo 	/* Set led of SD host function enable */
43706adf6bSPeter Guo 	ret = pci_read_config_dword(chip->pdev,
44706adf6bSPeter Guo 				    O2_SD_FUNC_REG0, &scratch_32);
45706adf6bSPeter Guo 	if (ret)
46706adf6bSPeter Guo 		return;
47706adf6bSPeter Guo 
48706adf6bSPeter Guo 	scratch_32 &= ~O2_SD_FREG0_LEDOFF;
49706adf6bSPeter Guo 	pci_write_config_dword(chip->pdev,
50706adf6bSPeter Guo 			       O2_SD_FUNC_REG0, scratch_32);
51706adf6bSPeter Guo 
52706adf6bSPeter Guo 	ret = pci_read_config_dword(chip->pdev,
53706adf6bSPeter Guo 				    O2_SD_TEST_REG, &scratch_32);
54706adf6bSPeter Guo 	if (ret)
55706adf6bSPeter Guo 		return;
56706adf6bSPeter Guo 
57706adf6bSPeter Guo 	scratch_32 |= O2_SD_LED_ENABLE;
58706adf6bSPeter Guo 	pci_write_config_dword(chip->pdev,
59706adf6bSPeter Guo 			       O2_SD_TEST_REG, scratch_32);
60706adf6bSPeter Guo 
61706adf6bSPeter Guo }
62706adf6bSPeter Guo 
63f0cbd780SBen Hutchings static void sdhci_pci_o2_fujin2_pci_init(struct sdhci_pci_chip *chip)
6401acf691SAdam Lee {
6501acf691SAdam Lee 	u32 scratch_32;
6601acf691SAdam Lee 	int ret;
6701acf691SAdam Lee 	/* Improve write performance for SD3.0 */
6801acf691SAdam Lee 	ret = pci_read_config_dword(chip->pdev, O2_SD_DEV_CTRL, &scratch_32);
6901acf691SAdam Lee 	if (ret)
7001acf691SAdam Lee 		return;
7101acf691SAdam Lee 	scratch_32 &= ~((1 << 12) | (1 << 13) | (1 << 14));
7201acf691SAdam Lee 	pci_write_config_dword(chip->pdev, O2_SD_DEV_CTRL, scratch_32);
7301acf691SAdam Lee 
7401acf691SAdam Lee 	/* Enable Link abnormal reset generating Reset */
7501acf691SAdam Lee 	ret = pci_read_config_dword(chip->pdev, O2_SD_MISC_REG5, &scratch_32);
7601acf691SAdam Lee 	if (ret)
7701acf691SAdam Lee 		return;
7801acf691SAdam Lee 	scratch_32 &= ~((1 << 19) | (1 << 11));
7901acf691SAdam Lee 	scratch_32 |= (1 << 10);
8001acf691SAdam Lee 	pci_write_config_dword(chip->pdev, O2_SD_MISC_REG5, scratch_32);
8101acf691SAdam Lee 
8201acf691SAdam Lee 	/* set card power over current protection */
8301acf691SAdam Lee 	ret = pci_read_config_dword(chip->pdev, O2_SD_TEST_REG, &scratch_32);
8401acf691SAdam Lee 	if (ret)
8501acf691SAdam Lee 		return;
8601acf691SAdam Lee 	scratch_32 |= (1 << 4);
8701acf691SAdam Lee 	pci_write_config_dword(chip->pdev, O2_SD_TEST_REG, scratch_32);
8801acf691SAdam Lee 
8901acf691SAdam Lee 	/* adjust the output delay for SD mode */
9001acf691SAdam Lee 	pci_write_config_dword(chip->pdev, O2_SD_DELAY_CTRL, 0x00002492);
9101acf691SAdam Lee 
9201acf691SAdam Lee 	/* Set the output voltage setting of Aux 1.2v LDO */
9301acf691SAdam Lee 	ret = pci_read_config_dword(chip->pdev, O2_SD_LD0_CTRL, &scratch_32);
9401acf691SAdam Lee 	if (ret)
9501acf691SAdam Lee 		return;
9601acf691SAdam Lee 	scratch_32 &= ~(3 << 12);
9701acf691SAdam Lee 	pci_write_config_dword(chip->pdev, O2_SD_LD0_CTRL, scratch_32);
9801acf691SAdam Lee 
9901acf691SAdam Lee 	/* Set Max power supply capability of SD host */
10001acf691SAdam Lee 	ret = pci_read_config_dword(chip->pdev, O2_SD_CAP_REG0, &scratch_32);
10101acf691SAdam Lee 	if (ret)
10201acf691SAdam Lee 		return;
10301acf691SAdam Lee 	scratch_32 &= ~(0x01FE);
10401acf691SAdam Lee 	scratch_32 |= 0x00CC;
10501acf691SAdam Lee 	pci_write_config_dword(chip->pdev, O2_SD_CAP_REG0, scratch_32);
10601acf691SAdam Lee 	/* Set DLL Tuning Window */
10701acf691SAdam Lee 	ret = pci_read_config_dword(chip->pdev,
10801acf691SAdam Lee 				    O2_SD_TUNING_CTRL, &scratch_32);
10901acf691SAdam Lee 	if (ret)
11001acf691SAdam Lee 		return;
11101acf691SAdam Lee 	scratch_32 &= ~(0x000000FF);
11201acf691SAdam Lee 	scratch_32 |= 0x00000066;
11301acf691SAdam Lee 	pci_write_config_dword(chip->pdev, O2_SD_TUNING_CTRL, scratch_32);
11401acf691SAdam Lee 
11501acf691SAdam Lee 	/* Set UHS2 T_EIDLE */
11601acf691SAdam Lee 	ret = pci_read_config_dword(chip->pdev,
11701acf691SAdam Lee 				    O2_SD_UHS2_L1_CTRL, &scratch_32);
11801acf691SAdam Lee 	if (ret)
11901acf691SAdam Lee 		return;
12001acf691SAdam Lee 	scratch_32 &= ~(0x000000FC);
12101acf691SAdam Lee 	scratch_32 |= 0x00000084;
12201acf691SAdam Lee 	pci_write_config_dword(chip->pdev, O2_SD_UHS2_L1_CTRL, scratch_32);
12301acf691SAdam Lee 
12401acf691SAdam Lee 	/* Set UHS2 Termination */
12501acf691SAdam Lee 	ret = pci_read_config_dword(chip->pdev, O2_SD_FUNC_REG3, &scratch_32);
12601acf691SAdam Lee 	if (ret)
12701acf691SAdam Lee 		return;
12801acf691SAdam Lee 	scratch_32 &= ~((1 << 21) | (1 << 30));
12901acf691SAdam Lee 
13001acf691SAdam Lee 	pci_write_config_dword(chip->pdev, O2_SD_FUNC_REG3, scratch_32);
13101acf691SAdam Lee 
13201acf691SAdam Lee 	/* Set L1 Entrance Timer */
13301acf691SAdam Lee 	ret = pci_read_config_dword(chip->pdev, O2_SD_CAPS, &scratch_32);
13401acf691SAdam Lee 	if (ret)
13501acf691SAdam Lee 		return;
13601acf691SAdam Lee 	scratch_32 &= ~(0xf0000000);
13701acf691SAdam Lee 	scratch_32 |= 0x30000000;
13801acf691SAdam Lee 	pci_write_config_dword(chip->pdev, O2_SD_CAPS, scratch_32);
13901acf691SAdam Lee 
14001acf691SAdam Lee 	ret = pci_read_config_dword(chip->pdev,
14101acf691SAdam Lee 				    O2_SD_MISC_CTRL4, &scratch_32);
14201acf691SAdam Lee 	if (ret)
14301acf691SAdam Lee 		return;
14401acf691SAdam Lee 	scratch_32 &= ~(0x000f0000);
14501acf691SAdam Lee 	scratch_32 |= 0x00080000;
14601acf691SAdam Lee 	pci_write_config_dword(chip->pdev, O2_SD_MISC_CTRL4, scratch_32);
14701acf691SAdam Lee }
14801acf691SAdam Lee 
14901acf691SAdam Lee int sdhci_pci_o2_probe_slot(struct sdhci_pci_slot *slot)
15001acf691SAdam Lee {
15101acf691SAdam Lee 	struct sdhci_pci_chip *chip;
15201acf691SAdam Lee 	struct sdhci_host *host;
15301acf691SAdam Lee 	u32 reg;
15401acf691SAdam Lee 
15501acf691SAdam Lee 	chip = slot->chip;
15601acf691SAdam Lee 	host = slot->host;
15701acf691SAdam Lee 	switch (chip->pdev->device) {
15801acf691SAdam Lee 	case PCI_DEVICE_ID_O2_SDS0:
15901acf691SAdam Lee 	case PCI_DEVICE_ID_O2_SEABIRD0:
16001acf691SAdam Lee 	case PCI_DEVICE_ID_O2_SEABIRD1:
16101acf691SAdam Lee 	case PCI_DEVICE_ID_O2_SDS1:
16201acf691SAdam Lee 	case PCI_DEVICE_ID_O2_FUJIN2:
16301acf691SAdam Lee 		reg = sdhci_readl(host, O2_SD_VENDOR_SETTING);
16401acf691SAdam Lee 		if (reg & 0x1)
16501acf691SAdam Lee 			host->quirks |= SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12;
16601acf691SAdam Lee 
16701acf691SAdam Lee 		if (chip->pdev->device != PCI_DEVICE_ID_O2_FUJIN2)
16801acf691SAdam Lee 			break;
16901acf691SAdam Lee 		/* set dll watch dog timer */
17001acf691SAdam Lee 		reg = sdhci_readl(host, O2_SD_VENDOR_SETTING2);
17101acf691SAdam Lee 		reg |= (1 << 12);
17201acf691SAdam Lee 		sdhci_writel(host, reg, O2_SD_VENDOR_SETTING2);
17301acf691SAdam Lee 
17401acf691SAdam Lee 		break;
17501acf691SAdam Lee 	default:
17601acf691SAdam Lee 		break;
17701acf691SAdam Lee 	}
17801acf691SAdam Lee 
17901acf691SAdam Lee 	return 0;
18001acf691SAdam Lee }
18101acf691SAdam Lee 
18201acf691SAdam Lee int sdhci_pci_o2_probe(struct sdhci_pci_chip *chip)
18301acf691SAdam Lee {
18401acf691SAdam Lee 	int ret;
18501acf691SAdam Lee 	u8 scratch;
18601acf691SAdam Lee 	u32 scratch_32;
18701acf691SAdam Lee 
18801acf691SAdam Lee 	switch (chip->pdev->device) {
18901acf691SAdam Lee 	case PCI_DEVICE_ID_O2_8220:
19001acf691SAdam Lee 	case PCI_DEVICE_ID_O2_8221:
19101acf691SAdam Lee 	case PCI_DEVICE_ID_O2_8320:
19201acf691SAdam Lee 	case PCI_DEVICE_ID_O2_8321:
19301acf691SAdam Lee 		/* This extra setup is required due to broken ADMA. */
19401acf691SAdam Lee 		ret = pci_read_config_byte(chip->pdev,
19501acf691SAdam Lee 				O2_SD_LOCK_WP, &scratch);
19601acf691SAdam Lee 		if (ret)
19701acf691SAdam Lee 			return ret;
19801acf691SAdam Lee 		scratch &= 0x7f;
19901acf691SAdam Lee 		pci_write_config_byte(chip->pdev, O2_SD_LOCK_WP, scratch);
20001acf691SAdam Lee 
20101acf691SAdam Lee 		/* Set Multi 3 to VCC3V# */
20201acf691SAdam Lee 		pci_write_config_byte(chip->pdev, O2_SD_MULTI_VCC3V, 0x08);
20301acf691SAdam Lee 
20401acf691SAdam Lee 		/* Disable CLK_REQ# support after media DET */
20501acf691SAdam Lee 		ret = pci_read_config_byte(chip->pdev,
20601acf691SAdam Lee 				O2_SD_CLKREQ, &scratch);
20701acf691SAdam Lee 		if (ret)
20801acf691SAdam Lee 			return ret;
20901acf691SAdam Lee 		scratch |= 0x20;
21001acf691SAdam Lee 		pci_write_config_byte(chip->pdev, O2_SD_CLKREQ, scratch);
21101acf691SAdam Lee 
21201acf691SAdam Lee 		/* Choose capabilities, enable SDMA.  We have to write 0x01
21301acf691SAdam Lee 		 * to the capabilities register first to unlock it.
21401acf691SAdam Lee 		 */
21501acf691SAdam Lee 		ret = pci_read_config_byte(chip->pdev, O2_SD_CAPS, &scratch);
21601acf691SAdam Lee 		if (ret)
21701acf691SAdam Lee 			return ret;
21801acf691SAdam Lee 		scratch |= 0x01;
21901acf691SAdam Lee 		pci_write_config_byte(chip->pdev, O2_SD_CAPS, scratch);
22001acf691SAdam Lee 		pci_write_config_byte(chip->pdev, O2_SD_CAPS, 0x73);
22101acf691SAdam Lee 
22201acf691SAdam Lee 		/* Disable ADMA1/2 */
22301acf691SAdam Lee 		pci_write_config_byte(chip->pdev, O2_SD_ADMA1, 0x39);
22401acf691SAdam Lee 		pci_write_config_byte(chip->pdev, O2_SD_ADMA2, 0x08);
22501acf691SAdam Lee 
22601acf691SAdam Lee 		/* Disable the infinite transfer mode */
22701acf691SAdam Lee 		ret = pci_read_config_byte(chip->pdev,
22801acf691SAdam Lee 				O2_SD_INF_MOD, &scratch);
22901acf691SAdam Lee 		if (ret)
23001acf691SAdam Lee 			return ret;
23101acf691SAdam Lee 		scratch |= 0x08;
23201acf691SAdam Lee 		pci_write_config_byte(chip->pdev, O2_SD_INF_MOD, scratch);
23301acf691SAdam Lee 
23401acf691SAdam Lee 		/* Lock WP */
23501acf691SAdam Lee 		ret = pci_read_config_byte(chip->pdev,
23601acf691SAdam Lee 				O2_SD_LOCK_WP, &scratch);
23701acf691SAdam Lee 		if (ret)
23801acf691SAdam Lee 			return ret;
23901acf691SAdam Lee 		scratch |= 0x80;
24001acf691SAdam Lee 		pci_write_config_byte(chip->pdev, O2_SD_LOCK_WP, scratch);
24101acf691SAdam Lee 		break;
24201acf691SAdam Lee 	case PCI_DEVICE_ID_O2_SDS0:
24301acf691SAdam Lee 	case PCI_DEVICE_ID_O2_SDS1:
24401acf691SAdam Lee 	case PCI_DEVICE_ID_O2_FUJIN2:
24501acf691SAdam Lee 		/* UnLock WP */
24601acf691SAdam Lee 		ret = pci_read_config_byte(chip->pdev,
24701acf691SAdam Lee 				O2_SD_LOCK_WP, &scratch);
24801acf691SAdam Lee 		if (ret)
24901acf691SAdam Lee 			return ret;
25001acf691SAdam Lee 
25101acf691SAdam Lee 		scratch &= 0x7f;
25201acf691SAdam Lee 		pci_write_config_byte(chip->pdev, O2_SD_LOCK_WP, scratch);
25301acf691SAdam Lee 
254706adf6bSPeter Guo 		/* DevId=8520 subId= 0x11 or 0x12  Type Chip support */
255706adf6bSPeter Guo 		if (chip->pdev->device == PCI_DEVICE_ID_O2_FUJIN2) {
256706adf6bSPeter Guo 			ret = pci_read_config_dword(chip->pdev,
257706adf6bSPeter Guo 						    O2_SD_FUNC_REG0,
258706adf6bSPeter Guo 						    &scratch_32);
259706adf6bSPeter Guo 			scratch_32 = ((scratch_32 & 0xFF000000) >> 24);
260706adf6bSPeter Guo 
261706adf6bSPeter Guo 			/* Check Whether subId is 0x11 or 0x12 */
262706adf6bSPeter Guo 			if ((scratch_32 == 0x11) || (scratch_32 == 0x12)) {
263706adf6bSPeter Guo 				scratch_32 = 0x2c280000;
264706adf6bSPeter Guo 
265706adf6bSPeter Guo 				/* Set Base Clock to 208MZ */
266706adf6bSPeter Guo 				o2_pci_set_baseclk(chip, scratch_32);
267706adf6bSPeter Guo 				ret = pci_read_config_dword(chip->pdev,
268706adf6bSPeter Guo 							    O2_SD_FUNC_REG4,
269706adf6bSPeter Guo 							    &scratch_32);
270706adf6bSPeter Guo 
271706adf6bSPeter Guo 				/* Enable Base Clk setting change */
272706adf6bSPeter Guo 				scratch_32 |= O2_SD_FREG4_ENABLE_CLK_SET;
273706adf6bSPeter Guo 				pci_write_config_dword(chip->pdev,
274706adf6bSPeter Guo 						       O2_SD_FUNC_REG4,
275706adf6bSPeter Guo 						       scratch_32);
276706adf6bSPeter Guo 
277706adf6bSPeter Guo 				/* Set Tuning Window to 4 */
278706adf6bSPeter Guo 				pci_write_config_byte(chip->pdev,
279706adf6bSPeter Guo 						      O2_SD_TUNING_CTRL, 0x44);
280706adf6bSPeter Guo 
281706adf6bSPeter Guo 				break;
282706adf6bSPeter Guo 			}
283706adf6bSPeter Guo 		}
284706adf6bSPeter Guo 
285706adf6bSPeter Guo 		/* Enable 8520 led function */
286706adf6bSPeter Guo 		o2_pci_led_enable(chip);
287706adf6bSPeter Guo 
28801acf691SAdam Lee 		/* Set timeout CLK */
28901acf691SAdam Lee 		ret = pci_read_config_dword(chip->pdev,
29001acf691SAdam Lee 					    O2_SD_CLK_SETTING, &scratch_32);
29101acf691SAdam Lee 		if (ret)
29201acf691SAdam Lee 			return ret;
29301acf691SAdam Lee 
29401acf691SAdam Lee 		scratch_32 &= ~(0xFF00);
29501acf691SAdam Lee 		scratch_32 |= 0x07E0C800;
29601acf691SAdam Lee 		pci_write_config_dword(chip->pdev,
29701acf691SAdam Lee 				       O2_SD_CLK_SETTING, scratch_32);
29801acf691SAdam Lee 
29901acf691SAdam Lee 		ret = pci_read_config_dword(chip->pdev,
30001acf691SAdam Lee 					    O2_SD_CLKREQ, &scratch_32);
30101acf691SAdam Lee 		if (ret)
30201acf691SAdam Lee 			return ret;
30301acf691SAdam Lee 		scratch_32 |= 0x3;
30401acf691SAdam Lee 		pci_write_config_dword(chip->pdev, O2_SD_CLKREQ, scratch_32);
30501acf691SAdam Lee 
30601acf691SAdam Lee 		ret = pci_read_config_dword(chip->pdev,
30701acf691SAdam Lee 					    O2_SD_PLL_SETTING, &scratch_32);
30801acf691SAdam Lee 		if (ret)
30901acf691SAdam Lee 			return ret;
31001acf691SAdam Lee 
31101acf691SAdam Lee 		scratch_32 &= ~(0x1F3F070E);
31201acf691SAdam Lee 		scratch_32 |= 0x18270106;
31301acf691SAdam Lee 		pci_write_config_dword(chip->pdev,
31401acf691SAdam Lee 				       O2_SD_PLL_SETTING, scratch_32);
31501acf691SAdam Lee 
31601acf691SAdam Lee 		/* Disable UHS1 funciton */
31701acf691SAdam Lee 		ret = pci_read_config_dword(chip->pdev,
31801acf691SAdam Lee 					    O2_SD_CAP_REG2, &scratch_32);
31901acf691SAdam Lee 		if (ret)
32001acf691SAdam Lee 			return ret;
32101acf691SAdam Lee 		scratch_32 &= ~(0xE0);
32201acf691SAdam Lee 		pci_write_config_dword(chip->pdev,
32301acf691SAdam Lee 				       O2_SD_CAP_REG2, scratch_32);
32401acf691SAdam Lee 
32501acf691SAdam Lee 		if (chip->pdev->device == PCI_DEVICE_ID_O2_FUJIN2)
32601acf691SAdam Lee 			sdhci_pci_o2_fujin2_pci_init(chip);
32701acf691SAdam Lee 
32801acf691SAdam Lee 		/* Lock WP */
32901acf691SAdam Lee 		ret = pci_read_config_byte(chip->pdev,
33001acf691SAdam Lee 					   O2_SD_LOCK_WP, &scratch);
33101acf691SAdam Lee 		if (ret)
33201acf691SAdam Lee 			return ret;
33301acf691SAdam Lee 		scratch |= 0x80;
33401acf691SAdam Lee 		pci_write_config_byte(chip->pdev, O2_SD_LOCK_WP, scratch);
33501acf691SAdam Lee 		break;
33601acf691SAdam Lee 	case PCI_DEVICE_ID_O2_SEABIRD0:
33701acf691SAdam Lee 	case PCI_DEVICE_ID_O2_SEABIRD1:
33801acf691SAdam Lee 		/* UnLock WP */
33901acf691SAdam Lee 		ret = pci_read_config_byte(chip->pdev,
34001acf691SAdam Lee 				O2_SD_LOCK_WP, &scratch);
34101acf691SAdam Lee 		if (ret)
34201acf691SAdam Lee 			return ret;
34301acf691SAdam Lee 
34401acf691SAdam Lee 		scratch &= 0x7f;
34501acf691SAdam Lee 		pci_write_config_byte(chip->pdev, O2_SD_LOCK_WP, scratch);
34601acf691SAdam Lee 
34701acf691SAdam Lee 		ret = pci_read_config_dword(chip->pdev,
348706adf6bSPeter Guo 					    O2_SD_PLL_SETTING, &scratch_32);
34901acf691SAdam Lee 
35001acf691SAdam Lee 		if ((scratch_32 & 0xff000000) == 0x01000000) {
35101acf691SAdam Lee 			scratch_32 &= 0x0000FFFF;
35201acf691SAdam Lee 			scratch_32 |= 0x1F340000;
35301acf691SAdam Lee 
35401acf691SAdam Lee 			pci_write_config_dword(chip->pdev,
35501acf691SAdam Lee 					       O2_SD_PLL_SETTING, scratch_32);
35601acf691SAdam Lee 		} else {
35701acf691SAdam Lee 			scratch_32 &= 0x0000FFFF;
35801acf691SAdam Lee 			scratch_32 |= 0x2c280000;
35901acf691SAdam Lee 
36001acf691SAdam Lee 			pci_write_config_dword(chip->pdev,
36101acf691SAdam Lee 					       O2_SD_PLL_SETTING, scratch_32);
36201acf691SAdam Lee 
36301acf691SAdam Lee 			ret = pci_read_config_dword(chip->pdev,
36401acf691SAdam Lee 						    O2_SD_FUNC_REG4,
36501acf691SAdam Lee 						    &scratch_32);
36601acf691SAdam Lee 			scratch_32 |= (1 << 22);
36701acf691SAdam Lee 			pci_write_config_dword(chip->pdev,
36801acf691SAdam Lee 					       O2_SD_FUNC_REG4, scratch_32);
36901acf691SAdam Lee 		}
37001acf691SAdam Lee 
371706adf6bSPeter Guo 		/* Set Tuning Windows to 5 */
372706adf6bSPeter Guo 		pci_write_config_byte(chip->pdev,
373706adf6bSPeter Guo 				O2_SD_TUNING_CTRL, 0x55);
37401acf691SAdam Lee 		/* Lock WP */
37501acf691SAdam Lee 		ret = pci_read_config_byte(chip->pdev,
37601acf691SAdam Lee 					   O2_SD_LOCK_WP, &scratch);
37701acf691SAdam Lee 		if (ret)
37801acf691SAdam Lee 			return ret;
37901acf691SAdam Lee 		scratch |= 0x80;
38001acf691SAdam Lee 		pci_write_config_byte(chip->pdev, O2_SD_LOCK_WP, scratch);
38101acf691SAdam Lee 		break;
38201acf691SAdam Lee 	}
38301acf691SAdam Lee 
38401acf691SAdam Lee 	return 0;
38501acf691SAdam Lee }
38601acf691SAdam Lee 
38701acf691SAdam Lee int sdhci_pci_o2_resume(struct sdhci_pci_chip *chip)
38801acf691SAdam Lee {
38901acf691SAdam Lee 	sdhci_pci_o2_probe(chip);
39001acf691SAdam Lee 	return 0;
39101acf691SAdam Lee }
392