summaryrefslogtreecommitdiff
path: root/src/drivers/i2c/designware/dw_i2c.h
blob: ccdb3d2351524f8d19009198e1c2909d327f8dad (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
/*
 * This file is part of the coreboot project.
 *
 * Copyright 2017 Intel Corporation.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; version 2 of the License.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 */

#ifndef __DRIVERS_I2C_DESIGNWARE_I2C_H__
#define __DRIVERS_I2C_DESIGNWARE_I2C_H__

#include <compiler.h>
#include <device/device.h>
#include <device/i2c.h>
#include <stdint.h>

#if IS_ENABLED(CONFIG_DRIVERS_I2C_DESIGNWARE_DEBUG)
#define DW_I2C_DEBUG BIOS_DEBUG

#else
#define DW_I2C_DEBUG BIOS_NEVER

#endif // CONFIG_DRIVERS_I2C_DESIGNWARE_DEBUG

/*
 * Timing values are in units of clock period, with the clock speed
 * provided by the SOC in CONFIG_DRIVERS_I2C_DESIGNWARE_I2C_CLOCK_MHZ
 * Automatic configuration is done based on requested speed, but the
 * values may need tuned depending on the board and the number of
 * devices present on the bus.
 */
struct dw_i2c_speed_config {
	enum i2c_speed speed;
	/* SCL high and low period count */
	uint16_t scl_lcnt;
	uint16_t scl_hcnt;
	/*
	 * SDA hold time should be 300ns in standard and fast modes
	 * and long enough for deterministic logic level change in
	 * fast-plus and high speed modes.
	 *
	 *  [15:0] SDA TX Hold Time
	 * [23:16] SDA RX Hold Time
	 */
	uint32_t sda_hold;
};

/*
 * This I2C controller has support for 3 independent speed configs but can
 * support both FAST_PLUS and HIGH speeds through the same set of speed
 * config registers.  These are treated separately so the speed config values
 * can be provided via ACPI to the OS.
 */
#define DW_I2C_SPEED_CONFIG_COUNT	4

struct dw_i2c_bus_config {
	/* Bus should be enabled prior to ramstage with temporary base */
	int early_init;
	/* Bus speed in Hz, default is I2C_SPEED_FAST (400 KHz) */
	enum i2c_speed speed;
	/* If rise_time_ns is non-zero the calculations for lcnt and hcnt
	 * registers take into account the times of the bus. However, if
	 * there is a match in speed_config those register values take
	 * precedence. */
	int rise_time_ns;
	int fall_time_ns;
	int data_hold_time_ns;
	/* Specific bus speed configuration */
	struct dw_i2c_speed_config speed_config[DW_I2C_SPEED_CONFIG_COUNT];
};

/* Functions to be implemented by SoC code */

/* Get base address for early init of I2C controllers. */
uintptr_t dw_i2c_get_soc_early_base(unsigned int bus);

/*
 * Map given I2C bus number to devfn.
 * Return value:
 * -1 = error
 * otherwise, devfn(>=0) corresponding to I2C bus number.
 */
int dw_i2c_soc_devfn_to_bus(unsigned int devfn);

/*
 * Map given bus number to a I2C Controller.
 * Return value:
 * -1 = error
 * otherwise, devfn(>=0) corresponding to I2C bus number.
 */
int dw_i2c_soc_bus_to_devfn(unsigned int bus);

/*
 * SoC implemented callback for getting I2C bus configuration.
 *
 * Returns NULL if i2c config is not found
 */
const struct dw_i2c_bus_config *dw_i2c_get_soc_cfg(unsigned int bus);

/* Get I2C controller base address */
uintptr_t dw_i2c_base_address(unsigned int bus);

/*
 * Initialize this bus controller and set the speed
 * Return value:
 * -1 = failure
 *  0 = success
*/
int dw_i2c_init(unsigned int bus, const struct dw_i2c_bus_config *bcfg);

/*
 * Generate speed config based on clock
 * Return value:
 * -1 = failure
 *  0 = success
*/
int dw_i2c_gen_speed_config(uintptr_t dw_i2c_addr,
					enum i2c_speed speed,
					const struct dw_i2c_bus_config *bcfg,
					struct dw_i2c_speed_config *config);

/*
 * Process given I2C segments in a single transfer
 * Return value:
 * -1 = failure
 *  0 = success
 */
int dw_i2c_transfer(unsigned int bus,
			const struct i2c_msg *segments,
			size_t count);

/*
 * Map an i2c host controller device to a logical bus number.
 * Return value:
 * -1 = failure
 * >=0 = logical bus number
 */
int dw_i2c_soc_dev_to_bus(struct device *dev);

/*
 * Common device_operations implementation to initialize the i2c host
 * controller.
 */
void dw_i2c_dev_init(struct device *dev);

/*
 * Common device_operations implementation to fill ACPI SSDT table for i2c
 * host controller.
 */
void dw_i2c_acpi_fill_ssdt(struct device *dev);

/*
 * Common device_operations implementation for i2c host controller ops.
 */
extern const struct i2c_bus_operations dw_i2c_bus_ops;

#endif /* __DRIVERS_I2C_DESIGNWARE_I2C_H__ */