2 * This file is part of the coreboot project.
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; version 2 of the License.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
17 #include <console/console.h>
18 #include <device/device.h>
19 #include <device/pci.h>
20 #include <device/pci_ids.h>
21 #include <reg_script.h>
25 #include <soc/pci_devs.h>
26 #include <soc/ramstage.h>
30 static void dev_enable_acpi_mode(struct device
*dev
, int iosf_reg
,
33 struct reg_script ops
[] = {
34 /* Disable PCI interrupt, enable Memory and Bus Master */
35 REG_PCI_OR32(PCI_COMMAND
,
36 PCI_COMMAND_MEMORY
| PCI_COMMAND_MASTER
| (1<<10)),
37 /* Enable ACPI mode */
38 REG_IOSF_OR(IOSF_PORT_LPSS
, iosf_reg
,
39 LPSS_CTL_PCI_CFG_DIS
| LPSS_CTL_ACPI_INT_EN
),
45 /* Find ACPI NVS to update BARs */
46 gnvs
= (global_nvs_t
*)cbmem_find(CBMEM_ID_ACPI_GNVS
);
48 printk(BIOS_ERR
, "Unable to locate Global NVS\n");
52 /* Save BAR0 and BAR1 to ACPI NVS */
53 bar
= find_resource(dev
, PCI_BASE_ADDRESS_0
);
55 gnvs
->dev
.lpss_bar0
[nvs_index
] = (u32
)bar
->base
;
57 bar
= find_resource(dev
, PCI_BASE_ADDRESS_1
);
59 gnvs
->dev
.lpss_bar1
[nvs_index
] = (u32
)bar
->base
;
61 /* Device is enabled in ACPI mode */
62 gnvs
->dev
.lpss_en
[nvs_index
] = 1;
64 /* Put device in ACPI mode */
65 reg_script_run_on_dev(dev
, ops
);
68 static void dev_enable_snoop_and_pm(struct device
*dev
, int iosf_reg
)
70 struct reg_script ops
[] = {
71 REG_IOSF_RMW(IOSF_PORT_LPSS
, iosf_reg
,
72 ~(LPSS_CTL_SNOOP
| LPSS_CTL_NOSNOOP
),
73 LPSS_CTL_SNOOP
| LPSS_CTL_PM_CAP_PRSNT
),
77 reg_script_run_on_dev(dev
, ops
);
80 static void dev_ctl_reg(struct device
*dev
, int *iosf_reg
, int *nvs_index
)
84 #define SET_IOSF_REG(name_) \
85 case PCI_DEVFN(name_ ## _DEV, name_ ## _FUNC): \
86 *iosf_reg = LPSS_ ## name_ ## _CTL; \
87 *nvs_index = LPSS_NVS_ ## name_
89 switch (dev
->path
.pci
.devfn
) {
90 SET_IOSF_REG(SIO_DMA1
);
106 SET_IOSF_REG(SIO_DMA2
);
112 SET_IOSF_REG(HSUART1
);
114 SET_IOSF_REG(HSUART2
);
121 static void i2c_disable_resets(struct device
*dev
)
123 /* Release the I2C devices from reset. */
124 static const struct reg_script ops
[] = {
125 REG_RES_WRITE32(PCI_BASE_ADDRESS_0
, 0x804, 0x3),
129 #define CASE_I2C(name_) \
130 case PCI_DEVFN(name_ ## _DEV, name_ ## _FUNC)
132 switch (dev
->path
.pci
.devfn
) {
140 printk(BIOS_DEBUG
, "Releasing I2C device from reset.\n");
141 reg_script_run_on_dev(dev
, ops
);
148 static void lpss_init(struct device
*dev
)
150 struct soc_intel_baytrail_config
*config
= config_of(dev
);
151 int iosf_reg
, nvs_index
;
153 dev_ctl_reg(dev
, &iosf_reg
, &nvs_index
);
156 int slot
= PCI_SLOT(dev
->path
.pci
.devfn
);
157 int func
= PCI_FUNC(dev
->path
.pci
.devfn
);
158 printk(BIOS_DEBUG
, "Could not find iosf_reg for %02x.%01x\n",
162 dev_enable_snoop_and_pm(dev
, iosf_reg
);
163 i2c_disable_resets(dev
);
165 if (config
->lpss_acpi_mode
)
166 dev_enable_acpi_mode(dev
, iosf_reg
, nvs_index
);
169 static struct device_operations device_ops
= {
170 .read_resources
= pci_dev_read_resources
,
171 .set_resources
= pci_dev_set_resources
,
172 .enable_resources
= pci_dev_enable_resources
,
176 .ops_pci
= &soc_pci_ops
,
179 static const unsigned short pci_device_ids
[] = {
197 static const struct pci_driver southcluster __pci_driver
= {
199 .vendor
= PCI_VENDOR_ID_INTEL
,
200 .devices
= pci_device_ids
,