blob: c1d75e0fa737c6a7c3265bd78f76efe9a5784249 [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[] = {
178 PCI_DEVICE_ID_INTEL_SPT_I2C0,
179 PCI_DEVICE_ID_INTEL_SPT_I2C1,
180 PCI_DEVICE_ID_INTEL_SPT_I2C2,
181 PCI_DEVICE_ID_INTEL_SPT_I2C3,
182 PCI_DEVICE_ID_INTEL_SPT_I2C4,
183 PCI_DEVICE_ID_INTEL_SPT_I2C5,
Angel Ponsf530e362021-04-27 10:20:04 +0200184 PCI_DEVICE_ID_INTEL_UPT_H_I2C0,
185 PCI_DEVICE_ID_INTEL_UPT_H_I2C1,
186 PCI_DEVICE_ID_INTEL_UPT_H_I2C2,
187 PCI_DEVICE_ID_INTEL_UPT_H_I2C3,
Rizwan Qureshiae6a4b62017-04-26 21:06:35 +0530188 PCI_DEVICE_ID_INTEL_APL_I2C0,
189 PCI_DEVICE_ID_INTEL_APL_I2C1,
190 PCI_DEVICE_ID_INTEL_APL_I2C2,
191 PCI_DEVICE_ID_INTEL_APL_I2C3,
192 PCI_DEVICE_ID_INTEL_APL_I2C4,
193 PCI_DEVICE_ID_INTEL_APL_I2C5,
194 PCI_DEVICE_ID_INTEL_APL_I2C6,
195 PCI_DEVICE_ID_INTEL_APL_I2C7,
Lijian Zhaobbedef92017-07-29 16:38:38 -0700196 PCI_DEVICE_ID_INTEL_CNL_I2C0,
197 PCI_DEVICE_ID_INTEL_CNL_I2C1,
198 PCI_DEVICE_ID_INTEL_CNL_I2C2,
199 PCI_DEVICE_ID_INTEL_CNL_I2C3,
200 PCI_DEVICE_ID_INTEL_CNL_I2C4,
201 PCI_DEVICE_ID_INTEL_CNL_I2C5,
Ravi Sarawadi3038e9b2017-05-18 16:00:35 -0700202 PCI_DEVICE_ID_INTEL_GLK_I2C0,
203 PCI_DEVICE_ID_INTEL_GLK_I2C1,
204 PCI_DEVICE_ID_INTEL_GLK_I2C2,
205 PCI_DEVICE_ID_INTEL_GLK_I2C3,
206 PCI_DEVICE_ID_INTEL_GLK_I2C4,
207 PCI_DEVICE_ID_INTEL_GLK_I2C5,
208 PCI_DEVICE_ID_INTEL_GLK_I2C6,
209 PCI_DEVICE_ID_INTEL_GLK_I2C7,
praveen hodagatta praneshe26c4a42018-09-20 03:49:45 +0800210 PCI_DEVICE_ID_INTEL_CNP_H_I2C0,
211 PCI_DEVICE_ID_INTEL_CNP_H_I2C1,
212 PCI_DEVICE_ID_INTEL_CNP_H_I2C2,
213 PCI_DEVICE_ID_INTEL_CNP_H_I2C3,
Aamir Bohra9eac0392018-06-30 12:07:04 +0530214 PCI_DEVICE_ID_INTEL_ICP_I2C0,
215 PCI_DEVICE_ID_INTEL_ICP_I2C1,
216 PCI_DEVICE_ID_INTEL_ICP_I2C2,
217 PCI_DEVICE_ID_INTEL_ICP_I2C3,
218 PCI_DEVICE_ID_INTEL_ICP_I2C4,
219 PCI_DEVICE_ID_INTEL_ICP_I2C5,
Ronak Kanabarda7ffb482019-02-05 01:51:13 +0530220 PCI_DEVICE_ID_INTEL_CMP_I2C0,
221 PCI_DEVICE_ID_INTEL_CMP_I2C1,
222 PCI_DEVICE_ID_INTEL_CMP_I2C2,
223 PCI_DEVICE_ID_INTEL_CMP_I2C3,
224 PCI_DEVICE_ID_INTEL_CMP_I2C4,
225 PCI_DEVICE_ID_INTEL_CMP_I2C5,
Gaggery Tsai12a651c2019-12-05 11:23:20 -0800226 PCI_DEVICE_ID_INTEL_CMP_H_I2C0,
227 PCI_DEVICE_ID_INTEL_CMP_H_I2C1,
228 PCI_DEVICE_ID_INTEL_CMP_H_I2C2,
229 PCI_DEVICE_ID_INTEL_CMP_H_I2C3,
Ravi Sarawadi6b5bf402019-10-21 22:25:04 -0700230 PCI_DEVICE_ID_INTEL_TGP_I2C0,
231 PCI_DEVICE_ID_INTEL_TGP_I2C1,
232 PCI_DEVICE_ID_INTEL_TGP_I2C2,
233 PCI_DEVICE_ID_INTEL_TGP_I2C3,
234 PCI_DEVICE_ID_INTEL_TGP_I2C4,
235 PCI_DEVICE_ID_INTEL_TGP_I2C5,
236 PCI_DEVICE_ID_INTEL_TGP_I2C6,
237 PCI_DEVICE_ID_INTEL_TGP_I2C7,
Jeremy Soller191a8d72021-08-10 14:06:51 -0600238 PCI_DEVICE_ID_INTEL_TGP_H_I2C0,
239 PCI_DEVICE_ID_INTEL_TGP_H_I2C1,
240 PCI_DEVICE_ID_INTEL_TGP_H_I2C2,
241 PCI_DEVICE_ID_INTEL_TGP_H_I2C3,
242 PCI_DEVICE_ID_INTEL_TGP_H_I2C4,
243 PCI_DEVICE_ID_INTEL_TGP_H_I2C5,
244 PCI_DEVICE_ID_INTEL_TGP_H_I2C6,
Tan, Lean Sheng26136092020-01-20 19:13:56 -0800245 PCI_DEVICE_ID_INTEL_MCC_I2C0,
246 PCI_DEVICE_ID_INTEL_MCC_I2C1,
247 PCI_DEVICE_ID_INTEL_MCC_I2C2,
248 PCI_DEVICE_ID_INTEL_MCC_I2C3,
249 PCI_DEVICE_ID_INTEL_MCC_I2C4,
250 PCI_DEVICE_ID_INTEL_MCC_I2C5,
251 PCI_DEVICE_ID_INTEL_MCC_I2C6,
252 PCI_DEVICE_ID_INTEL_MCC_I2C7,
Meera Ravindranath3f4af0d2020-02-12 16:01:22 +0530253 PCI_DEVICE_ID_INTEL_JSP_I2C0,
254 PCI_DEVICE_ID_INTEL_JSP_I2C1,
255 PCI_DEVICE_ID_INTEL_JSP_I2C2,
256 PCI_DEVICE_ID_INTEL_JSP_I2C3,
257 PCI_DEVICE_ID_INTEL_JSP_I2C4,
258 PCI_DEVICE_ID_INTEL_JSP_I2C5,
Subrata Banikf672f7f2020-08-03 14:29:25 +0530259 PCI_DEVICE_ID_INTEL_ADP_P_I2C0,
260 PCI_DEVICE_ID_INTEL_ADP_P_I2C1,
261 PCI_DEVICE_ID_INTEL_ADP_P_I2C2,
262 PCI_DEVICE_ID_INTEL_ADP_P_I2C3,
263 PCI_DEVICE_ID_INTEL_ADP_P_I2C4,
264 PCI_DEVICE_ID_INTEL_ADP_P_I2C5,
Varshit B Pandya339f0e72021-07-14 11:08:23 +0530265 PCI_DEVICE_ID_INTEL_ADP_P_I2C6,
266 PCI_DEVICE_ID_INTEL_ADP_P_I2C7,
Subrata Banikf672f7f2020-08-03 14:29:25 +0530267 PCI_DEVICE_ID_INTEL_ADP_S_I2C0,
268 PCI_DEVICE_ID_INTEL_ADP_S_I2C1,
269 PCI_DEVICE_ID_INTEL_ADP_S_I2C2,
270 PCI_DEVICE_ID_INTEL_ADP_S_I2C3,
271 PCI_DEVICE_ID_INTEL_ADP_S_I2C4,
272 PCI_DEVICE_ID_INTEL_ADP_S_I2C5,
Usha Paf5a9d62022-01-17 20:24:31 +0530273 PCI_DEVICE_ID_INTEL_ADP_M_N_I2C0,
274 PCI_DEVICE_ID_INTEL_ADP_M_N_I2C1,
275 PCI_DEVICE_ID_INTEL_ADP_M_N_I2C2,
276 PCI_DEVICE_ID_INTEL_ADP_M_N_I2C3,
277 PCI_DEVICE_ID_INTEL_ADP_M_N_I2C4,
278 PCI_DEVICE_ID_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,
284 .vendor = PCI_VENDOR_ID_INTEL,
285 .devices = pci_device_ids,
286};
Subrata Banike62836b2018-05-07 16:27:51 +0530287#endif