blob: b152bb98c26fd90a17d528875611248a63df80c4 [file] [log] [blame]
David Hendricksf4c35082012-12-27 14:15:51 -08001/*
David Hendrickscfb73602013-04-05 13:42:39 -07002 * This file is part of the coreboot project.
David Hendricksf4c35082012-12-27 14:15:51 -08003 *
Gabe Blackcdb61a62014-04-07 18:45:14 -07004 * Copyright (C) 2014 Google, Inc.
David Hendricksf4c35082012-12-27 14:15:51 -08005 *
David Hendrickscfb73602013-04-05 13:42:39 -07006 * 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.
David Hendricksf4c35082012-12-27 14:15:51 -08009 *
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.
David Hendricksf4c35082012-12-27 14:15:51 -080014 */
15
David Hendrickscfb73602013-04-05 13:42:39 -070016#ifndef _DEVICE_I2C_H_
17#define _DEVICE_I2C_H_
David Hendricksf4c35082012-12-27 14:15:51 -080018
Gabe Blacka5dc0912013-06-30 03:47:33 -070019#include <stdint.h>
Gabe Blackcdb61a62014-04-07 18:45:14 -070020#include <stdlib.h>
Gabe Blacka5dc0912013-06-30 03:47:33 -070021
Gabe Blackcdb61a62014-04-07 18:45:14 -070022struct i2c_seg
23{
24 int read;
25 uint8_t chip;
26 uint8_t *buf;
27 int len;
28};
29
Julius Werner37d7ac82014-05-05 18:03:46 -070030int platform_i2c_transfer(unsigned bus, struct i2c_seg *segments, int count);
31
32#define SOFTWARE_I2C_MAX_BUS 10 /* increase as necessary */
33
34struct software_i2c_ops {
35 void (*set_sda)(unsigned bus, int high);
36 void (*set_scl)(unsigned bus, int high);
37 int (*get_sda)(unsigned bus);
38 int (*get_scl)(unsigned bus);
39};
40
41extern struct software_i2c_ops *software_i2c[];
42
43int software_i2c_transfer(unsigned bus, struct i2c_seg *segments, int count);
44void software_i2c_wedge_ack(unsigned bus, u8 chip);
45void software_i2c_wedge_read(unsigned bus, u8 chip, u8 reg, int bit_count);
46void software_i2c_wedge_write(unsigned bus, u8 chip, u8 reg, int bit_count);
47
Yidi Lind33ebd12016-03-15 14:38:44 +080048int i2c_read_field(unsigned bus, uint8_t chip, uint8_t reg, uint8_t *data,
49 uint8_t mask, uint8_t shift);
50int i2c_write_field(unsigned bus, uint8_t chip, uint8_t reg, uint8_t data,
51 uint8_t mask, uint8_t shift);
52
Julius Werner37d7ac82014-05-05 18:03:46 -070053/*
54 * software_i2c is supposed to be a debug feature. It's usually not compiled in,
55 * but when it is it can be dynamically enabled at runtime for certain busses.
56 * Need this ugly stub to arbitrate since I2C device drivers hardcode
57 * 'i2c_transfer()' as their entry point.
58 */
59static inline int i2c_transfer(unsigned bus, struct i2c_seg *segments,
60 int count)
61{
62 if (CONFIG_SOFTWARE_I2C)
63 if (bus < SOFTWARE_I2C_MAX_BUS && software_i2c[bus])
64 return software_i2c_transfer(bus, segments, count);
65
66 return platform_i2c_transfer(bus, segments, count);
67}
Gabe Blackcdb61a62014-04-07 18:45:14 -070068
69/*
70 * Read a raw chunk of data in one segment and one frame.
71 *
72 * [start][slave addr][r][data][stop]
73 */
74static inline int i2c_read_raw(unsigned bus, uint8_t chip, uint8_t *data,
75 int len)
76{
77 struct i2c_seg seg =
78 { .read = 1, .chip = chip, .buf = data, .len = len };
79 return i2c_transfer(bus, &seg, 1);
80}
81
82/*
83 * Write a raw chunk of data in one segment and one frame.
84 *
85 * [start][slave addr][w][data][stop]
86 */
87static inline int i2c_write_raw(unsigned bus, uint8_t chip, uint8_t *data,
88 int len)
89{
90 struct i2c_seg seg =
91 { .read = 0, .chip = chip, .buf = data, .len = len };
92 return i2c_transfer(bus, &seg, 1);
93}
94
95/**
Jitao Shi5ffb6882016-02-01 17:33:49 +080096 * Read multi-bytes with two segments in one frame
97 *
98 * [start][slave addr][w][register addr][start][slave addr][r][data...][stop]
99 */
100static inline int i2c_read_bytes(unsigned bus, uint8_t chip, uint8_t reg,
101 uint8_t *data, int len)
102{
103 struct i2c_seg seg[2];
104
105 seg[0].read = 0;
106 seg[0].chip = chip;
107 seg[0].buf = &reg;
108 seg[0].len = 1;
109 seg[1].read = 1;
110 seg[1].chip = chip;
111 seg[1].buf = data;
112 seg[1].len = len;
113
114 return i2c_transfer(bus, seg, ARRAY_SIZE(seg));
115}
116
117/**
Gabe Blackcdb61a62014-04-07 18:45:14 -0700118 * Read a byte with two segments in one frame
119 *
120 * [start][slave addr][w][register addr][start][slave addr][r][data][stop]
121 */
122static inline int i2c_readb(unsigned bus, uint8_t chip, uint8_t reg,
123 uint8_t *data)
124{
125 struct i2c_seg seg[2];
126
127 seg[0].read = 0;
128 seg[0].chip = chip;
129 seg[0].buf = &reg;
130 seg[0].len = 1;
131 seg[1].read = 1;
132 seg[1].chip = chip;
133 seg[1].buf = data;
134 seg[1].len = 1;
135
136 return i2c_transfer(bus, seg, ARRAY_SIZE(seg));
137}
138
139/**
140 * Write a byte with one segment in one frame.
141 *
142 * [start][slave addr][w][register addr][data][stop]
143 */
144static inline int i2c_writeb(unsigned bus, uint8_t chip, uint8_t reg,
145 uint8_t data)
146{
147 struct i2c_seg seg;
148 uint8_t buf[] = {reg, data};
149
150 seg.read = 0;
151 seg.chip = chip;
152 seg.buf = buf;
153 seg.len = ARRAY_SIZE(buf);
154
155 return i2c_transfer(bus, &seg, 1);
156}
David Hendricksf4c35082012-12-27 14:15:51 -0800157
David Hendrickscfb73602013-04-05 13:42:39 -0700158#endif /* _DEVICE_I2C_H_ */