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>
657322d54Sernest.zhang  *          Ernest Zhang <ernest.zhang@bayhubtech.com>
701acf691SAdam Lee  *
801acf691SAdam Lee  * This software is licensed under the terms of the GNU General Public
901acf691SAdam Lee  * License version 2, as published by the Free Software Foundation, and
1001acf691SAdam Lee  * may be copied, distributed, and modified under those terms.
1101acf691SAdam Lee  *
1201acf691SAdam Lee  * This program is distributed in the hope that it will be useful,
1301acf691SAdam Lee  * but WITHOUT ANY WARRANTY; without even the implied warranty of
1401acf691SAdam Lee  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1501acf691SAdam Lee  * GNU General Public License for more details.
1601acf691SAdam Lee  *
1701acf691SAdam Lee  */
1801acf691SAdam Lee 
1901acf691SAdam Lee #include <linux/pci.h>
2001acf691SAdam Lee 
2101acf691SAdam Lee #include "sdhci.h"
2201acf691SAdam Lee #include "sdhci-pci.h"
23361eeda0SAdrian Hunter 
24361eeda0SAdrian Hunter /*
25361eeda0SAdrian Hunter  * O2Micro device registers
26361eeda0SAdrian Hunter  */
27361eeda0SAdrian Hunter 
28361eeda0SAdrian Hunter #define O2_SD_MISC_REG5		0x64
29361eeda0SAdrian Hunter #define O2_SD_LD0_CTRL		0x68
30361eeda0SAdrian Hunter #define O2_SD_DEV_CTRL		0x88
31361eeda0SAdrian Hunter #define O2_SD_LOCK_WP		0xD3
32361eeda0SAdrian Hunter #define O2_SD_TEST_REG		0xD4
33361eeda0SAdrian Hunter #define O2_SD_FUNC_REG0		0xDC
34361eeda0SAdrian Hunter #define O2_SD_MULTI_VCC3V	0xEE
35361eeda0SAdrian Hunter #define O2_SD_CLKREQ		0xEC
36361eeda0SAdrian Hunter #define O2_SD_CAPS		0xE0
37361eeda0SAdrian Hunter #define O2_SD_ADMA1		0xE2
38361eeda0SAdrian Hunter #define O2_SD_ADMA2		0xE7
39361eeda0SAdrian Hunter #define O2_SD_INF_MOD		0xF1
40361eeda0SAdrian Hunter #define O2_SD_MISC_CTRL4	0xFC
41361eeda0SAdrian Hunter #define O2_SD_TUNING_CTRL	0x300
42361eeda0SAdrian Hunter #define O2_SD_PLL_SETTING	0x304
4357322d54Sernest.zhang #define O2_SD_MISC_SETTING	0x308
44361eeda0SAdrian Hunter #define O2_SD_CLK_SETTING	0x328
45361eeda0SAdrian Hunter #define O2_SD_CAP_REG2		0x330
46361eeda0SAdrian Hunter #define O2_SD_CAP_REG0		0x334
47361eeda0SAdrian Hunter #define O2_SD_UHS1_CAP_SETTING	0x33C
48361eeda0SAdrian Hunter #define O2_SD_DELAY_CTRL	0x350
49361eeda0SAdrian Hunter #define O2_SD_UHS2_L1_CTRL	0x35C
50361eeda0SAdrian Hunter #define O2_SD_FUNC_REG3		0x3E0
51361eeda0SAdrian Hunter #define O2_SD_FUNC_REG4		0x3E4
52361eeda0SAdrian Hunter #define O2_SD_LED_ENABLE	BIT(6)
53361eeda0SAdrian Hunter #define O2_SD_FREG0_LEDOFF	BIT(13)
54361eeda0SAdrian Hunter #define O2_SD_FREG4_ENABLE_CLK_SET	BIT(22)
55361eeda0SAdrian Hunter 
56361eeda0SAdrian Hunter #define O2_SD_VENDOR_SETTING	0x110
57361eeda0SAdrian Hunter #define O2_SD_VENDOR_SETTING2	0x1C8
5801acf691SAdam Lee 
59706adf6bSPeter Guo static void o2_pci_set_baseclk(struct sdhci_pci_chip *chip, u32 value)
60706adf6bSPeter Guo {
61706adf6bSPeter Guo 	u32 scratch_32;
62706adf6bSPeter Guo 	pci_read_config_dword(chip->pdev,
63706adf6bSPeter Guo 			      O2_SD_PLL_SETTING, &scratch_32);
64706adf6bSPeter Guo 
65706adf6bSPeter Guo 	scratch_32 &= 0x0000FFFF;
66706adf6bSPeter Guo 	scratch_32 |= value;
67706adf6bSPeter Guo 
68706adf6bSPeter Guo 	pci_write_config_dword(chip->pdev,
69706adf6bSPeter Guo 			       O2_SD_PLL_SETTING, scratch_32);
70706adf6bSPeter Guo }
71706adf6bSPeter Guo 
72706adf6bSPeter Guo static void o2_pci_led_enable(struct sdhci_pci_chip *chip)
73706adf6bSPeter Guo {
74706adf6bSPeter Guo 	int ret;
75706adf6bSPeter Guo 	u32 scratch_32;
76706adf6bSPeter Guo 
77706adf6bSPeter Guo 	/* Set led of SD host function enable */
78706adf6bSPeter Guo 	ret = pci_read_config_dword(chip->pdev,
79706adf6bSPeter Guo 				    O2_SD_FUNC_REG0, &scratch_32);
80706adf6bSPeter Guo 	if (ret)
81706adf6bSPeter Guo 		return;
82706adf6bSPeter Guo 
83706adf6bSPeter Guo 	scratch_32 &= ~O2_SD_FREG0_LEDOFF;
84706adf6bSPeter Guo 	pci_write_config_dword(chip->pdev,
85706adf6bSPeter Guo 			       O2_SD_FUNC_REG0, scratch_32);
86706adf6bSPeter Guo 
87706adf6bSPeter Guo 	ret = pci_read_config_dword(chip->pdev,
88706adf6bSPeter Guo 				    O2_SD_TEST_REG, &scratch_32);
89706adf6bSPeter Guo 	if (ret)
90706adf6bSPeter Guo 		return;
91706adf6bSPeter Guo 
92706adf6bSPeter Guo 	scratch_32 |= O2_SD_LED_ENABLE;
93706adf6bSPeter Guo 	pci_write_config_dword(chip->pdev,
94706adf6bSPeter Guo 			       O2_SD_TEST_REG, scratch_32);
95706adf6bSPeter Guo 
96706adf6bSPeter Guo }
97706adf6bSPeter Guo 
98f0cbd780SBen Hutchings static void sdhci_pci_o2_fujin2_pci_init(struct sdhci_pci_chip *chip)
9901acf691SAdam Lee {
10001acf691SAdam Lee 	u32 scratch_32;
10101acf691SAdam Lee 	int ret;
10201acf691SAdam Lee 	/* Improve write performance for SD3.0 */
10301acf691SAdam Lee 	ret = pci_read_config_dword(chip->pdev, O2_SD_DEV_CTRL, &scratch_32);
10401acf691SAdam Lee 	if (ret)
10501acf691SAdam Lee 		return;
10601acf691SAdam Lee 	scratch_32 &= ~((1 << 12) | (1 << 13) | (1 << 14));
10701acf691SAdam Lee 	pci_write_config_dword(chip->pdev, O2_SD_DEV_CTRL, scratch_32);
10801acf691SAdam Lee 
10901acf691SAdam Lee 	/* Enable Link abnormal reset generating Reset */
11001acf691SAdam Lee 	ret = pci_read_config_dword(chip->pdev, O2_SD_MISC_REG5, &scratch_32);
11101acf691SAdam Lee 	if (ret)
11201acf691SAdam Lee 		return;
11301acf691SAdam Lee 	scratch_32 &= ~((1 << 19) | (1 << 11));
11401acf691SAdam Lee 	scratch_32 |= (1 << 10);
11501acf691SAdam Lee 	pci_write_config_dword(chip->pdev, O2_SD_MISC_REG5, scratch_32);
11601acf691SAdam Lee 
11701acf691SAdam Lee 	/* set card power over current protection */
11801acf691SAdam Lee 	ret = pci_read_config_dword(chip->pdev, O2_SD_TEST_REG, &scratch_32);
11901acf691SAdam Lee 	if (ret)
12001acf691SAdam Lee 		return;
12101acf691SAdam Lee 	scratch_32 |= (1 << 4);
12201acf691SAdam Lee 	pci_write_config_dword(chip->pdev, O2_SD_TEST_REG, scratch_32);
12301acf691SAdam Lee 
12401acf691SAdam Lee 	/* adjust the output delay for SD mode */
12501acf691SAdam Lee 	pci_write_config_dword(chip->pdev, O2_SD_DELAY_CTRL, 0x00002492);
12601acf691SAdam Lee 
12701acf691SAdam Lee 	/* Set the output voltage setting of Aux 1.2v LDO */
12801acf691SAdam Lee 	ret = pci_read_config_dword(chip->pdev, O2_SD_LD0_CTRL, &scratch_32);
12901acf691SAdam Lee 	if (ret)
13001acf691SAdam Lee 		return;
13101acf691SAdam Lee 	scratch_32 &= ~(3 << 12);
13201acf691SAdam Lee 	pci_write_config_dword(chip->pdev, O2_SD_LD0_CTRL, scratch_32);
13301acf691SAdam Lee 
13401acf691SAdam Lee 	/* Set Max power supply capability of SD host */
13501acf691SAdam Lee 	ret = pci_read_config_dword(chip->pdev, O2_SD_CAP_REG0, &scratch_32);
13601acf691SAdam Lee 	if (ret)
13701acf691SAdam Lee 		return;
13801acf691SAdam Lee 	scratch_32 &= ~(0x01FE);
13901acf691SAdam Lee 	scratch_32 |= 0x00CC;
14001acf691SAdam Lee 	pci_write_config_dword(chip->pdev, O2_SD_CAP_REG0, scratch_32);
14101acf691SAdam Lee 	/* Set DLL Tuning Window */
14201acf691SAdam Lee 	ret = pci_read_config_dword(chip->pdev,
14301acf691SAdam Lee 				    O2_SD_TUNING_CTRL, &scratch_32);
14401acf691SAdam Lee 	if (ret)
14501acf691SAdam Lee 		return;
14601acf691SAdam Lee 	scratch_32 &= ~(0x000000FF);
14701acf691SAdam Lee 	scratch_32 |= 0x00000066;
14801acf691SAdam Lee 	pci_write_config_dword(chip->pdev, O2_SD_TUNING_CTRL, scratch_32);
14901acf691SAdam Lee 
15001acf691SAdam Lee 	/* Set UHS2 T_EIDLE */
15101acf691SAdam Lee 	ret = pci_read_config_dword(chip->pdev,
15201acf691SAdam Lee 				    O2_SD_UHS2_L1_CTRL, &scratch_32);
15301acf691SAdam Lee 	if (ret)
15401acf691SAdam Lee 		return;
15501acf691SAdam Lee 	scratch_32 &= ~(0x000000FC);
15601acf691SAdam Lee 	scratch_32 |= 0x00000084;
15701acf691SAdam Lee 	pci_write_config_dword(chip->pdev, O2_SD_UHS2_L1_CTRL, scratch_32);
15801acf691SAdam Lee 
15901acf691SAdam Lee 	/* Set UHS2 Termination */
16001acf691SAdam Lee 	ret = pci_read_config_dword(chip->pdev, O2_SD_FUNC_REG3, &scratch_32);
16101acf691SAdam Lee 	if (ret)
16201acf691SAdam Lee 		return;
16301acf691SAdam Lee 	scratch_32 &= ~((1 << 21) | (1 << 30));
16401acf691SAdam Lee 
16501acf691SAdam Lee 	pci_write_config_dword(chip->pdev, O2_SD_FUNC_REG3, scratch_32);
16601acf691SAdam Lee 
16701acf691SAdam Lee 	/* Set L1 Entrance Timer */
16801acf691SAdam Lee 	ret = pci_read_config_dword(chip->pdev, O2_SD_CAPS, &scratch_32);
16901acf691SAdam Lee 	if (ret)
17001acf691SAdam Lee 		return;
17101acf691SAdam Lee 	scratch_32 &= ~(0xf0000000);
17201acf691SAdam Lee 	scratch_32 |= 0x30000000;
17301acf691SAdam Lee 	pci_write_config_dword(chip->pdev, O2_SD_CAPS, scratch_32);
17401acf691SAdam Lee 
17501acf691SAdam Lee 	ret = pci_read_config_dword(chip->pdev,
17601acf691SAdam Lee 				    O2_SD_MISC_CTRL4, &scratch_32);
17701acf691SAdam Lee 	if (ret)
17801acf691SAdam Lee 		return;
17901acf691SAdam Lee 	scratch_32 &= ~(0x000f0000);
18001acf691SAdam Lee 	scratch_32 |= 0x00080000;
18101acf691SAdam Lee 	pci_write_config_dword(chip->pdev, O2_SD_MISC_CTRL4, scratch_32);
18201acf691SAdam Lee }
18301acf691SAdam Lee 
18401acf691SAdam Lee int sdhci_pci_o2_probe_slot(struct sdhci_pci_slot *slot)
18501acf691SAdam Lee {
18601acf691SAdam Lee 	struct sdhci_pci_chip *chip;
18701acf691SAdam Lee 	struct sdhci_host *host;
18801acf691SAdam Lee 	u32 reg;
18957322d54Sernest.zhang 	int ret;
19001acf691SAdam Lee 
19101acf691SAdam Lee 	chip = slot->chip;
19201acf691SAdam Lee 	host = slot->host;
19301acf691SAdam Lee 	switch (chip->pdev->device) {
19401acf691SAdam Lee 	case PCI_DEVICE_ID_O2_SDS0:
19501acf691SAdam Lee 	case PCI_DEVICE_ID_O2_SEABIRD0:
19601acf691SAdam Lee 	case PCI_DEVICE_ID_O2_SEABIRD1:
19701acf691SAdam Lee 	case PCI_DEVICE_ID_O2_SDS1:
19801acf691SAdam Lee 	case PCI_DEVICE_ID_O2_FUJIN2:
19901acf691SAdam Lee 		reg = sdhci_readl(host, O2_SD_VENDOR_SETTING);
20001acf691SAdam Lee 		if (reg & 0x1)
20101acf691SAdam Lee 			host->quirks |= SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12;
20201acf691SAdam Lee 
20357322d54Sernest.zhang 		if (chip->pdev->device == PCI_DEVICE_ID_O2_SEABIRD0) {
20457322d54Sernest.zhang 			ret = pci_read_config_dword(chip->pdev,
20557322d54Sernest.zhang 						    O2_SD_MISC_SETTING, &reg);
20657322d54Sernest.zhang 			if (ret)
20757322d54Sernest.zhang 				return -EIO;
20857322d54Sernest.zhang 			if (reg & (1 << 4)) {
20957322d54Sernest.zhang 				pr_info("%s: emmc 1.8v flag is set, force 1.8v signaling voltage\n",
21057322d54Sernest.zhang 					mmc_hostname(host->mmc));
21157322d54Sernest.zhang 				host->flags &= ~SDHCI_SIGNALING_330;
21257322d54Sernest.zhang 				host->flags |= SDHCI_SIGNALING_180;
21357322d54Sernest.zhang 				host->mmc->caps2 |= MMC_CAP2_NO_SD;
21457322d54Sernest.zhang 				host->mmc->caps2 |= MMC_CAP2_NO_SDIO;
21557322d54Sernest.zhang 			}
21657322d54Sernest.zhang 		}
21757322d54Sernest.zhang 
21801acf691SAdam Lee 		if (chip->pdev->device != PCI_DEVICE_ID_O2_FUJIN2)
21901acf691SAdam Lee 			break;
22001acf691SAdam Lee 		/* set dll watch dog timer */
22101acf691SAdam Lee 		reg = sdhci_readl(host, O2_SD_VENDOR_SETTING2);
22201acf691SAdam Lee 		reg |= (1 << 12);
22301acf691SAdam Lee 		sdhci_writel(host, reg, O2_SD_VENDOR_SETTING2);
22401acf691SAdam Lee 
22501acf691SAdam Lee 		break;
22601acf691SAdam Lee 	default:
22701acf691SAdam Lee 		break;
22801acf691SAdam Lee 	}
22901acf691SAdam Lee 
23001acf691SAdam Lee 	return 0;
23101acf691SAdam Lee }
23201acf691SAdam Lee 
23301acf691SAdam Lee int sdhci_pci_o2_probe(struct sdhci_pci_chip *chip)
23401acf691SAdam Lee {
23501acf691SAdam Lee 	int ret;
23601acf691SAdam Lee 	u8 scratch;
23701acf691SAdam Lee 	u32 scratch_32;
23801acf691SAdam Lee 
23901acf691SAdam Lee 	switch (chip->pdev->device) {
24001acf691SAdam Lee 	case PCI_DEVICE_ID_O2_8220:
24101acf691SAdam Lee 	case PCI_DEVICE_ID_O2_8221:
24201acf691SAdam Lee 	case PCI_DEVICE_ID_O2_8320:
24301acf691SAdam Lee 	case PCI_DEVICE_ID_O2_8321:
24401acf691SAdam Lee 		/* This extra setup is required due to broken ADMA. */
24501acf691SAdam Lee 		ret = pci_read_config_byte(chip->pdev,
24601acf691SAdam Lee 				O2_SD_LOCK_WP, &scratch);
24701acf691SAdam Lee 		if (ret)
24801acf691SAdam Lee 			return ret;
24901acf691SAdam Lee 		scratch &= 0x7f;
25001acf691SAdam Lee 		pci_write_config_byte(chip->pdev, O2_SD_LOCK_WP, scratch);
25101acf691SAdam Lee 
25201acf691SAdam Lee 		/* Set Multi 3 to VCC3V# */
25301acf691SAdam Lee 		pci_write_config_byte(chip->pdev, O2_SD_MULTI_VCC3V, 0x08);
25401acf691SAdam Lee 
25501acf691SAdam Lee 		/* Disable CLK_REQ# support after media DET */
25601acf691SAdam Lee 		ret = pci_read_config_byte(chip->pdev,
25701acf691SAdam Lee 				O2_SD_CLKREQ, &scratch);
25801acf691SAdam Lee 		if (ret)
25901acf691SAdam Lee 			return ret;
26001acf691SAdam Lee 		scratch |= 0x20;
26101acf691SAdam Lee 		pci_write_config_byte(chip->pdev, O2_SD_CLKREQ, scratch);
26201acf691SAdam Lee 
26301acf691SAdam Lee 		/* Choose capabilities, enable SDMA.  We have to write 0x01
26401acf691SAdam Lee 		 * to the capabilities register first to unlock it.
26501acf691SAdam Lee 		 */
26601acf691SAdam Lee 		ret = pci_read_config_byte(chip->pdev, O2_SD_CAPS, &scratch);
26701acf691SAdam Lee 		if (ret)
26801acf691SAdam Lee 			return ret;
26901acf691SAdam Lee 		scratch |= 0x01;
27001acf691SAdam Lee 		pci_write_config_byte(chip->pdev, O2_SD_CAPS, scratch);
27101acf691SAdam Lee 		pci_write_config_byte(chip->pdev, O2_SD_CAPS, 0x73);
27201acf691SAdam Lee 
27301acf691SAdam Lee 		/* Disable ADMA1/2 */
27401acf691SAdam Lee 		pci_write_config_byte(chip->pdev, O2_SD_ADMA1, 0x39);
27501acf691SAdam Lee 		pci_write_config_byte(chip->pdev, O2_SD_ADMA2, 0x08);
27601acf691SAdam Lee 
27701acf691SAdam Lee 		/* Disable the infinite transfer mode */
27801acf691SAdam Lee 		ret = pci_read_config_byte(chip->pdev,
27901acf691SAdam Lee 				O2_SD_INF_MOD, &scratch);
28001acf691SAdam Lee 		if (ret)
28101acf691SAdam Lee 			return ret;
28201acf691SAdam Lee 		scratch |= 0x08;
28301acf691SAdam Lee 		pci_write_config_byte(chip->pdev, O2_SD_INF_MOD, scratch);
28401acf691SAdam Lee 
28501acf691SAdam Lee 		/* Lock WP */
28601acf691SAdam Lee 		ret = pci_read_config_byte(chip->pdev,
28701acf691SAdam Lee 				O2_SD_LOCK_WP, &scratch);
28801acf691SAdam Lee 		if (ret)
28901acf691SAdam Lee 			return ret;
29001acf691SAdam Lee 		scratch |= 0x80;
29101acf691SAdam Lee 		pci_write_config_byte(chip->pdev, O2_SD_LOCK_WP, scratch);
29201acf691SAdam Lee 		break;
29301acf691SAdam Lee 	case PCI_DEVICE_ID_O2_SDS0:
29401acf691SAdam Lee 	case PCI_DEVICE_ID_O2_SDS1:
29501acf691SAdam Lee 	case PCI_DEVICE_ID_O2_FUJIN2:
29601acf691SAdam Lee 		/* UnLock WP */
29701acf691SAdam Lee 		ret = pci_read_config_byte(chip->pdev,
29801acf691SAdam Lee 				O2_SD_LOCK_WP, &scratch);
29901acf691SAdam Lee 		if (ret)
30001acf691SAdam Lee 			return ret;
30101acf691SAdam Lee 
30201acf691SAdam Lee 		scratch &= 0x7f;
30301acf691SAdam Lee 		pci_write_config_byte(chip->pdev, O2_SD_LOCK_WP, scratch);
30401acf691SAdam Lee 
305706adf6bSPeter Guo 		/* DevId=8520 subId= 0x11 or 0x12  Type Chip support */
306706adf6bSPeter Guo 		if (chip->pdev->device == PCI_DEVICE_ID_O2_FUJIN2) {
307706adf6bSPeter Guo 			ret = pci_read_config_dword(chip->pdev,
308706adf6bSPeter Guo 						    O2_SD_FUNC_REG0,
309706adf6bSPeter Guo 						    &scratch_32);
310706adf6bSPeter Guo 			scratch_32 = ((scratch_32 & 0xFF000000) >> 24);
311706adf6bSPeter Guo 
312706adf6bSPeter Guo 			/* Check Whether subId is 0x11 or 0x12 */
313706adf6bSPeter Guo 			if ((scratch_32 == 0x11) || (scratch_32 == 0x12)) {
314*3665ff03Sernest.zhang 				scratch_32 = 0x25100000;
315706adf6bSPeter Guo 
316706adf6bSPeter Guo 				o2_pci_set_baseclk(chip, scratch_32);
317706adf6bSPeter Guo 				ret = pci_read_config_dword(chip->pdev,
318706adf6bSPeter Guo 							    O2_SD_FUNC_REG4,
319706adf6bSPeter Guo 							    &scratch_32);
320706adf6bSPeter Guo 
321706adf6bSPeter Guo 				/* Enable Base Clk setting change */
322706adf6bSPeter Guo 				scratch_32 |= O2_SD_FREG4_ENABLE_CLK_SET;
323706adf6bSPeter Guo 				pci_write_config_dword(chip->pdev,
324706adf6bSPeter Guo 						       O2_SD_FUNC_REG4,
325706adf6bSPeter Guo 						       scratch_32);
326706adf6bSPeter Guo 
327706adf6bSPeter Guo 				/* Set Tuning Window to 4 */
328706adf6bSPeter Guo 				pci_write_config_byte(chip->pdev,
329706adf6bSPeter Guo 						      O2_SD_TUNING_CTRL, 0x44);
330706adf6bSPeter Guo 
331706adf6bSPeter Guo 				break;
332706adf6bSPeter Guo 			}
333706adf6bSPeter Guo 		}
334706adf6bSPeter Guo 
335706adf6bSPeter Guo 		/* Enable 8520 led function */
336706adf6bSPeter Guo 		o2_pci_led_enable(chip);
337706adf6bSPeter Guo 
33801acf691SAdam Lee 		/* Set timeout CLK */
33901acf691SAdam Lee 		ret = pci_read_config_dword(chip->pdev,
34001acf691SAdam Lee 					    O2_SD_CLK_SETTING, &scratch_32);
34101acf691SAdam Lee 		if (ret)
34201acf691SAdam Lee 			return ret;
34301acf691SAdam Lee 
34401acf691SAdam Lee 		scratch_32 &= ~(0xFF00);
34501acf691SAdam Lee 		scratch_32 |= 0x07E0C800;
34601acf691SAdam Lee 		pci_write_config_dword(chip->pdev,
34701acf691SAdam Lee 				       O2_SD_CLK_SETTING, scratch_32);
34801acf691SAdam Lee 
34901acf691SAdam Lee 		ret = pci_read_config_dword(chip->pdev,
35001acf691SAdam Lee 					    O2_SD_CLKREQ, &scratch_32);
35101acf691SAdam Lee 		if (ret)
35201acf691SAdam Lee 			return ret;
35301acf691SAdam Lee 		scratch_32 |= 0x3;
35401acf691SAdam Lee 		pci_write_config_dword(chip->pdev, O2_SD_CLKREQ, scratch_32);
35501acf691SAdam Lee 
35601acf691SAdam Lee 		ret = pci_read_config_dword(chip->pdev,
35701acf691SAdam Lee 					    O2_SD_PLL_SETTING, &scratch_32);
35801acf691SAdam Lee 		if (ret)
35901acf691SAdam Lee 			return ret;
36001acf691SAdam Lee 
36101acf691SAdam Lee 		scratch_32 &= ~(0x1F3F070E);
36201acf691SAdam Lee 		scratch_32 |= 0x18270106;
36301acf691SAdam Lee 		pci_write_config_dword(chip->pdev,
36401acf691SAdam Lee 				       O2_SD_PLL_SETTING, scratch_32);
36501acf691SAdam Lee 
36601acf691SAdam Lee 		/* Disable UHS1 funciton */
36701acf691SAdam Lee 		ret = pci_read_config_dword(chip->pdev,
36801acf691SAdam Lee 					    O2_SD_CAP_REG2, &scratch_32);
36901acf691SAdam Lee 		if (ret)
37001acf691SAdam Lee 			return ret;
37101acf691SAdam Lee 		scratch_32 &= ~(0xE0);
37201acf691SAdam Lee 		pci_write_config_dword(chip->pdev,
37301acf691SAdam Lee 				       O2_SD_CAP_REG2, scratch_32);
37401acf691SAdam Lee 
37501acf691SAdam Lee 		if (chip->pdev->device == PCI_DEVICE_ID_O2_FUJIN2)
37601acf691SAdam Lee 			sdhci_pci_o2_fujin2_pci_init(chip);
37701acf691SAdam Lee 
37801acf691SAdam Lee 		/* Lock WP */
37901acf691SAdam Lee 		ret = pci_read_config_byte(chip->pdev,
38001acf691SAdam Lee 					   O2_SD_LOCK_WP, &scratch);
38101acf691SAdam Lee 		if (ret)
38201acf691SAdam Lee 			return ret;
38301acf691SAdam Lee 		scratch |= 0x80;
38401acf691SAdam Lee 		pci_write_config_byte(chip->pdev, O2_SD_LOCK_WP, scratch);
38501acf691SAdam Lee 		break;
38601acf691SAdam Lee 	case PCI_DEVICE_ID_O2_SEABIRD0:
38701acf691SAdam Lee 	case PCI_DEVICE_ID_O2_SEABIRD1:
38801acf691SAdam Lee 		/* UnLock WP */
38901acf691SAdam Lee 		ret = pci_read_config_byte(chip->pdev,
39001acf691SAdam Lee 				O2_SD_LOCK_WP, &scratch);
39101acf691SAdam Lee 		if (ret)
39201acf691SAdam Lee 			return ret;
39301acf691SAdam Lee 
39401acf691SAdam Lee 		scratch &= 0x7f;
39501acf691SAdam Lee 		pci_write_config_byte(chip->pdev, O2_SD_LOCK_WP, scratch);
39601acf691SAdam Lee 
39701acf691SAdam Lee 		ret = pci_read_config_dword(chip->pdev,
398706adf6bSPeter Guo 					    O2_SD_PLL_SETTING, &scratch_32);
39901acf691SAdam Lee 
40001acf691SAdam Lee 		if ((scratch_32 & 0xff000000) == 0x01000000) {
40101acf691SAdam Lee 			scratch_32 &= 0x0000FFFF;
40201acf691SAdam Lee 			scratch_32 |= 0x1F340000;
40301acf691SAdam Lee 
40401acf691SAdam Lee 			pci_write_config_dword(chip->pdev,
40501acf691SAdam Lee 					       O2_SD_PLL_SETTING, scratch_32);
40601acf691SAdam Lee 		} else {
40701acf691SAdam Lee 			scratch_32 &= 0x0000FFFF;
408*3665ff03Sernest.zhang 			scratch_32 |= 0x25100000;
40901acf691SAdam Lee 
41001acf691SAdam Lee 			pci_write_config_dword(chip->pdev,
41101acf691SAdam Lee 					       O2_SD_PLL_SETTING, scratch_32);
41201acf691SAdam Lee 
41301acf691SAdam Lee 			ret = pci_read_config_dword(chip->pdev,
41401acf691SAdam Lee 						    O2_SD_FUNC_REG4,
41501acf691SAdam Lee 						    &scratch_32);
41601acf691SAdam Lee 			scratch_32 |= (1 << 22);
41701acf691SAdam Lee 			pci_write_config_dword(chip->pdev,
41801acf691SAdam Lee 					       O2_SD_FUNC_REG4, scratch_32);
41901acf691SAdam Lee 		}
42001acf691SAdam Lee 
421706adf6bSPeter Guo 		/* Set Tuning Windows to 5 */
422706adf6bSPeter Guo 		pci_write_config_byte(chip->pdev,
423706adf6bSPeter Guo 				O2_SD_TUNING_CTRL, 0x55);
42401acf691SAdam Lee 		/* Lock WP */
42501acf691SAdam Lee 		ret = pci_read_config_byte(chip->pdev,
42601acf691SAdam Lee 					   O2_SD_LOCK_WP, &scratch);
42701acf691SAdam Lee 		if (ret)
42801acf691SAdam Lee 			return ret;
42901acf691SAdam Lee 		scratch |= 0x80;
43001acf691SAdam Lee 		pci_write_config_byte(chip->pdev, O2_SD_LOCK_WP, scratch);
43101acf691SAdam Lee 		break;
43201acf691SAdam Lee 	}
43301acf691SAdam Lee 
43401acf691SAdam Lee 	return 0;
43501acf691SAdam Lee }
43601acf691SAdam Lee 
437b7813f0fSAdrian Hunter #ifdef CONFIG_PM_SLEEP
43801acf691SAdam Lee int sdhci_pci_o2_resume(struct sdhci_pci_chip *chip)
43901acf691SAdam Lee {
44001acf691SAdam Lee 	sdhci_pci_o2_probe(chip);
44130cf2803SAdrian Hunter 	return sdhci_pci_resume_host(chip);
44201acf691SAdam Lee }
443b7813f0fSAdrian Hunter #endif
444