blob: b5ea15e0c66f6741e344ede640af1512aeaf17ab [file] [log] [blame]
Rizwan Qureshiae6a4b62017-04-26 21:06:35 +05301/*
2 * This file is part of the coreboot project.
3 *
Rizwan Qureshiae6a4b62017-04-26 21:06:35 +05304 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; version 2 of the License.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 */
14
Kyösti Mälkkif1b58b72019-03-01 13:43:02 +020015#include <device/pci_ops.h>
Subrata Banike62836b2018-05-07 16:27:51 +053016#include <console/console.h>
17#include <device/device.h>
18#include <device/i2c_simple.h>
Rizwan Qureshiae6a4b62017-04-26 21:06:35 +053019#include <device/pci.h>
20#include <device/pci_def.h>
21#include <device/pci_ids.h>
Chris Chingb8dc63b2017-12-06 14:26:15 -070022#include <drivers/i2c/designware/dw_i2c.h>
Kyösti Mälkki32d47eb2019-09-28 00:00:30 +030023#include <intelblocks/cfg.h>
Subrata Banike62836b2018-05-07 16:27:51 +053024#include <intelblocks/lpss.h>
25#include <soc/iomap.h>
26#include <soc/pci_devs.h>
27
28int dw_i2c_soc_dev_to_bus(struct device *dev)
29{
30 pci_devfn_t devfn = dev->path.pci.devfn;
31 return dw_i2c_soc_devfn_to_bus(devfn);
32}
33
34/* Getting I2C bus configuration from devicetree config */
35const struct dw_i2c_bus_config *dw_i2c_get_soc_cfg(unsigned int bus)
36{
37 const struct soc_intel_common_config *common_config;
38 common_config = chip_get_common_soc_structure();
39
40 return &common_config->i2c[bus];
41}
42
43/* Get base address for early init of I2C controllers. */
44uintptr_t dw_i2c_get_soc_early_base(unsigned int bus)
45{
46 return EARLY_I2C_BASE(bus);
47}
48
Subrata Banik42c44c22019-05-15 20:27:04 +053049#if !ENV_PAYLOAD_LOADER
Subrata Banike62836b2018-05-07 16:27:51 +053050static int lpss_i2c_early_init_bus(unsigned int bus)
51{
52 const struct dw_i2c_bus_config *config;
53 const struct device *tree_dev;
54 pci_devfn_t dev;
55 int devfn;
56 uintptr_t base;
57
58 /* Find the PCI device for this bus controller */
59 devfn = dw_i2c_soc_bus_to_devfn(bus);
60 if (devfn < 0) {
61 printk(BIOS_ERR, "I2C%u device not found\n", bus);
62 return -1;
63 }
64
65 /* Look up the controller device in the devicetree */
66 dev = PCI_DEV(0, PCI_SLOT(devfn), PCI_FUNC(devfn));
Kyösti Mälkkie7377552018-06-21 16:20:55 +030067 tree_dev = pcidev_path_on_root(devfn);
Subrata Banike62836b2018-05-07 16:27:51 +053068 if (!tree_dev || !tree_dev->enabled) {
69 printk(BIOS_ERR, "I2C%u device not enabled\n", bus);
70 return -1;
71 }
72
73 /* Skip if not enabled for early init */
74 config = dw_i2c_get_soc_cfg(bus);
75 if (!config || !config->early_init) {
76 printk(BIOS_DEBUG, "I2C%u not enabled for early init\n", bus);
77 return -1;
78 }
79
80 /* Prepare early base address for access before memory */
81 base = dw_i2c_get_soc_early_base(bus);
82 pci_write_config32(dev, PCI_BASE_ADDRESS_0, base);
83 pci_write_config32(dev, PCI_COMMAND,
84 PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
85
86 /* Take device out of reset */
87 lpss_reset_release(base);
88
Aamir Bohraf5202a62019-07-12 14:37:55 +053089 /* Ensure controller is in D0 state */
90 lpss_set_power_state(tree_dev, STATE_D0);
91
Subrata Banike62836b2018-05-07 16:27:51 +053092 /* Initialize the controller */
93 if (dw_i2c_init(bus, config) < 0) {
94 printk(BIOS_ERR, "I2C%u failed to initialize\n", bus);
95 return -1;
96 }
97
98 return 0;
99}
100
101uintptr_t dw_i2c_base_address(unsigned int bus)
102{
103 int devfn;
104 pci_devfn_t dev;
105 uintptr_t base;
106
107 /* Find device+function for this controller */
108 devfn = dw_i2c_soc_bus_to_devfn(bus);
109 if (devfn < 0)
110 return (uintptr_t)NULL;
111
112 /* Form a PCI address for this device */
113 dev = PCI_DEV(0, PCI_SLOT(devfn), PCI_FUNC(devfn));
114
115 /* Read the first base address for this device */
116 base = ALIGN_DOWN(pci_read_config32(dev, PCI_BASE_ADDRESS_0), 16);
117
118 /* Attempt to initialize bus if base is not set yet */
119 if (!base && !lpss_i2c_early_init_bus(bus))
120 base = ALIGN_DOWN(pci_read_config32(dev, PCI_BASE_ADDRESS_0),
121 16);
122 return base;
123}
124#else
Rizwan Qureshiae6a4b62017-04-26 21:06:35 +0530125
Chris Chingb8dc63b2017-12-06 14:26:15 -0700126uintptr_t dw_i2c_base_address(unsigned int bus)
Rizwan Qureshiae6a4b62017-04-26 21:06:35 +0530127{
128 int devfn;
129 struct device *dev;
130 struct resource *res;
131
132 /* bus -> devfn */
Aaron Durbin9aee8192018-01-22 20:29:25 -0700133 devfn = dw_i2c_soc_bus_to_devfn(bus);
Rizwan Qureshiae6a4b62017-04-26 21:06:35 +0530134
135 if (devfn < 0)
136 return (uintptr_t)NULL;
137
138 /* devfn -> dev */
Kyösti Mälkkie7377552018-06-21 16:20:55 +0300139 dev = pcidev_path_on_root(devfn);
Furquan Shaikhd629e4332017-06-09 17:54:00 -0700140 if (!dev || !dev->enabled)
Rizwan Qureshiae6a4b62017-04-26 21:06:35 +0530141 return (uintptr_t)NULL;
142
143 /* dev -> bar0 */
144 res = find_resource(dev, PCI_BASE_ADDRESS_0);
145 if (res)
146 return res->base;
147
148 return (uintptr_t)NULL;
149}
150
Subrata Banik7d8c0c22018-09-27 19:27:39 +0530151/*
152 * This function ensures that the device is actually out of reset and
153 * its ready for initialization sequence.
154 */
155static void dw_i2c_device_init(struct device *dev)
156{
157 uintptr_t base_address;
158 int bus = dw_i2c_soc_dev_to_bus(dev);
159
160 if (bus < 0)
161 return;
162
163 base_address = dw_i2c_base_address(bus);
164 if (!base_address)
165 return;
166
Aamir Bohraf5202a62019-07-12 14:37:55 +0530167 /* Ensure controller is in D0 state */
168 lpss_set_power_state(dev, STATE_D0);
169
Subrata Banik7d8c0c22018-09-27 19:27:39 +0530170 /* Take device out of reset if its not done before */
171 if (lpss_is_controller_in_reset(base_address))
172 lpss_reset_release(base_address);
173
174 dw_i2c_dev_init(dev);
175}
176
Rizwan Qureshiae6a4b62017-04-26 21:06:35 +0530177static struct device_operations i2c_dev_ops = {
Elyes HAOUAS1d191272018-11-27 12:23:48 +0100178 .read_resources = pci_dev_read_resources,
179 .set_resources = pci_dev_set_resources,
180 .enable_resources = pci_dev_enable_resources,
181 .scan_bus = scan_smbus,
Aaron Durbinb7d79cd2018-01-22 21:31:48 -0700182 .ops_i2c_bus = &dw_i2c_bus_ops,
Subrata Banik6bbc91a2017-12-07 14:55:51 +0530183 .ops_pci = &pci_dev_ops_pci,
Elyes HAOUAS1d191272018-11-27 12:23:48 +0100184 .init = dw_i2c_device_init,
Karthikeyan Ramasubramanian0e971e12020-01-09 11:32:16 -0700185#if CONFIG(HAVE_ACPI_TABLES)
Elyes HAOUAS1d191272018-11-27 12:23:48 +0100186 .acpi_fill_ssdt_generator = dw_i2c_acpi_fill_ssdt,
Karthikeyan Ramasubramanian0e971e12020-01-09 11:32:16 -0700187#endif
Rizwan Qureshiae6a4b62017-04-26 21:06:35 +0530188};
189
190static const unsigned short pci_device_ids[] = {
191 PCI_DEVICE_ID_INTEL_SPT_I2C0,
192 PCI_DEVICE_ID_INTEL_SPT_I2C1,
193 PCI_DEVICE_ID_INTEL_SPT_I2C2,
194 PCI_DEVICE_ID_INTEL_SPT_I2C3,
195 PCI_DEVICE_ID_INTEL_SPT_I2C4,
196 PCI_DEVICE_ID_INTEL_SPT_I2C5,
V Sowmyaacc2a482018-01-23 15:27:23 +0530197 PCI_DEVICE_ID_INTEL_KBP_H_I2C0,
198 PCI_DEVICE_ID_INTEL_KBP_H_I2C1,
199 PCI_DEVICE_ID_INTEL_KBP_H_I2C2,
200 PCI_DEVICE_ID_INTEL_KBP_H_I2C3,
Rizwan Qureshiae6a4b62017-04-26 21:06:35 +0530201 PCI_DEVICE_ID_INTEL_APL_I2C0,
202 PCI_DEVICE_ID_INTEL_APL_I2C1,
203 PCI_DEVICE_ID_INTEL_APL_I2C2,
204 PCI_DEVICE_ID_INTEL_APL_I2C3,
205 PCI_DEVICE_ID_INTEL_APL_I2C4,
206 PCI_DEVICE_ID_INTEL_APL_I2C5,
207 PCI_DEVICE_ID_INTEL_APL_I2C6,
208 PCI_DEVICE_ID_INTEL_APL_I2C7,
Lijian Zhaobbedef92017-07-29 16:38:38 -0700209 PCI_DEVICE_ID_INTEL_CNL_I2C0,
210 PCI_DEVICE_ID_INTEL_CNL_I2C1,
211 PCI_DEVICE_ID_INTEL_CNL_I2C2,
212 PCI_DEVICE_ID_INTEL_CNL_I2C3,
213 PCI_DEVICE_ID_INTEL_CNL_I2C4,
214 PCI_DEVICE_ID_INTEL_CNL_I2C5,
Ravi Sarawadi3038e9b2017-05-18 16:00:35 -0700215 PCI_DEVICE_ID_INTEL_GLK_I2C0,
216 PCI_DEVICE_ID_INTEL_GLK_I2C1,
217 PCI_DEVICE_ID_INTEL_GLK_I2C2,
218 PCI_DEVICE_ID_INTEL_GLK_I2C3,
219 PCI_DEVICE_ID_INTEL_GLK_I2C4,
220 PCI_DEVICE_ID_INTEL_GLK_I2C5,
221 PCI_DEVICE_ID_INTEL_GLK_I2C6,
222 PCI_DEVICE_ID_INTEL_GLK_I2C7,
praveen hodagatta praneshe26c4a42018-09-20 03:49:45 +0800223 PCI_DEVICE_ID_INTEL_CNP_H_I2C0,
224 PCI_DEVICE_ID_INTEL_CNP_H_I2C1,
225 PCI_DEVICE_ID_INTEL_CNP_H_I2C2,
226 PCI_DEVICE_ID_INTEL_CNP_H_I2C3,
Aamir Bohra9eac0392018-06-30 12:07:04 +0530227 PCI_DEVICE_ID_INTEL_ICP_I2C0,
228 PCI_DEVICE_ID_INTEL_ICP_I2C1,
229 PCI_DEVICE_ID_INTEL_ICP_I2C2,
230 PCI_DEVICE_ID_INTEL_ICP_I2C3,
231 PCI_DEVICE_ID_INTEL_ICP_I2C4,
232 PCI_DEVICE_ID_INTEL_ICP_I2C5,
Ronak Kanabarda7ffb482019-02-05 01:51:13 +0530233 PCI_DEVICE_ID_INTEL_CMP_I2C0,
234 PCI_DEVICE_ID_INTEL_CMP_I2C1,
235 PCI_DEVICE_ID_INTEL_CMP_I2C2,
236 PCI_DEVICE_ID_INTEL_CMP_I2C3,
237 PCI_DEVICE_ID_INTEL_CMP_I2C4,
238 PCI_DEVICE_ID_INTEL_CMP_I2C5,
Gaggery Tsai12a651c2019-12-05 11:23:20 -0800239 PCI_DEVICE_ID_INTEL_CMP_H_I2C0,
240 PCI_DEVICE_ID_INTEL_CMP_H_I2C1,
241 PCI_DEVICE_ID_INTEL_CMP_H_I2C2,
242 PCI_DEVICE_ID_INTEL_CMP_H_I2C3,
Ravi Sarawadi6b5bf402019-10-21 22:25:04 -0700243 PCI_DEVICE_ID_INTEL_TGP_I2C0,
244 PCI_DEVICE_ID_INTEL_TGP_I2C1,
245 PCI_DEVICE_ID_INTEL_TGP_I2C2,
246 PCI_DEVICE_ID_INTEL_TGP_I2C3,
247 PCI_DEVICE_ID_INTEL_TGP_I2C4,
248 PCI_DEVICE_ID_INTEL_TGP_I2C5,
249 PCI_DEVICE_ID_INTEL_TGP_I2C6,
250 PCI_DEVICE_ID_INTEL_TGP_I2C7,
Tan, Lean Sheng26136092020-01-20 19:13:56 -0800251 PCI_DEVICE_ID_INTEL_MCC_I2C0,
252 PCI_DEVICE_ID_INTEL_MCC_I2C1,
253 PCI_DEVICE_ID_INTEL_MCC_I2C2,
254 PCI_DEVICE_ID_INTEL_MCC_I2C3,
255 PCI_DEVICE_ID_INTEL_MCC_I2C4,
256 PCI_DEVICE_ID_INTEL_MCC_I2C5,
257 PCI_DEVICE_ID_INTEL_MCC_I2C6,
258 PCI_DEVICE_ID_INTEL_MCC_I2C7,
Meera Ravindranath3f4af0d2020-02-12 16:01:22 +0530259 PCI_DEVICE_ID_INTEL_JSP_I2C0,
260 PCI_DEVICE_ID_INTEL_JSP_I2C1,
261 PCI_DEVICE_ID_INTEL_JSP_I2C2,
262 PCI_DEVICE_ID_INTEL_JSP_I2C3,
263 PCI_DEVICE_ID_INTEL_JSP_I2C4,
264 PCI_DEVICE_ID_INTEL_JSP_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