blob: 961d405156aec088a2c422d36fc5a2f2e33d54fc [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 Pons89739ba2020-07-25 02:46:39 +020022 REG_PCI_OR16(PCI_COMMAND,
23 PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | PCI_COMMAND_INT_DISABLE),
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;
Kyösti Mälkki0c1dd9c2020-06-17 23:37:49 +030031 struct global_nvs *gnvs;
Lee Leahy77ff0b12015-05-05 15:07:29 -070032
33 /* Find ACPI NVS to update BARs */
Kyösti Mälkki5daa1d32020-06-14 12:01:58 +030034 gnvs = acpi_get_gnvs();
35 if (!gnvs)
Lee Leahy77ff0b12015-05-05 15:07:29 -070036 return;
Lee Leahy77ff0b12015-05-05 15:07:29 -070037
38 /* Save BAR0 and BAR1 to ACPI NVS */
39 bar = find_resource(dev, PCI_BASE_ADDRESS_0);
40 if (bar)
41 gnvs->dev.lpss_bar0[nvs_index] = (u32)bar->base;
42
43 bar = find_resource(dev, PCI_BASE_ADDRESS_1);
44 if (bar)
45 gnvs->dev.lpss_bar1[nvs_index] = (u32)bar->base;
46
47 /* Device is enabled in ACPI mode */
48 gnvs->dev.lpss_en[nvs_index] = 1;
49
50 /* Put device in ACPI mode */
51 reg_script_run_on_dev(dev, ops);
52}
53
Lee Leahy77ff0b12015-05-05 15:07:29 -070054#define SET_IOSF_REG(name_) \
55 case PCI_DEVFN(name_ ## _DEV, name_ ## _FUNC): \
Lee Leahy32471722015-04-20 15:20:28 -070056 do { \
57 *iosf_reg = LPSS_ ## name_ ## _CTL; \
58 *nvs_index = LPSS_NVS_ ## name_; \
59 } while (0)
Lee Leahy77ff0b12015-05-05 15:07:29 -070060
Angel Ponsaee7ab22020-03-19 00:31:58 +010061static void dev_ctl_reg(struct device *dev, int *iosf_reg, int *nvs_index)
62{
63 *iosf_reg = -1;
64 *nvs_index = -1;
65
Lee Leahy77ff0b12015-05-05 15:07:29 -070066 switch (dev->path.pci.devfn) {
67 SET_IOSF_REG(SIO_DMA1);
68 break;
69 SET_IOSF_REG(I2C1);
70 break;
71 SET_IOSF_REG(I2C2);
72 break;
73 SET_IOSF_REG(I2C3);
74 break;
75 SET_IOSF_REG(I2C4);
76 break;
77 SET_IOSF_REG(I2C5);
78 break;
79 SET_IOSF_REG(I2C6);
80 break;
81 SET_IOSF_REG(I2C7);
82 break;
83 SET_IOSF_REG(SIO_DMA2);
84 break;
85 SET_IOSF_REG(PWM1);
86 break;
87 SET_IOSF_REG(PWM2);
88 break;
89 SET_IOSF_REG(HSUART1);
90 break;
91 SET_IOSF_REG(HSUART2);
92 break;
93 SET_IOSF_REG(SPI);
94 break;
95 }
96}
97
Angel Ponsaee7ab22020-03-19 00:31:58 +010098#define CASE_I2C(name_) case PCI_DEVFN(name_ ## _DEV, name_ ## _FUNC)
99
Elyes HAOUASb13fac32018-05-24 22:29:44 +0200100static void i2c_disable_resets(struct device *dev)
Lee Leahy77ff0b12015-05-05 15:07:29 -0700101{
102 /* Release the I2C devices from reset. */
103 static const struct reg_script ops[] = {
104 REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0x804, 0x3),
105 REG_SCRIPT_END,
106 };
107
Lee Leahy77ff0b12015-05-05 15:07:29 -0700108 switch (dev->path.pci.devfn) {
Lee Leahy32471722015-04-20 15:20:28 -0700109 CASE_I2C(I2C1) :
110 CASE_I2C(I2C2) :
111 CASE_I2C(I2C3) :
112 CASE_I2C(I2C4) :
113 CASE_I2C(I2C5) :
114 CASE_I2C(I2C6) :
115 CASE_I2C(I2C7) :
Lee Leahy77ff0b12015-05-05 15:07:29 -0700116 printk(BIOS_DEBUG, "Releasing I2C device from reset.\n");
117 reg_script_run_on_dev(dev, ops);
118 break;
119 default:
120 return;
121 }
122}
123
Elyes HAOUASb13fac32018-05-24 22:29:44 +0200124static void lpss_init(struct device *dev)
Lee Leahy77ff0b12015-05-05 15:07:29 -0700125{
Kyösti Mälkki8950cfb2019-07-13 22:16:25 +0300126 struct soc_intel_braswell_config *config = config_of(dev);
Lee Leahy77ff0b12015-05-05 15:07:29 -0700127 int iosf_reg, nvs_index;
128
129 dev_ctl_reg(dev, &iosf_reg, &nvs_index);
130
131 if (iosf_reg < 0) {
132 int slot = PCI_SLOT(dev->path.pci.devfn);
133 int func = PCI_FUNC(dev->path.pci.devfn);
Angel Ponsaee7ab22020-03-19 00:31:58 +0100134 printk(BIOS_DEBUG, "Could not find iosf_reg for %02x.%01x\n", slot, func);
Lee Leahy77ff0b12015-05-05 15:07:29 -0700135 return;
136 }
Lee Leahy32471722015-04-20 15:20:28 -0700137
Lee Leahy77ff0b12015-05-05 15:07:29 -0700138 i2c_disable_resets(dev);
139
140 if (config->lpss_acpi_mode)
141 dev_enable_acpi_mode(dev, iosf_reg, nvs_index);
142}
143
144static struct device_operations device_ops = {
145 .read_resources = pci_dev_read_resources,
146 .set_resources = pci_dev_set_resources,
147 .enable_resources = pci_dev_enable_resources,
148 .init = lpss_init,
Lee Leahy77ff0b12015-05-05 15:07:29 -0700149 .ops_pci = &soc_pci_ops,
150};
151
152static const unsigned short pci_device_ids[] = {
153 SIO_DMA1_DEVID,
154 I2C1_DEVID,
155 I2C2_DEVID,
156 I2C3_DEVID,
157 I2C4_DEVID,
158 I2C5_DEVID,
159 I2C6_DEVID,
160 I2C7_DEVID,
161 SIO_DMA2_DEVID,
162 PWM1_DEVID,
163 PWM2_DEVID,
164 HSUART1_DEVID,
165 HSUART2_DEVID,
166 SPI_DEVID,
167 0,
168};
169
170static const struct pci_driver southcluster __pci_driver = {
171 .ops = &device_ops,
172 .vendor = PCI_VENDOR_ID_INTEL,
173 .devices = pci_device_ids,
174};