blob: 82002487af1fc7085737b5d5771a825a2312cf8b [file] [log] [blame]
Angel Ponsba38f372020-04-05 15:46:45 +02001/* SPDX-License-Identifier: GPL-2.0-only */
Lee Leahy77ff0b12015-05-05 15:07:29 -07002
3#include <stdint.h>
Kyösti Mälkki5daa1d32020-06-14 12:01:58 +03004#include <acpi/acpi_gnvs.h>
Lee Leahy77ff0b12015-05-05 15:07:29 -07005#include <console/console.h>
6#include <device/device.h>
7#include <device/pci.h>
8#include <device/pci_ids.h>
9#include <reg_script.h>
10
11#include <soc/iosf.h>
12#include <soc/nvs.h>
13#include <soc/pci_devs.h>
14#include <soc/ramstage.h>
15
16#include "chip.h"
17
Angel Ponsaee7ab22020-03-19 00:31:58 +010018static void dev_enable_acpi_mode(struct device *dev, int iosf_reg, int nvs_index)
Lee Leahy77ff0b12015-05-05 15:07:29 -070019{
20 struct reg_script ops[] = {
21 /* Disable PCI interrupt, enable Memory and Bus Master */
Angel Ponsaee7ab22020-03-19 00:31:58 +010022 REG_PCI_OR32(PCI_COMMAND, PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | (1 << 10)),
Lee Leahy77ff0b12015-05-05 15:07:29 -070023 /* Enable ACPI mode */
24 REG_IOSF_OR(IOSF_PORT_LPSS, iosf_reg,
25 LPSS_CTL_PCI_CFG_DIS | LPSS_CTL_ACPI_INT_EN),
Angel Ponsaee7ab22020-03-19 00:31:58 +010026
Lee Leahy77ff0b12015-05-05 15:07:29 -070027 REG_SCRIPT_END
28 };
29 struct resource *bar;
30 global_nvs_t *gnvs;
31
32 /* Find ACPI NVS to update BARs */
Kyösti Mälkki5daa1d32020-06-14 12:01:58 +030033 gnvs = acpi_get_gnvs();
34 if (!gnvs)
Lee Leahy77ff0b12015-05-05 15:07:29 -070035 return;
Lee Leahy77ff0b12015-05-05 15:07:29 -070036
37 /* Save BAR0 and BAR1 to ACPI NVS */
38 bar = find_resource(dev, PCI_BASE_ADDRESS_0);
39 if (bar)
40 gnvs->dev.lpss_bar0[nvs_index] = (u32)bar->base;
41
42 bar = find_resource(dev, PCI_BASE_ADDRESS_1);
43 if (bar)
44 gnvs->dev.lpss_bar1[nvs_index] = (u32)bar->base;
45
46 /* Device is enabled in ACPI mode */
47 gnvs->dev.lpss_en[nvs_index] = 1;
48
49 /* Put device in ACPI mode */
50 reg_script_run_on_dev(dev, ops);
51}
52
Lee Leahy77ff0b12015-05-05 15:07:29 -070053#define SET_IOSF_REG(name_) \
54 case PCI_DEVFN(name_ ## _DEV, name_ ## _FUNC): \
Lee Leahy32471722015-04-20 15:20:28 -070055 do { \
56 *iosf_reg = LPSS_ ## name_ ## _CTL; \
57 *nvs_index = LPSS_NVS_ ## name_; \
58 } while (0)
Lee Leahy77ff0b12015-05-05 15:07:29 -070059
Angel Ponsaee7ab22020-03-19 00:31:58 +010060static void dev_ctl_reg(struct device *dev, int *iosf_reg, int *nvs_index)
61{
62 *iosf_reg = -1;
63 *nvs_index = -1;
64
Lee Leahy77ff0b12015-05-05 15:07:29 -070065 switch (dev->path.pci.devfn) {
66 SET_IOSF_REG(SIO_DMA1);
67 break;
68 SET_IOSF_REG(I2C1);
69 break;
70 SET_IOSF_REG(I2C2);
71 break;
72 SET_IOSF_REG(I2C3);
73 break;
74 SET_IOSF_REG(I2C4);
75 break;
76 SET_IOSF_REG(I2C5);
77 break;
78 SET_IOSF_REG(I2C6);
79 break;
80 SET_IOSF_REG(I2C7);
81 break;
82 SET_IOSF_REG(SIO_DMA2);
83 break;
84 SET_IOSF_REG(PWM1);
85 break;
86 SET_IOSF_REG(PWM2);
87 break;
88 SET_IOSF_REG(HSUART1);
89 break;
90 SET_IOSF_REG(HSUART2);
91 break;
92 SET_IOSF_REG(SPI);
93 break;
94 }
95}
96
Angel Ponsaee7ab22020-03-19 00:31:58 +010097#define CASE_I2C(name_) case PCI_DEVFN(name_ ## _DEV, name_ ## _FUNC)
98
Elyes HAOUASb13fac32018-05-24 22:29:44 +020099static void i2c_disable_resets(struct device *dev)
Lee Leahy77ff0b12015-05-05 15:07:29 -0700100{
101 /* Release the I2C devices from reset. */
102 static const struct reg_script ops[] = {
103 REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0x804, 0x3),
104 REG_SCRIPT_END,
105 };
106
Lee Leahy77ff0b12015-05-05 15:07:29 -0700107 switch (dev->path.pci.devfn) {
Lee Leahy32471722015-04-20 15:20:28 -0700108 CASE_I2C(I2C1) :
109 CASE_I2C(I2C2) :
110 CASE_I2C(I2C3) :
111 CASE_I2C(I2C4) :
112 CASE_I2C(I2C5) :
113 CASE_I2C(I2C6) :
114 CASE_I2C(I2C7) :
Lee Leahy77ff0b12015-05-05 15:07:29 -0700115 printk(BIOS_DEBUG, "Releasing I2C device from reset.\n");
116 reg_script_run_on_dev(dev, ops);
117 break;
118 default:
119 return;
120 }
121}
122
Elyes HAOUASb13fac32018-05-24 22:29:44 +0200123static void lpss_init(struct device *dev)
Lee Leahy77ff0b12015-05-05 15:07:29 -0700124{
Kyösti Mälkki8950cfb2019-07-13 22:16:25 +0300125 struct soc_intel_braswell_config *config = config_of(dev);
Lee Leahy77ff0b12015-05-05 15:07:29 -0700126 int iosf_reg, nvs_index;
127
Angel Ponsaee7ab22020-03-19 00:31:58 +0100128 printk(BIOS_SPEW, "%s/%s (%s)\n", __FILE__, __func__, dev_name(dev));
129 printk(BIOS_SPEW, "%s - %s\n", get_pci_class_name(dev), get_pci_subclass_name(dev));
Lee Leahy32471722015-04-20 15:20:28 -0700130
Lee Leahy77ff0b12015-05-05 15:07:29 -0700131 dev_ctl_reg(dev, &iosf_reg, &nvs_index);
132
133 if (iosf_reg < 0) {
134 int slot = PCI_SLOT(dev->path.pci.devfn);
135 int func = PCI_FUNC(dev->path.pci.devfn);
Angel Ponsaee7ab22020-03-19 00:31:58 +0100136 printk(BIOS_DEBUG, "Could not find iosf_reg for %02x.%01x\n", slot, func);
Lee Leahy77ff0b12015-05-05 15:07:29 -0700137 return;
138 }
Lee Leahy32471722015-04-20 15:20:28 -0700139
Lee Leahy77ff0b12015-05-05 15:07:29 -0700140 i2c_disable_resets(dev);
141
142 if (config->lpss_acpi_mode)
143 dev_enable_acpi_mode(dev, iosf_reg, nvs_index);
144}
145
146static struct device_operations device_ops = {
147 .read_resources = pci_dev_read_resources,
148 .set_resources = pci_dev_set_resources,
149 .enable_resources = pci_dev_enable_resources,
150 .init = lpss_init,
Lee Leahy77ff0b12015-05-05 15:07:29 -0700151 .ops_pci = &soc_pci_ops,
152};
153
154static const unsigned short pci_device_ids[] = {
155 SIO_DMA1_DEVID,
156 I2C1_DEVID,
157 I2C2_DEVID,
158 I2C3_DEVID,
159 I2C4_DEVID,
160 I2C5_DEVID,
161 I2C6_DEVID,
162 I2C7_DEVID,
163 SIO_DMA2_DEVID,
164 PWM1_DEVID,
165 PWM2_DEVID,
166 HSUART1_DEVID,
167 HSUART2_DEVID,
168 SPI_DEVID,
169 0,
170};
171
172static const struct pci_driver southcluster __pci_driver = {
173 .ops = &device_ops,
174 .vendor = PCI_VENDOR_ID_INTEL,
175 .devices = pci_device_ids,
176};