blob: 11bd018c8bb110f23c4afd37f76c1be9b9452f4c [file] [log] [blame]
Rizwan Qureshiae6a4b62017-04-26 21:06:35 +05301/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright 2017 Intel Corporation.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 */
15
Subrata Banike62836b2018-05-07 16:27:51 +053016#include <arch/io.h>
17#include <console/console.h>
18#include <device/device.h>
19#include <device/i2c_simple.h>
Rizwan Qureshiae6a4b62017-04-26 21:06:35 +053020#include <device/pci.h>
21#include <device/pci_def.h>
22#include <device/pci_ids.h>
Chris Chingb8dc63b2017-12-06 14:26:15 -070023#include <drivers/i2c/designware/dw_i2c.h>
Subrata Banike62836b2018-05-07 16:27:51 +053024#include <intelblocks/chip.h>
25#include <intelblocks/lpss.h>
26#include <soc/iomap.h>
27#include <soc/pci_devs.h>
28
29int dw_i2c_soc_dev_to_bus(struct device *dev)
30{
31 pci_devfn_t devfn = dev->path.pci.devfn;
32 return dw_i2c_soc_devfn_to_bus(devfn);
33}
34
35/* Getting I2C bus configuration from devicetree config */
36const struct dw_i2c_bus_config *dw_i2c_get_soc_cfg(unsigned int bus)
37{
38 const struct soc_intel_common_config *common_config;
39 common_config = chip_get_common_soc_structure();
40
41 return &common_config->i2c[bus];
42}
43
44/* Get base address for early init of I2C controllers. */
45uintptr_t dw_i2c_get_soc_early_base(unsigned int bus)
46{
47 return EARLY_I2C_BASE(bus);
48}
49
50#if !ENV_RAMSTAGE
51static int lpss_i2c_early_init_bus(unsigned int bus)
52{
53 const struct dw_i2c_bus_config *config;
54 const struct device *tree_dev;
55 pci_devfn_t dev;
56 int devfn;
57 uintptr_t base;
58
59 /* Find the PCI device for this bus controller */
60 devfn = dw_i2c_soc_bus_to_devfn(bus);
61 if (devfn < 0) {
62 printk(BIOS_ERR, "I2C%u device not found\n", bus);
63 return -1;
64 }
65
66 /* Look up the controller device in the devicetree */
67 dev = PCI_DEV(0, PCI_SLOT(devfn), PCI_FUNC(devfn));
68 tree_dev = dev_find_slot(0, devfn);
69 if (!tree_dev || !tree_dev->enabled) {
70 printk(BIOS_ERR, "I2C%u device not enabled\n", bus);
71 return -1;
72 }
73
74 /* Skip if not enabled for early init */
75 config = dw_i2c_get_soc_cfg(bus);
76 if (!config || !config->early_init) {
77 printk(BIOS_DEBUG, "I2C%u not enabled for early init\n", bus);
78 return -1;
79 }
80
81 /* Prepare early base address for access before memory */
82 base = dw_i2c_get_soc_early_base(bus);
83 pci_write_config32(dev, PCI_BASE_ADDRESS_0, base);
84 pci_write_config32(dev, PCI_COMMAND,
85 PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
86
87 /* Take device out of reset */
88 lpss_reset_release(base);
89
90 /* Initialize the controller */
91 if (dw_i2c_init(bus, config) < 0) {
92 printk(BIOS_ERR, "I2C%u failed to initialize\n", bus);
93 return -1;
94 }
95
96 return 0;
97}
98
99uintptr_t dw_i2c_base_address(unsigned int bus)
100{
101 int devfn;
102 pci_devfn_t dev;
103 uintptr_t base;
104
105 /* Find device+function for this controller */
106 devfn = dw_i2c_soc_bus_to_devfn(bus);
107 if (devfn < 0)
108 return (uintptr_t)NULL;
109
110 /* Form a PCI address for this device */
111 dev = PCI_DEV(0, PCI_SLOT(devfn), PCI_FUNC(devfn));
112
113 /* Read the first base address for this device */
114 base = ALIGN_DOWN(pci_read_config32(dev, PCI_BASE_ADDRESS_0), 16);
115
116 /* Attempt to initialize bus if base is not set yet */
117 if (!base && !lpss_i2c_early_init_bus(bus))
118 base = ALIGN_DOWN(pci_read_config32(dev, PCI_BASE_ADDRESS_0),
119 16);
120 return base;
121}
122#else
Rizwan Qureshiae6a4b62017-04-26 21:06:35 +0530123
Chris Chingb8dc63b2017-12-06 14:26:15 -0700124uintptr_t dw_i2c_base_address(unsigned int bus)
Rizwan Qureshiae6a4b62017-04-26 21:06:35 +0530125{
126 int devfn;
127 struct device *dev;
128 struct resource *res;
129
130 /* bus -> devfn */
Aaron Durbin9aee8192018-01-22 20:29:25 -0700131 devfn = dw_i2c_soc_bus_to_devfn(bus);
Rizwan Qureshiae6a4b62017-04-26 21:06:35 +0530132
133 if (devfn < 0)
134 return (uintptr_t)NULL;
135
136 /* devfn -> dev */
137 dev = dev_find_slot(0, devfn);
Furquan Shaikhd629e4332017-06-09 17:54:00 -0700138 if (!dev || !dev->enabled)
Rizwan Qureshiae6a4b62017-04-26 21:06:35 +0530139 return (uintptr_t)NULL;
140
141 /* dev -> bar0 */
142 res = find_resource(dev, PCI_BASE_ADDRESS_0);
143 if (res)
144 return res->base;
145
146 return (uintptr_t)NULL;
147}
148
Rizwan Qureshiae6a4b62017-04-26 21:06:35 +0530149static struct device_operations i2c_dev_ops = {
150 .read_resources = &pci_dev_read_resources,
151 .set_resources = &pci_dev_set_resources,
152 .enable_resources = &pci_dev_enable_resources,
153 .scan_bus = &scan_smbus,
Aaron Durbinb7d79cd2018-01-22 21:31:48 -0700154 .ops_i2c_bus = &dw_i2c_bus_ops,
Subrata Banik6bbc91a2017-12-07 14:55:51 +0530155 .ops_pci = &pci_dev_ops_pci,
Aaron Durbinb7d79cd2018-01-22 21:31:48 -0700156 .init = &dw_i2c_dev_init,
157 .acpi_fill_ssdt_generator = &dw_i2c_acpi_fill_ssdt,
Rizwan Qureshiae6a4b62017-04-26 21:06:35 +0530158};
159
160static const unsigned short pci_device_ids[] = {
161 PCI_DEVICE_ID_INTEL_SPT_I2C0,
162 PCI_DEVICE_ID_INTEL_SPT_I2C1,
163 PCI_DEVICE_ID_INTEL_SPT_I2C2,
164 PCI_DEVICE_ID_INTEL_SPT_I2C3,
165 PCI_DEVICE_ID_INTEL_SPT_I2C4,
166 PCI_DEVICE_ID_INTEL_SPT_I2C5,
V Sowmyaacc2a482018-01-23 15:27:23 +0530167 PCI_DEVICE_ID_INTEL_KBP_H_I2C0,
168 PCI_DEVICE_ID_INTEL_KBP_H_I2C1,
169 PCI_DEVICE_ID_INTEL_KBP_H_I2C2,
170 PCI_DEVICE_ID_INTEL_KBP_H_I2C3,
Rizwan Qureshiae6a4b62017-04-26 21:06:35 +0530171 PCI_DEVICE_ID_INTEL_APL_I2C0,
172 PCI_DEVICE_ID_INTEL_APL_I2C1,
173 PCI_DEVICE_ID_INTEL_APL_I2C2,
174 PCI_DEVICE_ID_INTEL_APL_I2C3,
175 PCI_DEVICE_ID_INTEL_APL_I2C4,
176 PCI_DEVICE_ID_INTEL_APL_I2C5,
177 PCI_DEVICE_ID_INTEL_APL_I2C6,
178 PCI_DEVICE_ID_INTEL_APL_I2C7,
Lijian Zhaobbedef92017-07-29 16:38:38 -0700179 PCI_DEVICE_ID_INTEL_CNL_I2C0,
180 PCI_DEVICE_ID_INTEL_CNL_I2C1,
181 PCI_DEVICE_ID_INTEL_CNL_I2C2,
182 PCI_DEVICE_ID_INTEL_CNL_I2C3,
183 PCI_DEVICE_ID_INTEL_CNL_I2C4,
184 PCI_DEVICE_ID_INTEL_CNL_I2C5,
Ravi Sarawadi3038e9b2017-05-18 16:00:35 -0700185 PCI_DEVICE_ID_INTEL_GLK_I2C0,
186 PCI_DEVICE_ID_INTEL_GLK_I2C1,
187 PCI_DEVICE_ID_INTEL_GLK_I2C2,
188 PCI_DEVICE_ID_INTEL_GLK_I2C3,
189 PCI_DEVICE_ID_INTEL_GLK_I2C4,
190 PCI_DEVICE_ID_INTEL_GLK_I2C5,
191 PCI_DEVICE_ID_INTEL_GLK_I2C6,
192 PCI_DEVICE_ID_INTEL_GLK_I2C7,
193 0,
Rizwan Qureshiae6a4b62017-04-26 21:06:35 +0530194};
195
196static const struct pci_driver pch_i2c __pci_driver = {
197 .ops = &i2c_dev_ops,
198 .vendor = PCI_VENDOR_ID_INTEL,
199 .devices = pci_device_ids,
200};
Subrata Banike62836b2018-05-07 16:27:51 +0530201#endif