blob: 582c3237ce1180d55f3c488e9e94fbc3c97e34d2 [file] [log] [blame]
Angel Ponsba38f372020-04-05 15:46:45 +02001/* SPDX-License-Identifier: GPL-2.0-only */
2/* This file is part of the coreboot project. */
Lee Leahy77ff0b12015-05-05 15:07:29 -07003
4#include <stdint.h>
Lee Leahy77ff0b12015-05-05 15:07:29 -07005#include <cbmem.h>
6#include <console/console.h>
7#include <device/device.h>
8#include <device/pci.h>
9#include <device/pci_ids.h>
10#include <reg_script.h>
11
12#include <soc/iosf.h>
13#include <soc/nvs.h>
14#include <soc/pci_devs.h>
15#include <soc/ramstage.h>
16
17#include "chip.h"
18
Angel Ponsaee7ab22020-03-19 00:31:58 +010019static void dev_enable_acpi_mode(struct device *dev, int iosf_reg, int nvs_index)
Lee Leahy77ff0b12015-05-05 15:07:29 -070020{
21 struct reg_script ops[] = {
22 /* Disable PCI interrupt, enable Memory and Bus Master */
Angel Ponsaee7ab22020-03-19 00:31:58 +010023 REG_PCI_OR32(PCI_COMMAND, PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | (1 << 10)),
Lee Leahy77ff0b12015-05-05 15:07:29 -070024 /* Enable ACPI mode */
25 REG_IOSF_OR(IOSF_PORT_LPSS, iosf_reg,
26 LPSS_CTL_PCI_CFG_DIS | LPSS_CTL_ACPI_INT_EN),
Angel Ponsaee7ab22020-03-19 00:31:58 +010027
Lee Leahy77ff0b12015-05-05 15:07:29 -070028 REG_SCRIPT_END
29 };
30 struct resource *bar;
31 global_nvs_t *gnvs;
32
33 /* Find ACPI NVS to update BARs */
Lee Leahy32471722015-04-20 15:20:28 -070034 gnvs = cbmem_find(CBMEM_ID_ACPI_GNVS);
Lee Leahy77ff0b12015-05-05 15:07:29 -070035 if (!gnvs) {
36 printk(BIOS_ERR, "Unable to locate Global NVS\n");
37 return;
38 }
39
40 /* Save BAR0 and BAR1 to ACPI NVS */
41 bar = find_resource(dev, PCI_BASE_ADDRESS_0);
42 if (bar)
43 gnvs->dev.lpss_bar0[nvs_index] = (u32)bar->base;
44
45 bar = find_resource(dev, PCI_BASE_ADDRESS_1);
46 if (bar)
47 gnvs->dev.lpss_bar1[nvs_index] = (u32)bar->base;
48
49 /* Device is enabled in ACPI mode */
50 gnvs->dev.lpss_en[nvs_index] = 1;
51
52 /* Put device in ACPI mode */
53 reg_script_run_on_dev(dev, ops);
54}
55
Lee Leahy77ff0b12015-05-05 15:07:29 -070056#define SET_IOSF_REG(name_) \
57 case PCI_DEVFN(name_ ## _DEV, name_ ## _FUNC): \
Lee Leahy32471722015-04-20 15:20:28 -070058 do { \
59 *iosf_reg = LPSS_ ## name_ ## _CTL; \
60 *nvs_index = LPSS_NVS_ ## name_; \
61 } while (0)
Lee Leahy77ff0b12015-05-05 15:07:29 -070062
Angel Ponsaee7ab22020-03-19 00:31:58 +010063static void dev_ctl_reg(struct device *dev, int *iosf_reg, int *nvs_index)
64{
65 *iosf_reg = -1;
66 *nvs_index = -1;
67
Lee Leahy77ff0b12015-05-05 15:07:29 -070068 switch (dev->path.pci.devfn) {
69 SET_IOSF_REG(SIO_DMA1);
70 break;
71 SET_IOSF_REG(I2C1);
72 break;
73 SET_IOSF_REG(I2C2);
74 break;
75 SET_IOSF_REG(I2C3);
76 break;
77 SET_IOSF_REG(I2C4);
78 break;
79 SET_IOSF_REG(I2C5);
80 break;
81 SET_IOSF_REG(I2C6);
82 break;
83 SET_IOSF_REG(I2C7);
84 break;
85 SET_IOSF_REG(SIO_DMA2);
86 break;
87 SET_IOSF_REG(PWM1);
88 break;
89 SET_IOSF_REG(PWM2);
90 break;
91 SET_IOSF_REG(HSUART1);
92 break;
93 SET_IOSF_REG(HSUART2);
94 break;
95 SET_IOSF_REG(SPI);
96 break;
97 }
98}
99
Angel Ponsaee7ab22020-03-19 00:31:58 +0100100#define CASE_I2C(name_) case PCI_DEVFN(name_ ## _DEV, name_ ## _FUNC)
101
Elyes HAOUASb13fac32018-05-24 22:29:44 +0200102static void i2c_disable_resets(struct device *dev)
Lee Leahy77ff0b12015-05-05 15:07:29 -0700103{
104 /* Release the I2C devices from reset. */
105 static const struct reg_script ops[] = {
106 REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0x804, 0x3),
107 REG_SCRIPT_END,
108 };
109
Lee Leahy77ff0b12015-05-05 15:07:29 -0700110 switch (dev->path.pci.devfn) {
Lee Leahy32471722015-04-20 15:20:28 -0700111 CASE_I2C(I2C1) :
112 CASE_I2C(I2C2) :
113 CASE_I2C(I2C3) :
114 CASE_I2C(I2C4) :
115 CASE_I2C(I2C5) :
116 CASE_I2C(I2C6) :
117 CASE_I2C(I2C7) :
Lee Leahy77ff0b12015-05-05 15:07:29 -0700118 printk(BIOS_DEBUG, "Releasing I2C device from reset.\n");
119 reg_script_run_on_dev(dev, ops);
120 break;
121 default:
122 return;
123 }
124}
125
Elyes HAOUASb13fac32018-05-24 22:29:44 +0200126static void lpss_init(struct device *dev)
Lee Leahy77ff0b12015-05-05 15:07:29 -0700127{
Kyösti Mälkki8950cfb2019-07-13 22:16:25 +0300128 struct soc_intel_braswell_config *config = config_of(dev);
Lee Leahy77ff0b12015-05-05 15:07:29 -0700129 int iosf_reg, nvs_index;
130
Angel Ponsaee7ab22020-03-19 00:31:58 +0100131 printk(BIOS_SPEW, "%s/%s (%s)\n", __FILE__, __func__, dev_name(dev));
132 printk(BIOS_SPEW, "%s - %s\n", get_pci_class_name(dev), get_pci_subclass_name(dev));
Lee Leahy32471722015-04-20 15:20:28 -0700133
Lee Leahy77ff0b12015-05-05 15:07:29 -0700134 dev_ctl_reg(dev, &iosf_reg, &nvs_index);
135
136 if (iosf_reg < 0) {
137 int slot = PCI_SLOT(dev->path.pci.devfn);
138 int func = PCI_FUNC(dev->path.pci.devfn);
Angel Ponsaee7ab22020-03-19 00:31:58 +0100139 printk(BIOS_DEBUG, "Could not find iosf_reg for %02x.%01x\n", slot, func);
Lee Leahy77ff0b12015-05-05 15:07:29 -0700140 return;
141 }
Lee Leahy32471722015-04-20 15:20:28 -0700142
Lee Leahy77ff0b12015-05-05 15:07:29 -0700143 i2c_disable_resets(dev);
144
145 if (config->lpss_acpi_mode)
146 dev_enable_acpi_mode(dev, iosf_reg, nvs_index);
147}
148
149static struct device_operations device_ops = {
150 .read_resources = pci_dev_read_resources,
151 .set_resources = pci_dev_set_resources,
152 .enable_resources = pci_dev_enable_resources,
153 .init = lpss_init,
Lee Leahy77ff0b12015-05-05 15:07:29 -0700154 .ops_pci = &soc_pci_ops,
155};
156
157static const unsigned short pci_device_ids[] = {
158 SIO_DMA1_DEVID,
159 I2C1_DEVID,
160 I2C2_DEVID,
161 I2C3_DEVID,
162 I2C4_DEVID,
163 I2C5_DEVID,
164 I2C6_DEVID,
165 I2C7_DEVID,
166 SIO_DMA2_DEVID,
167 PWM1_DEVID,
168 PWM2_DEVID,
169 HSUART1_DEVID,
170 HSUART2_DEVID,
171 SPI_DEVID,
172 0,
173};
174
175static const struct pci_driver southcluster __pci_driver = {
176 .ops = &device_ops,
177 .vendor = PCI_VENDOR_ID_INTEL,
178 .devices = pci_device_ids,
179};