blob: 5aa7729613aa4ad590d190b42f76f647603aa08f [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;
41 const struct device *tree_dev;
42 pci_devfn_t dev;
43 int devfn;
44 uintptr_t base;
45
46 /* Find the PCI device for this bus controller */
47 devfn = dw_i2c_soc_bus_to_devfn(bus);
48 if (devfn < 0) {
49 printk(BIOS_ERR, "I2C%u device not found\n", bus);
50 return -1;
51 }
52
53 /* Look up the controller device in the devicetree */
54 dev = PCI_DEV(0, PCI_SLOT(devfn), PCI_FUNC(devfn));
Kyösti Mälkkie7377552018-06-21 16:20:55 +030055 tree_dev = pcidev_path_on_root(devfn);
Subrata Banike62836b2018-05-07 16:27:51 +053056 if (!tree_dev || !tree_dev->enabled) {
57 printk(BIOS_ERR, "I2C%u device not enabled\n", bus);
58 return -1;
59 }
60
61 /* Skip if not enabled for early init */
62 config = dw_i2c_get_soc_cfg(bus);
63 if (!config || !config->early_init) {
64 printk(BIOS_DEBUG, "I2C%u not enabled for early init\n", bus);
65 return -1;
66 }
67
68 /* Prepare early base address for access before memory */
69 base = dw_i2c_get_soc_early_base(bus);
70 pci_write_config32(dev, PCI_BASE_ADDRESS_0, base);
Elyes HAOUAS2ec1c132020-04-29 09:57:05 +020071 pci_write_config16(dev, PCI_COMMAND,
Subrata Banike62836b2018-05-07 16:27:51 +053072 PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
73
74 /* Take device out of reset */
75 lpss_reset_release(base);
76
Aamir Bohraf5202a62019-07-12 14:37:55 +053077 /* Ensure controller is in D0 state */
78 lpss_set_power_state(tree_dev, STATE_D0);
79
Subrata Banike62836b2018-05-07 16:27:51 +053080 /* Initialize the controller */
81 if (dw_i2c_init(bus, config) < 0) {
82 printk(BIOS_ERR, "I2C%u failed to initialize\n", bus);
83 return -1;
84 }
85
86 return 0;
87}
88
89uintptr_t dw_i2c_base_address(unsigned int bus)
90{
91 int devfn;
92 pci_devfn_t dev;
93 uintptr_t base;
94
95 /* Find device+function for this controller */
96 devfn = dw_i2c_soc_bus_to_devfn(bus);
97 if (devfn < 0)
98 return (uintptr_t)NULL;
99
100 /* Form a PCI address for this device */
101 dev = PCI_DEV(0, PCI_SLOT(devfn), PCI_FUNC(devfn));
102
103 /* Read the first base address for this device */
104 base = ALIGN_DOWN(pci_read_config32(dev, PCI_BASE_ADDRESS_0), 16);
105
106 /* Attempt to initialize bus if base is not set yet */
107 if (!base && !lpss_i2c_early_init_bus(bus))
108 base = ALIGN_DOWN(pci_read_config32(dev, PCI_BASE_ADDRESS_0),
109 16);
110 return base;
111}
112#else
Rizwan Qureshiae6a4b62017-04-26 21:06:35 +0530113
Chris Chingb8dc63b2017-12-06 14:26:15 -0700114uintptr_t dw_i2c_base_address(unsigned int bus)
Rizwan Qureshiae6a4b62017-04-26 21:06:35 +0530115{
116 int devfn;
117 struct device *dev;
118 struct resource *res;
119
120 /* bus -> devfn */
Aaron Durbin9aee8192018-01-22 20:29:25 -0700121 devfn = dw_i2c_soc_bus_to_devfn(bus);
Rizwan Qureshiae6a4b62017-04-26 21:06:35 +0530122
123 if (devfn < 0)
124 return (uintptr_t)NULL;
125
126 /* devfn -> dev */
Kyösti Mälkkie7377552018-06-21 16:20:55 +0300127 dev = pcidev_path_on_root(devfn);
Furquan Shaikhd629e4332017-06-09 17:54:00 -0700128 if (!dev || !dev->enabled)
Rizwan Qureshiae6a4b62017-04-26 21:06:35 +0530129 return (uintptr_t)NULL;
130
131 /* dev -> bar0 */
132 res = find_resource(dev, PCI_BASE_ADDRESS_0);
133 if (res)
134 return res->base;
135
136 return (uintptr_t)NULL;
137}
138
Subrata Banik7d8c0c22018-09-27 19:27:39 +0530139/*
140 * This function ensures that the device is actually out of reset and
141 * its ready for initialization sequence.
142 */
143static void dw_i2c_device_init(struct device *dev)
144{
145 uintptr_t base_address;
146 int bus = dw_i2c_soc_dev_to_bus(dev);
147
148 if (bus < 0)
149 return;
150
151 base_address = dw_i2c_base_address(bus);
152 if (!base_address)
153 return;
154
Aamir Bohraf5202a62019-07-12 14:37:55 +0530155 /* Ensure controller is in D0 state */
156 lpss_set_power_state(dev, STATE_D0);
157
Subrata Banik7d8c0c22018-09-27 19:27:39 +0530158 /* Take device out of reset if its not done before */
159 if (lpss_is_controller_in_reset(base_address))
160 lpss_reset_release(base_address);
161
162 dw_i2c_dev_init(dev);
163}
164
Rizwan Qureshiae6a4b62017-04-26 21:06:35 +0530165static struct device_operations i2c_dev_ops = {
Nico Huber68680dd2020-03-31 17:34:52 +0200166 .read_resources = pci_dev_read_resources,
167 .set_resources = pci_dev_set_resources,
168 .enable_resources = pci_dev_enable_resources,
Karthikeyan Ramasubramanian7524b5e2020-10-02 00:35:14 -0600169 .scan_bus = scan_static_bus,
Nico Huber68680dd2020-03-31 17:34:52 +0200170 .ops_i2c_bus = &dw_i2c_bus_ops,
171 .ops_pci = &pci_dev_ops_pci,
172 .init = dw_i2c_device_init,
Karthikeyan Ramasubramanian0e971e12020-01-09 11:32:16 -0700173#if CONFIG(HAVE_ACPI_TABLES)
Nico Huber68680dd2020-03-31 17:34:52 +0200174 .acpi_fill_ssdt = dw_i2c_acpi_fill_ssdt,
Karthikeyan Ramasubramanian0e971e12020-01-09 11:32:16 -0700175#endif
Rizwan Qureshiae6a4b62017-04-26 21:06:35 +0530176};
177
178static const unsigned short pci_device_ids[] = {
179 PCI_DEVICE_ID_INTEL_SPT_I2C0,
180 PCI_DEVICE_ID_INTEL_SPT_I2C1,
181 PCI_DEVICE_ID_INTEL_SPT_I2C2,
182 PCI_DEVICE_ID_INTEL_SPT_I2C3,
183 PCI_DEVICE_ID_INTEL_SPT_I2C4,
184 PCI_DEVICE_ID_INTEL_SPT_I2C5,
V Sowmyaacc2a482018-01-23 15:27:23 +0530185 PCI_DEVICE_ID_INTEL_KBP_H_I2C0,
186 PCI_DEVICE_ID_INTEL_KBP_H_I2C1,
187 PCI_DEVICE_ID_INTEL_KBP_H_I2C2,
188 PCI_DEVICE_ID_INTEL_KBP_H_I2C3,
Rizwan Qureshiae6a4b62017-04-26 21:06:35 +0530189 PCI_DEVICE_ID_INTEL_APL_I2C0,
190 PCI_DEVICE_ID_INTEL_APL_I2C1,
191 PCI_DEVICE_ID_INTEL_APL_I2C2,
192 PCI_DEVICE_ID_INTEL_APL_I2C3,
193 PCI_DEVICE_ID_INTEL_APL_I2C4,
194 PCI_DEVICE_ID_INTEL_APL_I2C5,
195 PCI_DEVICE_ID_INTEL_APL_I2C6,
196 PCI_DEVICE_ID_INTEL_APL_I2C7,
Lijian Zhaobbedef92017-07-29 16:38:38 -0700197 PCI_DEVICE_ID_INTEL_CNL_I2C0,
198 PCI_DEVICE_ID_INTEL_CNL_I2C1,
199 PCI_DEVICE_ID_INTEL_CNL_I2C2,
200 PCI_DEVICE_ID_INTEL_CNL_I2C3,
201 PCI_DEVICE_ID_INTEL_CNL_I2C4,
202 PCI_DEVICE_ID_INTEL_CNL_I2C5,
Ravi Sarawadi3038e9b2017-05-18 16:00:35 -0700203 PCI_DEVICE_ID_INTEL_GLK_I2C0,
204 PCI_DEVICE_ID_INTEL_GLK_I2C1,
205 PCI_DEVICE_ID_INTEL_GLK_I2C2,
206 PCI_DEVICE_ID_INTEL_GLK_I2C3,
207 PCI_DEVICE_ID_INTEL_GLK_I2C4,
208 PCI_DEVICE_ID_INTEL_GLK_I2C5,
209 PCI_DEVICE_ID_INTEL_GLK_I2C6,
210 PCI_DEVICE_ID_INTEL_GLK_I2C7,
praveen hodagatta praneshe26c4a42018-09-20 03:49:45 +0800211 PCI_DEVICE_ID_INTEL_CNP_H_I2C0,
212 PCI_DEVICE_ID_INTEL_CNP_H_I2C1,
213 PCI_DEVICE_ID_INTEL_CNP_H_I2C2,
214 PCI_DEVICE_ID_INTEL_CNP_H_I2C3,
Aamir Bohra9eac0392018-06-30 12:07:04 +0530215 PCI_DEVICE_ID_INTEL_ICP_I2C0,
216 PCI_DEVICE_ID_INTEL_ICP_I2C1,
217 PCI_DEVICE_ID_INTEL_ICP_I2C2,
218 PCI_DEVICE_ID_INTEL_ICP_I2C3,
219 PCI_DEVICE_ID_INTEL_ICP_I2C4,
220 PCI_DEVICE_ID_INTEL_ICP_I2C5,
Ronak Kanabarda7ffb482019-02-05 01:51:13 +0530221 PCI_DEVICE_ID_INTEL_CMP_I2C0,
222 PCI_DEVICE_ID_INTEL_CMP_I2C1,
223 PCI_DEVICE_ID_INTEL_CMP_I2C2,
224 PCI_DEVICE_ID_INTEL_CMP_I2C3,
225 PCI_DEVICE_ID_INTEL_CMP_I2C4,
226 PCI_DEVICE_ID_INTEL_CMP_I2C5,
Gaggery Tsai12a651c2019-12-05 11:23:20 -0800227 PCI_DEVICE_ID_INTEL_CMP_H_I2C0,
228 PCI_DEVICE_ID_INTEL_CMP_H_I2C1,
229 PCI_DEVICE_ID_INTEL_CMP_H_I2C2,
230 PCI_DEVICE_ID_INTEL_CMP_H_I2C3,
Ravi Sarawadi6b5bf402019-10-21 22:25:04 -0700231 PCI_DEVICE_ID_INTEL_TGP_I2C0,
232 PCI_DEVICE_ID_INTEL_TGP_I2C1,
233 PCI_DEVICE_ID_INTEL_TGP_I2C2,
234 PCI_DEVICE_ID_INTEL_TGP_I2C3,
235 PCI_DEVICE_ID_INTEL_TGP_I2C4,
236 PCI_DEVICE_ID_INTEL_TGP_I2C5,
237 PCI_DEVICE_ID_INTEL_TGP_I2C6,
238 PCI_DEVICE_ID_INTEL_TGP_I2C7,
Tan, Lean Sheng26136092020-01-20 19:13:56 -0800239 PCI_DEVICE_ID_INTEL_MCC_I2C0,
240 PCI_DEVICE_ID_INTEL_MCC_I2C1,
241 PCI_DEVICE_ID_INTEL_MCC_I2C2,
242 PCI_DEVICE_ID_INTEL_MCC_I2C3,
243 PCI_DEVICE_ID_INTEL_MCC_I2C4,
244 PCI_DEVICE_ID_INTEL_MCC_I2C5,
245 PCI_DEVICE_ID_INTEL_MCC_I2C6,
246 PCI_DEVICE_ID_INTEL_MCC_I2C7,
Meera Ravindranath3f4af0d2020-02-12 16:01:22 +0530247 PCI_DEVICE_ID_INTEL_JSP_I2C0,
248 PCI_DEVICE_ID_INTEL_JSP_I2C1,
249 PCI_DEVICE_ID_INTEL_JSP_I2C2,
250 PCI_DEVICE_ID_INTEL_JSP_I2C3,
251 PCI_DEVICE_ID_INTEL_JSP_I2C4,
252 PCI_DEVICE_ID_INTEL_JSP_I2C5,
Subrata Banikf672f7f2020-08-03 14:29:25 +0530253 PCI_DEVICE_ID_INTEL_ADP_P_I2C0,
254 PCI_DEVICE_ID_INTEL_ADP_P_I2C1,
255 PCI_DEVICE_ID_INTEL_ADP_P_I2C2,
256 PCI_DEVICE_ID_INTEL_ADP_P_I2C3,
257 PCI_DEVICE_ID_INTEL_ADP_P_I2C4,
258 PCI_DEVICE_ID_INTEL_ADP_P_I2C5,
259 PCI_DEVICE_ID_INTEL_ADP_S_I2C0,
260 PCI_DEVICE_ID_INTEL_ADP_S_I2C1,
261 PCI_DEVICE_ID_INTEL_ADP_S_I2C2,
262 PCI_DEVICE_ID_INTEL_ADP_S_I2C3,
263 PCI_DEVICE_ID_INTEL_ADP_S_I2C4,
264 PCI_DEVICE_ID_INTEL_ADP_S_I2C5,
Ravi Sarawadi3038e9b2017-05-18 16:00:35 -0700265 0,
Rizwan Qureshiae6a4b62017-04-26 21:06:35 +0530266};
267
268static const struct pci_driver pch_i2c __pci_driver = {
269 .ops = &i2c_dev_ops,
270 .vendor = PCI_VENDOR_ID_INTEL,
271 .devices = pci_device_ids,
272};
Subrata Banike62836b2018-05-07 16:27:51 +0530273#endif