blob: 9aadc78b8cd2bbdf2b497e3afc68bd525adce66e [file] [log] [blame]
Duncan Laurieff8bce02016-06-27 10:57:13 -07001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright 2016 Google Inc.
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
16#include <arch/acpi_device.h>
17#include <arch/acpigen.h>
18#include <device/device.h>
19#include <device/i2c.h>
20#include <device/pci.h>
21#include <device/pci_def.h>
22#include <device/pci_ids.h>
23#include <soc/i2c.h>
24#include <soc/intel/common/lpss_i2c.h>
25#include <soc/pci_devs.h>
26#include <soc/pci_ids.h>
27#include "chip.h"
28
Lee Leahy0096d072017-03-09 10:05:29 -080029uintptr_t lpss_i2c_base_address(unsigned int bus)
Duncan Laurieff8bce02016-06-27 10:57:13 -070030{
Lee Leahy0096d072017-03-09 10:05:29 -080031 unsigned int devfn;
Duncan Laurieff8bce02016-06-27 10:57:13 -070032 struct device *dev;
33 struct resource *res;
34
35 /* bus -> devfn */
36 devfn = i2c_bus_to_devfn(bus);
37 if (devfn >= 0) {
38 /* devfn -> dev */
39 dev = dev_find_slot(0, devfn);
40 if (dev) {
41 /* dev -> bar0 */
42 res = find_resource(dev, PCI_BASE_ADDRESS_0);
43 if (res)
44 return res->base;
45 }
46 }
47
48 return (uintptr_t)NULL;
49}
50
51static int i2c_dev_to_bus(struct device *dev)
52{
53 return i2c_devfn_to_bus(dev->path.pci.devfn);
54}
55
56/*
57 * The device should already be enabled and out of reset,
58 * either from early init in coreboot or FSP-S.
59 */
60static void i2c_dev_init(struct device *dev)
61{
62 struct soc_intel_apollolake_config *config = dev->chip_info;
Aaron Durbin4668ba72016-11-09 17:09:40 -060063 int bus = i2c_dev_to_bus(dev);
Duncan Laurieff8bce02016-06-27 10:57:13 -070064
65 if (!config || bus < 0)
66 return;
67
Aaron Durbin4668ba72016-11-09 17:09:40 -060068 lpss_i2c_init(bus, &config->i2c[bus]);
Duncan Laurieff8bce02016-06-27 10:57:13 -070069}
70
71static void i2c_fill_ssdt(struct device *dev)
72{
73 struct soc_intel_apollolake_config *config = dev->chip_info;
74 int bus = i2c_dev_to_bus(dev);
75
76 if (!config || bus < 0)
77 return;
78
79 acpigen_write_scope(acpi_device_path(dev));
Aaron Durbin2b3e0cd2016-11-09 23:20:30 -060080 lpss_i2c_acpi_fill_ssdt(bus, &config->i2c[bus]);
Duncan Laurieff8bce02016-06-27 10:57:13 -070081 acpigen_pop_len();
82}
83
84static struct i2c_bus_operations i2c_bus_ops = {
85 .dev_to_bus = &i2c_dev_to_bus,
86};
87
88static struct device_operations i2c_dev_ops = {
89 .read_resources = &pci_dev_read_resources,
90 .set_resources = &pci_dev_set_resources,
91 .enable_resources = &pci_dev_enable_resources,
92 .scan_bus = &scan_smbus,
93 .ops_i2c_bus = &i2c_bus_ops,
94 .init = &i2c_dev_init,
95 .acpi_fill_ssdt_generator = &i2c_fill_ssdt,
96};
97
98static const unsigned short pci_device_ids[] = {
99 PCI_DEVICE_ID_APOLLOLAKE_I2C0,
100 PCI_DEVICE_ID_APOLLOLAKE_I2C1,
101 PCI_DEVICE_ID_APOLLOLAKE_I2C2,
102 PCI_DEVICE_ID_APOLLOLAKE_I2C3,
103 PCI_DEVICE_ID_APOLLOLAKE_I2C4,
104 PCI_DEVICE_ID_APOLLOLAKE_I2C5,
105 PCI_DEVICE_ID_APOLLOLAKE_I2C6,
106 PCI_DEVICE_ID_APOLLOLAKE_I2C7,
107 0,
108};
109
110static const struct pci_driver pch_i2c __pci_driver = {
111 .ops = &i2c_dev_ops,
112 .vendor = PCI_VENDOR_ID_INTEL,
113 .devices = pci_device_ids,
114};