blob: 1c16a06058e6f947c9b4294b6e40105eb449c4b3 [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
29uintptr_t lpss_i2c_base_address(unsigned bus)
30{
31 unsigned devfn;
32 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;
63 const struct lpss_i2c_speed_config *sptr;
64 enum i2c_speed speed;
65 int i, bus = i2c_dev_to_bus(dev);
66
67 if (!config || bus < 0)
68 return;
69
70 speed = config->i2c[bus].speed ? : I2C_SPEED_FAST;
71 lpss_i2c_init(bus, speed);
72
73 /* Apply custom speed config if it has been set by the board */
74 for (i = 0; i < LPSS_I2C_SPEED_CONFIG_COUNT; i++) {
75 sptr = &config->i2c[bus].speed_config[i];
76 if (sptr->speed == speed) {
77 lpss_i2c_set_speed_config(bus, sptr);
78 break;
79 }
80 }
81}
82
83static void i2c_fill_ssdt(struct device *dev)
84{
85 struct soc_intel_apollolake_config *config = dev->chip_info;
86 int bus = i2c_dev_to_bus(dev);
87
88 if (!config || bus < 0)
89 return;
90
91 acpigen_write_scope(acpi_device_path(dev));
92 lpss_i2c_acpi_fill_ssdt(config->i2c[bus].speed_config);
93 acpigen_pop_len();
94}
95
96static struct i2c_bus_operations i2c_bus_ops = {
97 .dev_to_bus = &i2c_dev_to_bus,
98};
99
100static struct device_operations i2c_dev_ops = {
101 .read_resources = &pci_dev_read_resources,
102 .set_resources = &pci_dev_set_resources,
103 .enable_resources = &pci_dev_enable_resources,
104 .scan_bus = &scan_smbus,
105 .ops_i2c_bus = &i2c_bus_ops,
106 .init = &i2c_dev_init,
107 .acpi_fill_ssdt_generator = &i2c_fill_ssdt,
108};
109
110static const unsigned short pci_device_ids[] = {
111 PCI_DEVICE_ID_APOLLOLAKE_I2C0,
112 PCI_DEVICE_ID_APOLLOLAKE_I2C1,
113 PCI_DEVICE_ID_APOLLOLAKE_I2C2,
114 PCI_DEVICE_ID_APOLLOLAKE_I2C3,
115 PCI_DEVICE_ID_APOLLOLAKE_I2C4,
116 PCI_DEVICE_ID_APOLLOLAKE_I2C5,
117 PCI_DEVICE_ID_APOLLOLAKE_I2C6,
118 PCI_DEVICE_ID_APOLLOLAKE_I2C7,
119 0,
120};
121
122static const struct pci_driver pch_i2c __pci_driver = {
123 .ops = &i2c_dev_ops,
124 .vendor = PCI_VENDOR_ID_INTEL,
125 .devices = pci_device_ids,
126};