blob: ba10b2c5bb48d3489e86ce0bc63a38f41dd11dd5 [file] [log] [blame]
Angel Pons0612b272020-04-05 15:46:56 +02001/* SPDX-License-Identifier: GPL-2.0-only */
Rizwan Qureshiae6a4b62017-04-26 21:06:35 +05302
Kyösti Mälkkif1b58b72019-03-01 13:43:02 +02003#include <device/pci_ops.h>
Subrata Banike62836b2018-05-07 16:27:51 +05304#include <console/console.h>
5#include <device/device.h>
6#include <device/i2c_simple.h>
Rizwan Qureshiae6a4b62017-04-26 21:06:35 +05307#include <device/pci.h>
8#include <device/pci_def.h>
9#include <device/pci_ids.h>
Chris Chingb8dc63b2017-12-06 14:26:15 -070010#include <drivers/i2c/designware/dw_i2c.h>
Kyösti Mälkki32d47eb2019-09-28 00:00:30 +030011#include <intelblocks/cfg.h>
Subrata Banike62836b2018-05-07 16:27:51 +053012#include <intelblocks/lpss.h>
13#include <soc/iomap.h>
14#include <soc/pci_devs.h>
15
Furquan Shaikh00296ea2020-04-24 21:33:02 -070016int dw_i2c_soc_dev_to_bus(const struct device *dev)
Subrata Banike62836b2018-05-07 16:27:51 +053017{
18 pci_devfn_t devfn = dev->path.pci.devfn;
19 return dw_i2c_soc_devfn_to_bus(devfn);
20}
21
22/* Getting I2C bus configuration from devicetree config */
23const struct dw_i2c_bus_config *dw_i2c_get_soc_cfg(unsigned int bus)
24{
25 const struct soc_intel_common_config *common_config;
26 common_config = chip_get_common_soc_structure();
27
28 return &common_config->i2c[bus];
29}
30
31/* Get base address for early init of I2C controllers. */
32uintptr_t dw_i2c_get_soc_early_base(unsigned int bus)
33{
34 return EARLY_I2C_BASE(bus);
35}
36
Subrata Banik42c44c22019-05-15 20:27:04 +053037#if !ENV_PAYLOAD_LOADER
Subrata Banike62836b2018-05-07 16:27:51 +053038static int lpss_i2c_early_init_bus(unsigned int bus)
39{
40 const struct dw_i2c_bus_config *config;
Subrata Banike62836b2018-05-07 16:27:51 +053041 pci_devfn_t dev;
42 int devfn;
43 uintptr_t base;
44
45 /* Find the PCI device for this bus controller */
46 devfn = dw_i2c_soc_bus_to_devfn(bus);
47 if (devfn < 0) {
48 printk(BIOS_ERR, "I2C%u device not found\n", bus);
49 return -1;
50 }
51
52 /* Look up the controller device in the devicetree */
53 dev = PCI_DEV(0, PCI_SLOT(devfn), PCI_FUNC(devfn));
Subrata Banike62836b2018-05-07 16:27:51 +053054
55 /* Skip if not enabled for early init */
56 config = dw_i2c_get_soc_cfg(bus);
57 if (!config || !config->early_init) {
58 printk(BIOS_DEBUG, "I2C%u not enabled for early init\n", bus);
59 return -1;
60 }
61
62 /* Prepare early base address for access before memory */
63 base = dw_i2c_get_soc_early_base(bus);
64 pci_write_config32(dev, PCI_BASE_ADDRESS_0, base);
Elyes HAOUAS2ec1c132020-04-29 09:57:05 +020065 pci_write_config16(dev, PCI_COMMAND,
Subrata Banike62836b2018-05-07 16:27:51 +053066 PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
67
68 /* Take device out of reset */
69 lpss_reset_release(base);
70
Aamir Bohraf5202a62019-07-12 14:37:55 +053071 /* Ensure controller is in D0 state */
Furquan Shaikhfb29ca02021-01-02 00:03:00 -080072 lpss_set_power_state(dev, STATE_D0);
Aamir Bohraf5202a62019-07-12 14:37:55 +053073
Subrata Banike62836b2018-05-07 16:27:51 +053074 /* Initialize the controller */
Felix Held3d945892022-01-31 15:52:36 +010075 if (dw_i2c_init(bus, config) != CB_SUCCESS) {
Subrata Banike62836b2018-05-07 16:27:51 +053076 printk(BIOS_ERR, "I2C%u failed to initialize\n", bus);
77 return -1;
78 }
79
80 return 0;
81}
82
83uintptr_t dw_i2c_base_address(unsigned int bus)
84{
85 int devfn;
86 pci_devfn_t dev;
87 uintptr_t base;
88
89 /* Find device+function for this controller */
90 devfn = dw_i2c_soc_bus_to_devfn(bus);
91 if (devfn < 0)
92 return (uintptr_t)NULL;
93
94 /* Form a PCI address for this device */
95 dev = PCI_DEV(0, PCI_SLOT(devfn), PCI_FUNC(devfn));
96
97 /* Read the first base address for this device */
98 base = ALIGN_DOWN(pci_read_config32(dev, PCI_BASE_ADDRESS_0), 16);
99
100 /* Attempt to initialize bus if base is not set yet */
101 if (!base && !lpss_i2c_early_init_bus(bus))
102 base = ALIGN_DOWN(pci_read_config32(dev, PCI_BASE_ADDRESS_0),
103 16);
104 return base;
105}
106#else
Rizwan Qureshiae6a4b62017-04-26 21:06:35 +0530107
Chris Chingb8dc63b2017-12-06 14:26:15 -0700108uintptr_t dw_i2c_base_address(unsigned int bus)
Rizwan Qureshiae6a4b62017-04-26 21:06:35 +0530109{
110 int devfn;
111 struct device *dev;
112 struct resource *res;
113
114 /* bus -> devfn */
Aaron Durbin9aee8192018-01-22 20:29:25 -0700115 devfn = dw_i2c_soc_bus_to_devfn(bus);
Rizwan Qureshiae6a4b62017-04-26 21:06:35 +0530116
117 if (devfn < 0)
118 return (uintptr_t)NULL;
119
120 /* devfn -> dev */
Kyösti Mälkkie7377552018-06-21 16:20:55 +0300121 dev = pcidev_path_on_root(devfn);
Furquan Shaikhd629e4332017-06-09 17:54:00 -0700122 if (!dev || !dev->enabled)
Rizwan Qureshiae6a4b62017-04-26 21:06:35 +0530123 return (uintptr_t)NULL;
124
125 /* dev -> bar0 */
Angel Ponsc1bfbe02021-11-03 13:18:53 +0100126 res = probe_resource(dev, PCI_BASE_ADDRESS_0);
Rizwan Qureshiae6a4b62017-04-26 21:06:35 +0530127 if (res)
128 return res->base;
129
Tim Wawrzynczak7a91a102022-02-08 12:50:46 -0700130 /* No resource found yet, it's possible this is running in the
131 * PAYLOAD_LOADER stage before resources have been assigned yet,
132 * therefore, any early init BAR should still be valid. */
133
134 /* Read the first base address for this device */
135 return (uintptr_t)ALIGN_DOWN(pci_read_config32(dev, PCI_BASE_ADDRESS_0), 16);
Rizwan Qureshiae6a4b62017-04-26 21:06:35 +0530136}
137
Subrata Banik7d8c0c22018-09-27 19:27:39 +0530138/*
139 * This function ensures that the device is actually out of reset and
140 * its ready for initialization sequence.
141 */
142static void dw_i2c_device_init(struct device *dev)
143{
144 uintptr_t base_address;
145 int bus = dw_i2c_soc_dev_to_bus(dev);
146
147 if (bus < 0)
148 return;
149
150 base_address = dw_i2c_base_address(bus);
151 if (!base_address)
152 return;
153
Aamir Bohraf5202a62019-07-12 14:37:55 +0530154 /* Ensure controller is in D0 state */
Furquan Shaikhfb29ca02021-01-02 00:03:00 -0800155 lpss_set_power_state(PCI_BDF(dev), STATE_D0);
Aamir Bohraf5202a62019-07-12 14:37:55 +0530156
Subrata Banik7d8c0c22018-09-27 19:27:39 +0530157 /* Take device out of reset if its not done before */
158 if (lpss_is_controller_in_reset(base_address))
159 lpss_reset_release(base_address);
160
161 dw_i2c_dev_init(dev);
162}
163
Rizwan Qureshiae6a4b62017-04-26 21:06:35 +0530164static struct device_operations i2c_dev_ops = {
Nico Huber68680dd2020-03-31 17:34:52 +0200165 .read_resources = pci_dev_read_resources,
166 .set_resources = pci_dev_set_resources,
167 .enable_resources = pci_dev_enable_resources,
Karthikeyan Ramasubramanian7524b5e2020-10-02 00:35:14 -0600168 .scan_bus = scan_static_bus,
Nico Huber68680dd2020-03-31 17:34:52 +0200169 .ops_i2c_bus = &dw_i2c_bus_ops,
170 .ops_pci = &pci_dev_ops_pci,
171 .init = dw_i2c_device_init,
Karthikeyan Ramasubramanian0e971e12020-01-09 11:32:16 -0700172#if CONFIG(HAVE_ACPI_TABLES)
Nico Huber68680dd2020-03-31 17:34:52 +0200173 .acpi_fill_ssdt = dw_i2c_acpi_fill_ssdt,
Karthikeyan Ramasubramanian0e971e12020-01-09 11:32:16 -0700174#endif
Rizwan Qureshiae6a4b62017-04-26 21:06:35 +0530175};
176
177static const unsigned short pci_device_ids[] = {
Felix Singer43b7f412022-03-07 04:34:52 +0100178 PCI_DID_INTEL_SPT_I2C0,
179 PCI_DID_INTEL_SPT_I2C1,
180 PCI_DID_INTEL_SPT_I2C2,
181 PCI_DID_INTEL_SPT_I2C3,
182 PCI_DID_INTEL_SPT_I2C4,
183 PCI_DID_INTEL_SPT_I2C5,
184 PCI_DID_INTEL_UPT_H_I2C0,
185 PCI_DID_INTEL_UPT_H_I2C1,
186 PCI_DID_INTEL_UPT_H_I2C2,
187 PCI_DID_INTEL_UPT_H_I2C3,
188 PCI_DID_INTEL_APL_I2C0,
189 PCI_DID_INTEL_APL_I2C1,
190 PCI_DID_INTEL_APL_I2C2,
191 PCI_DID_INTEL_APL_I2C3,
192 PCI_DID_INTEL_APL_I2C4,
193 PCI_DID_INTEL_APL_I2C5,
194 PCI_DID_INTEL_APL_I2C6,
195 PCI_DID_INTEL_APL_I2C7,
196 PCI_DID_INTEL_CNL_I2C0,
197 PCI_DID_INTEL_CNL_I2C1,
198 PCI_DID_INTEL_CNL_I2C2,
199 PCI_DID_INTEL_CNL_I2C3,
200 PCI_DID_INTEL_CNL_I2C4,
201 PCI_DID_INTEL_CNL_I2C5,
202 PCI_DID_INTEL_GLK_I2C0,
203 PCI_DID_INTEL_GLK_I2C1,
204 PCI_DID_INTEL_GLK_I2C2,
205 PCI_DID_INTEL_GLK_I2C3,
206 PCI_DID_INTEL_GLK_I2C4,
207 PCI_DID_INTEL_GLK_I2C5,
208 PCI_DID_INTEL_GLK_I2C6,
209 PCI_DID_INTEL_GLK_I2C7,
210 PCI_DID_INTEL_CNP_H_I2C0,
211 PCI_DID_INTEL_CNP_H_I2C1,
212 PCI_DID_INTEL_CNP_H_I2C2,
213 PCI_DID_INTEL_CNP_H_I2C3,
214 PCI_DID_INTEL_ICP_I2C0,
215 PCI_DID_INTEL_ICP_I2C1,
216 PCI_DID_INTEL_ICP_I2C2,
217 PCI_DID_INTEL_ICP_I2C3,
218 PCI_DID_INTEL_ICP_I2C4,
219 PCI_DID_INTEL_ICP_I2C5,
220 PCI_DID_INTEL_CMP_I2C0,
221 PCI_DID_INTEL_CMP_I2C1,
222 PCI_DID_INTEL_CMP_I2C2,
223 PCI_DID_INTEL_CMP_I2C3,
224 PCI_DID_INTEL_CMP_I2C4,
225 PCI_DID_INTEL_CMP_I2C5,
226 PCI_DID_INTEL_CMP_H_I2C0,
227 PCI_DID_INTEL_CMP_H_I2C1,
228 PCI_DID_INTEL_CMP_H_I2C2,
229 PCI_DID_INTEL_CMP_H_I2C3,
230 PCI_DID_INTEL_TGP_I2C0,
231 PCI_DID_INTEL_TGP_I2C1,
232 PCI_DID_INTEL_TGP_I2C2,
233 PCI_DID_INTEL_TGP_I2C3,
234 PCI_DID_INTEL_TGP_I2C4,
235 PCI_DID_INTEL_TGP_I2C5,
236 PCI_DID_INTEL_TGP_I2C6,
237 PCI_DID_INTEL_TGP_I2C7,
238 PCI_DID_INTEL_TGP_H_I2C0,
239 PCI_DID_INTEL_TGP_H_I2C1,
240 PCI_DID_INTEL_TGP_H_I2C2,
241 PCI_DID_INTEL_TGP_H_I2C3,
242 PCI_DID_INTEL_TGP_H_I2C4,
243 PCI_DID_INTEL_TGP_H_I2C5,
244 PCI_DID_INTEL_TGP_H_I2C6,
245 PCI_DID_INTEL_MCC_I2C0,
246 PCI_DID_INTEL_MCC_I2C1,
247 PCI_DID_INTEL_MCC_I2C2,
248 PCI_DID_INTEL_MCC_I2C3,
249 PCI_DID_INTEL_MCC_I2C4,
250 PCI_DID_INTEL_MCC_I2C5,
251 PCI_DID_INTEL_MCC_I2C6,
252 PCI_DID_INTEL_MCC_I2C7,
253 PCI_DID_INTEL_JSP_I2C0,
254 PCI_DID_INTEL_JSP_I2C1,
255 PCI_DID_INTEL_JSP_I2C2,
256 PCI_DID_INTEL_JSP_I2C3,
257 PCI_DID_INTEL_JSP_I2C4,
258 PCI_DID_INTEL_JSP_I2C5,
259 PCI_DID_INTEL_ADP_P_I2C0,
260 PCI_DID_INTEL_ADP_P_I2C1,
261 PCI_DID_INTEL_ADP_P_I2C2,
262 PCI_DID_INTEL_ADP_P_I2C3,
263 PCI_DID_INTEL_ADP_P_I2C4,
264 PCI_DID_INTEL_ADP_P_I2C5,
265 PCI_DID_INTEL_ADP_P_I2C6,
266 PCI_DID_INTEL_ADP_P_I2C7,
267 PCI_DID_INTEL_ADP_S_I2C0,
268 PCI_DID_INTEL_ADP_S_I2C1,
269 PCI_DID_INTEL_ADP_S_I2C2,
270 PCI_DID_INTEL_ADP_S_I2C3,
271 PCI_DID_INTEL_ADP_S_I2C4,
272 PCI_DID_INTEL_ADP_S_I2C5,
273 PCI_DID_INTEL_ADP_M_N_I2C0,
274 PCI_DID_INTEL_ADP_M_N_I2C1,
275 PCI_DID_INTEL_ADP_M_N_I2C2,
276 PCI_DID_INTEL_ADP_M_N_I2C3,
277 PCI_DID_INTEL_ADP_M_N_I2C4,
278 PCI_DID_INTEL_ADP_M_N_I2C5,
Ravi Sarawadi3038e9b2017-05-18 16:00:35 -0700279 0,
Rizwan Qureshiae6a4b62017-04-26 21:06:35 +0530280};
281
282static const struct pci_driver pch_i2c __pci_driver = {
283 .ops = &i2c_dev_ops,
Felix Singer43b7f412022-03-07 04:34:52 +0100284 .vendor = PCI_VID_INTEL,
Rizwan Qureshiae6a4b62017-04-26 21:06:35 +0530285 .devices = pci_device_ids,
286};
Subrata Banike62836b2018-05-07 16:27:51 +0530287#endif