blob: 70c7e18bac3d6f1abd1eca0f2efa472a9a07b714 [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>
Rizwan Qureshiae6a4b62017-04-26 21:06:35 +05308#include <device/pci_ids.h>
Chris Chingb8dc63b2017-12-06 14:26:15 -07009#include <drivers/i2c/designware/dw_i2c.h>
Kyösti Mälkki32d47eb2019-09-28 00:00:30 +030010#include <intelblocks/cfg.h>
Subrata Banike62836b2018-05-07 16:27:51 +053011#include <intelblocks/lpss.h>
12#include <soc/iomap.h>
13#include <soc/pci_devs.h>
14
Furquan Shaikh00296ea2020-04-24 21:33:02 -070015int dw_i2c_soc_dev_to_bus(const struct device *dev)
Subrata Banike62836b2018-05-07 16:27:51 +053016{
17 pci_devfn_t devfn = dev->path.pci.devfn;
18 return dw_i2c_soc_devfn_to_bus(devfn);
19}
20
21/* Getting I2C bus configuration from devicetree config */
22const struct dw_i2c_bus_config *dw_i2c_get_soc_cfg(unsigned int bus)
23{
24 const struct soc_intel_common_config *common_config;
25 common_config = chip_get_common_soc_structure();
26
27 return &common_config->i2c[bus];
28}
29
30/* Get base address for early init of I2C controllers. */
31uintptr_t dw_i2c_get_soc_early_base(unsigned int bus)
32{
33 return EARLY_I2C_BASE(bus);
34}
35
Subrata Banik42c44c22019-05-15 20:27:04 +053036#if !ENV_PAYLOAD_LOADER
Subrata Banike62836b2018-05-07 16:27:51 +053037static int lpss_i2c_early_init_bus(unsigned int bus)
38{
39 const struct dw_i2c_bus_config *config;
Subrata Banike62836b2018-05-07 16:27:51 +053040 pci_devfn_t dev;
41 int devfn;
42 uintptr_t base;
43
44 /* Find the PCI device for this bus controller */
45 devfn = dw_i2c_soc_bus_to_devfn(bus);
46 if (devfn < 0) {
47 printk(BIOS_ERR, "I2C%u device not found\n", bus);
48 return -1;
49 }
50
51 /* Look up the controller device in the devicetree */
52 dev = PCI_DEV(0, PCI_SLOT(devfn), PCI_FUNC(devfn));
Subrata Banike62836b2018-05-07 16:27:51 +053053
54 /* Skip if not enabled for early init */
55 config = dw_i2c_get_soc_cfg(bus);
56 if (!config || !config->early_init) {
57 printk(BIOS_DEBUG, "I2C%u not enabled for early init\n", bus);
58 return -1;
59 }
60
61 /* Prepare early base address for access before memory */
62 base = dw_i2c_get_soc_early_base(bus);
63 pci_write_config32(dev, PCI_BASE_ADDRESS_0, base);
Elyes HAOUAS2ec1c132020-04-29 09:57:05 +020064 pci_write_config16(dev, PCI_COMMAND,
Subrata Banike62836b2018-05-07 16:27:51 +053065 PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
66
67 /* Take device out of reset */
68 lpss_reset_release(base);
69
Aamir Bohraf5202a62019-07-12 14:37:55 +053070 /* Ensure controller is in D0 state */
Furquan Shaikhfb29ca02021-01-02 00:03:00 -080071 lpss_set_power_state(dev, STATE_D0);
Aamir Bohraf5202a62019-07-12 14:37:55 +053072
Subrata Banike62836b2018-05-07 16:27:51 +053073 /* Initialize the controller */
Felix Held3d945892022-01-31 15:52:36 +010074 if (dw_i2c_init(bus, config) != CB_SUCCESS) {
Subrata Banike62836b2018-05-07 16:27:51 +053075 printk(BIOS_ERR, "I2C%u failed to initialize\n", bus);
76 return -1;
77 }
78
79 return 0;
80}
81
82uintptr_t dw_i2c_base_address(unsigned int bus)
83{
84 int devfn;
85 pci_devfn_t dev;
86 uintptr_t base;
87
88 /* Find device+function for this controller */
89 devfn = dw_i2c_soc_bus_to_devfn(bus);
90 if (devfn < 0)
91 return (uintptr_t)NULL;
92
93 /* Form a PCI address for this device */
94 dev = PCI_DEV(0, PCI_SLOT(devfn), PCI_FUNC(devfn));
95
96 /* Read the first base address for this device */
97 base = ALIGN_DOWN(pci_read_config32(dev, PCI_BASE_ADDRESS_0), 16);
98
99 /* Attempt to initialize bus if base is not set yet */
100 if (!base && !lpss_i2c_early_init_bus(bus))
101 base = ALIGN_DOWN(pci_read_config32(dev, PCI_BASE_ADDRESS_0),
102 16);
103 return base;
104}
105#else
Rizwan Qureshiae6a4b62017-04-26 21:06:35 +0530106
Chris Chingb8dc63b2017-12-06 14:26:15 -0700107uintptr_t dw_i2c_base_address(unsigned int bus)
Rizwan Qureshiae6a4b62017-04-26 21:06:35 +0530108{
109 int devfn;
110 struct device *dev;
111 struct resource *res;
112
113 /* bus -> devfn */
Aaron Durbin9aee8192018-01-22 20:29:25 -0700114 devfn = dw_i2c_soc_bus_to_devfn(bus);
Rizwan Qureshiae6a4b62017-04-26 21:06:35 +0530115
116 if (devfn < 0)
117 return (uintptr_t)NULL;
118
119 /* devfn -> dev */
Kyösti Mälkkie7377552018-06-21 16:20:55 +0300120 dev = pcidev_path_on_root(devfn);
Furquan Shaikhd629e4332017-06-09 17:54:00 -0700121 if (!dev || !dev->enabled)
Rizwan Qureshiae6a4b62017-04-26 21:06:35 +0530122 return (uintptr_t)NULL;
123
124 /* dev -> bar0 */
Angel Ponsc1bfbe02021-11-03 13:18:53 +0100125 res = probe_resource(dev, PCI_BASE_ADDRESS_0);
Rizwan Qureshiae6a4b62017-04-26 21:06:35 +0530126 if (res)
127 return res->base;
128
Tim Wawrzynczak7a91a102022-02-08 12:50:46 -0700129 /* No resource found yet, it's possible this is running in the
130 * PAYLOAD_LOADER stage before resources have been assigned yet,
131 * therefore, any early init BAR should still be valid. */
132
133 /* Read the first base address for this device */
134 return (uintptr_t)ALIGN_DOWN(pci_read_config32(dev, PCI_BASE_ADDRESS_0), 16);
Rizwan Qureshiae6a4b62017-04-26 21:06:35 +0530135}
136
Subrata Banik7d8c0c22018-09-27 19:27:39 +0530137/*
138 * This function ensures that the device is actually out of reset and
139 * its ready for initialization sequence.
140 */
141static void dw_i2c_device_init(struct device *dev)
142{
143 uintptr_t base_address;
144 int bus = dw_i2c_soc_dev_to_bus(dev);
145
146 if (bus < 0)
147 return;
148
149 base_address = dw_i2c_base_address(bus);
150 if (!base_address)
151 return;
152
Aamir Bohraf5202a62019-07-12 14:37:55 +0530153 /* Ensure controller is in D0 state */
Furquan Shaikhfb29ca02021-01-02 00:03:00 -0800154 lpss_set_power_state(PCI_BDF(dev), STATE_D0);
Aamir Bohraf5202a62019-07-12 14:37:55 +0530155
Subrata Banik7d8c0c22018-09-27 19:27:39 +0530156 /* Take device out of reset if its not done before */
157 if (lpss_is_controller_in_reset(base_address))
158 lpss_reset_release(base_address);
159
160 dw_i2c_dev_init(dev);
161}
162
Nico Huber57686192022-08-06 19:11:55 +0200163struct device_operations i2c_dev_ops = {
Nico Huber68680dd2020-03-31 17:34:52 +0200164 .read_resources = pci_dev_read_resources,
165 .set_resources = pci_dev_set_resources,
166 .enable_resources = pci_dev_enable_resources,
Karthikeyan Ramasubramanian7524b5e2020-10-02 00:35:14 -0600167 .scan_bus = scan_static_bus,
Nico Huber68680dd2020-03-31 17:34:52 +0200168 .ops_i2c_bus = &dw_i2c_bus_ops,
169 .ops_pci = &pci_dev_ops_pci,
170 .init = dw_i2c_device_init,
Karthikeyan Ramasubramanian0e971e12020-01-09 11:32:16 -0700171#if CONFIG(HAVE_ACPI_TABLES)
Nico Huber68680dd2020-03-31 17:34:52 +0200172 .acpi_fill_ssdt = dw_i2c_acpi_fill_ssdt,
Karthikeyan Ramasubramanian0e971e12020-01-09 11:32:16 -0700173#endif
Rizwan Qureshiae6a4b62017-04-26 21:06:35 +0530174};
175
176static const unsigned short pci_device_ids[] = {
Wonkyu Kim9f401072020-11-13 15:16:32 -0800177 PCI_DID_INTEL_MTL_I2C0,
178 PCI_DID_INTEL_MTL_I2C1,
179 PCI_DID_INTEL_MTL_I2C2,
180 PCI_DID_INTEL_MTL_I2C3,
181 PCI_DID_INTEL_MTL_I2C4,
182 PCI_DID_INTEL_MTL_I2C5,
Felix Singer43b7f412022-03-07 04:34:52 +0100183 PCI_DID_INTEL_APL_I2C0,
184 PCI_DID_INTEL_APL_I2C1,
185 PCI_DID_INTEL_APL_I2C2,
186 PCI_DID_INTEL_APL_I2C3,
187 PCI_DID_INTEL_APL_I2C4,
188 PCI_DID_INTEL_APL_I2C5,
189 PCI_DID_INTEL_APL_I2C6,
190 PCI_DID_INTEL_APL_I2C7,
191 PCI_DID_INTEL_CNL_I2C0,
192 PCI_DID_INTEL_CNL_I2C1,
193 PCI_DID_INTEL_CNL_I2C2,
194 PCI_DID_INTEL_CNL_I2C3,
195 PCI_DID_INTEL_CNL_I2C4,
196 PCI_DID_INTEL_CNL_I2C5,
197 PCI_DID_INTEL_GLK_I2C0,
198 PCI_DID_INTEL_GLK_I2C1,
199 PCI_DID_INTEL_GLK_I2C2,
200 PCI_DID_INTEL_GLK_I2C3,
201 PCI_DID_INTEL_GLK_I2C4,
202 PCI_DID_INTEL_GLK_I2C5,
203 PCI_DID_INTEL_GLK_I2C6,
204 PCI_DID_INTEL_GLK_I2C7,
205 PCI_DID_INTEL_CNP_H_I2C0,
206 PCI_DID_INTEL_CNP_H_I2C1,
207 PCI_DID_INTEL_CNP_H_I2C2,
208 PCI_DID_INTEL_CNP_H_I2C3,
209 PCI_DID_INTEL_ICP_I2C0,
210 PCI_DID_INTEL_ICP_I2C1,
211 PCI_DID_INTEL_ICP_I2C2,
212 PCI_DID_INTEL_ICP_I2C3,
213 PCI_DID_INTEL_ICP_I2C4,
214 PCI_DID_INTEL_ICP_I2C5,
215 PCI_DID_INTEL_CMP_I2C0,
216 PCI_DID_INTEL_CMP_I2C1,
217 PCI_DID_INTEL_CMP_I2C2,
218 PCI_DID_INTEL_CMP_I2C3,
219 PCI_DID_INTEL_CMP_I2C4,
220 PCI_DID_INTEL_CMP_I2C5,
221 PCI_DID_INTEL_CMP_H_I2C0,
222 PCI_DID_INTEL_CMP_H_I2C1,
223 PCI_DID_INTEL_CMP_H_I2C2,
224 PCI_DID_INTEL_CMP_H_I2C3,
225 PCI_DID_INTEL_TGP_I2C0,
226 PCI_DID_INTEL_TGP_I2C1,
227 PCI_DID_INTEL_TGP_I2C2,
228 PCI_DID_INTEL_TGP_I2C3,
229 PCI_DID_INTEL_TGP_I2C4,
230 PCI_DID_INTEL_TGP_I2C5,
231 PCI_DID_INTEL_TGP_I2C6,
232 PCI_DID_INTEL_TGP_I2C7,
233 PCI_DID_INTEL_TGP_H_I2C0,
234 PCI_DID_INTEL_TGP_H_I2C1,
235 PCI_DID_INTEL_TGP_H_I2C2,
236 PCI_DID_INTEL_TGP_H_I2C3,
237 PCI_DID_INTEL_TGP_H_I2C4,
238 PCI_DID_INTEL_TGP_H_I2C5,
239 PCI_DID_INTEL_TGP_H_I2C6,
240 PCI_DID_INTEL_MCC_I2C0,
241 PCI_DID_INTEL_MCC_I2C1,
242 PCI_DID_INTEL_MCC_I2C2,
243 PCI_DID_INTEL_MCC_I2C3,
244 PCI_DID_INTEL_MCC_I2C4,
245 PCI_DID_INTEL_MCC_I2C5,
246 PCI_DID_INTEL_MCC_I2C6,
247 PCI_DID_INTEL_MCC_I2C7,
248 PCI_DID_INTEL_JSP_I2C0,
249 PCI_DID_INTEL_JSP_I2C1,
250 PCI_DID_INTEL_JSP_I2C2,
251 PCI_DID_INTEL_JSP_I2C3,
252 PCI_DID_INTEL_JSP_I2C4,
253 PCI_DID_INTEL_JSP_I2C5,
254 PCI_DID_INTEL_ADP_P_I2C0,
255 PCI_DID_INTEL_ADP_P_I2C1,
256 PCI_DID_INTEL_ADP_P_I2C2,
257 PCI_DID_INTEL_ADP_P_I2C3,
258 PCI_DID_INTEL_ADP_P_I2C4,
259 PCI_DID_INTEL_ADP_P_I2C5,
260 PCI_DID_INTEL_ADP_P_I2C6,
261 PCI_DID_INTEL_ADP_P_I2C7,
262 PCI_DID_INTEL_ADP_S_I2C0,
263 PCI_DID_INTEL_ADP_S_I2C1,
264 PCI_DID_INTEL_ADP_S_I2C2,
265 PCI_DID_INTEL_ADP_S_I2C3,
266 PCI_DID_INTEL_ADP_S_I2C4,
267 PCI_DID_INTEL_ADP_S_I2C5,
268 PCI_DID_INTEL_ADP_M_N_I2C0,
269 PCI_DID_INTEL_ADP_M_N_I2C1,
270 PCI_DID_INTEL_ADP_M_N_I2C2,
271 PCI_DID_INTEL_ADP_M_N_I2C3,
272 PCI_DID_INTEL_ADP_M_N_I2C4,
273 PCI_DID_INTEL_ADP_M_N_I2C5,
Ravi Sarawadi3038e9b2017-05-18 16:00:35 -0700274 0,
Rizwan Qureshiae6a4b62017-04-26 21:06:35 +0530275};
276
277static const struct pci_driver pch_i2c __pci_driver = {
278 .ops = &i2c_dev_ops,
Felix Singer43b7f412022-03-07 04:34:52 +0100279 .vendor = PCI_VID_INTEL,
Rizwan Qureshiae6a4b62017-04-26 21:06:35 +0530280 .devices = pci_device_ids,
281};
Subrata Banike62836b2018-05-07 16:27:51 +0530282#endif