blob: caee7d9007d1de0e97f8f597a0036407cedc84f7 [file] [log] [blame]
Angel Pons0612b272020-04-05 15:46:56 +02001/* SPDX-License-Identifier: GPL-2.0-only */
Bora Guvendikb7fe7a12018-03-08 16:32:43 -08002
Furquan Shaikh76cedd22020-05-02 10:24:23 -07003#include <acpi/acpi.h>
Bora Guvendikb7fe7a12018-03-08 16:32:43 -08004#include <cbmem.h>
5#include <commonlib/storage/sd_mmc.h>
6#include <commonlib/sd_mmc_ctrlr.h>
7#include <commonlib/sdhci.h>
8#include <compiler.h>
9#include <console/console.h>
10#include <device/pci.h>
Kane Chen01ebc742019-08-23 12:03:05 +080011#include <intelblocks/mmc.h>
Bora Guvendikb7fe7a12018-03-08 16:32:43 -080012#include <soc/iomap.h>
13#include <soc/pci_devs.h>
14#include <string.h>
15
Bora Guvendikb7fe7a12018-03-08 16:32:43 -080016void soc_sd_mmc_controller_quirks(struct sd_mmc_ctrlr *ctrlr)
17{
18 uint32_t f_min, f_max;
19
20 if (soc_get_mmc_frequencies(&f_min, &f_max) < 0) {
21 printk(BIOS_ERR,
22 "MMC early init: failed to get mmc frequencies\n");
23 return;
24 }
25
26 ctrlr->f_min = f_min;
27 ctrlr->f_max = f_max;
28}
29
30static void enable_mmc_controller_bar(void)
31{
32 pci_write_config32(PCH_DEV_EMMC, PCI_BASE_ADDRESS_0,
33 PRERAM_MMC_BASE_ADDRESS);
Elyes HAOUAS2ec1c132020-04-29 09:57:05 +020034 pci_write_config16(PCH_DEV_EMMC, PCI_COMMAND,
Bora Guvendikb7fe7a12018-03-08 16:32:43 -080035 PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY);
36}
37
38static void disable_mmc_controller_bar(void)
39{
40 pci_write_config32(PCH_DEV_EMMC, PCI_BASE_ADDRESS_0, 0);
Elyes HAOUAS2ec1c132020-04-29 09:57:05 +020041 pci_write_config16(PCH_DEV_EMMC, PCI_COMMAND,
Bora Guvendikb7fe7a12018-03-08 16:32:43 -080042 ~(PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY));
43}
44
Bora Guvendikb7fe7a12018-03-08 16:32:43 -080045static void set_early_mmc_wake_status(int32_t status)
46{
47 int32_t *ms_cbmem;
48
49 ms_cbmem = cbmem_add(CBMEM_ID_MMC_STATUS, sizeof(int));
50
51 if (ms_cbmem == NULL) {
52 printk(BIOS_ERR,
53 "%s: Failed to add early mmc wake status to cbmem!\n",
54 __func__);
55 return;
56 }
57
58 *ms_cbmem = status;
59}
60
61int early_mmc_wake_hw(void)
62{
63 struct storage_media media;
64 struct sd_mmc_ctrlr *mmc_ctrlr;
65 struct sdhci_ctrlr *sdhci_ctrlr;
66 int err;
67
68 if (acpi_is_wakeup_s3())
69 return -1;
70
71 /* Configure mmc gpios */
72 if (soc_configure_mmc_gpios() < 0) {
73 printk(BIOS_ERR,
74 "%s: MMC early init: failed to configure mmc gpios\n",
75 __func__);
76 return -1;
77 }
78 /* Setup pci bar */
79 enable_mmc_controller_bar();
80
81 /* Initialize sdhci */
82 mmc_ctrlr = new_pci_sdhci_controller(PCH_DEV_EMMC);
83 if (mmc_ctrlr == NULL)
84 goto out_err;
85
86 sdhci_ctrlr = container_of(mmc_ctrlr, struct sdhci_ctrlr, sd_mmc_ctrlr);
87
88 /* set emmc DLL tuning parameters */
89 if (set_mmc_dll(sdhci_ctrlr->ioaddr) < 0)
90 goto out_err;
91
92 memset(&media, 0, sizeof(media));
93 media.ctrlr = mmc_ctrlr;
94 SET_BUS_WIDTH(mmc_ctrlr, 1);
95 /*
96 * Set clock to 1 so that the driver can choose minimum frequency
97 * possible
98 */
99 SET_CLOCK(mmc_ctrlr, 1);
100
101 /* Reset emmc, send CMD0 */
102 if (sd_mmc_go_idle(&media))
103 goto out_err;
104
105 /* Send CMD1 */
106 err = mmc_send_op_cond(&media);
107 if (err != 0 && err != CARD_IN_PROGRESS)
108 goto out_err;
109
110 disable_mmc_controller_bar();
111
112 set_early_mmc_wake_status(1);
113 return 0;
114
115out_err:
116
117 disable_mmc_controller_bar();
118 return -1;
119}