blob: c1f2a2103acaeb776ca9aab9168a9b0dea67a1bd [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.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
David Hendrickscfb73602013-04-05 13:42:39 -070017 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA
David Hendricksf4c35082012-12-27 14:15:51 -080018 */
19
David Hendrickscfb73602013-04-05 13:42:39 -070020#ifndef _DEVICE_I2C_H_
21#define _DEVICE_I2C_H_
David Hendricksf4c35082012-12-27 14:15:51 -080022
Gabe Blacka5dc0912013-06-30 03:47:33 -070023#include <stdint.h>
Gabe Blackcdb61a62014-04-07 18:45:14 -070024#include <stdlib.h>
Gabe Blacka5dc0912013-06-30 03:47:33 -070025
Gabe Blackcdb61a62014-04-07 18:45:14 -070026struct i2c_seg
27{
28 int read;
29 uint8_t chip;
30 uint8_t *buf;
31 int len;
32};
33
Julius Werner37d7ac82014-05-05 18:03:46 -070034int platform_i2c_transfer(unsigned bus, struct i2c_seg *segments, int count);
35
36#define SOFTWARE_I2C_MAX_BUS 10 /* increase as necessary */
37
38struct software_i2c_ops {
39 void (*set_sda)(unsigned bus, int high);
40 void (*set_scl)(unsigned bus, int high);
41 int (*get_sda)(unsigned bus);
42 int (*get_scl)(unsigned bus);
43};
44
45extern struct software_i2c_ops *software_i2c[];
46
47int software_i2c_transfer(unsigned bus, struct i2c_seg *segments, int count);
48void software_i2c_wedge_ack(unsigned bus, u8 chip);
49void software_i2c_wedge_read(unsigned bus, u8 chip, u8 reg, int bit_count);
50void software_i2c_wedge_write(unsigned bus, u8 chip, u8 reg, int bit_count);
51
52/*
53 * software_i2c is supposed to be a debug feature. It's usually not compiled in,
54 * but when it is it can be dynamically enabled at runtime for certain busses.
55 * Need this ugly stub to arbitrate since I2C device drivers hardcode
56 * 'i2c_transfer()' as their entry point.
57 */
58static inline int i2c_transfer(unsigned bus, struct i2c_seg *segments,
59 int count)
60{
61 if (CONFIG_SOFTWARE_I2C)
62 if (bus < SOFTWARE_I2C_MAX_BUS && software_i2c[bus])
63 return software_i2c_transfer(bus, segments, count);
64
65 return platform_i2c_transfer(bus, segments, count);
66}
Gabe Blackcdb61a62014-04-07 18:45:14 -070067
68/*
69 * Read a raw chunk of data in one segment and one frame.
70 *
71 * [start][slave addr][r][data][stop]
72 */
73static inline int i2c_read_raw(unsigned bus, uint8_t chip, uint8_t *data,
74 int len)
75{
76 struct i2c_seg seg =
77 { .read = 1, .chip = chip, .buf = data, .len = len };
78 return i2c_transfer(bus, &seg, 1);
79}
80
81/*
82 * Write a raw chunk of data in one segment and one frame.
83 *
84 * [start][slave addr][w][data][stop]
85 */
86static inline int i2c_write_raw(unsigned bus, uint8_t chip, uint8_t *data,
87 int len)
88{
89 struct i2c_seg seg =
90 { .read = 0, .chip = chip, .buf = data, .len = len };
91 return i2c_transfer(bus, &seg, 1);
92}
93
94/**
95 * Read a byte with two segments in one frame
96 *
97 * [start][slave addr][w][register addr][start][slave addr][r][data][stop]
98 */
99static inline int i2c_readb(unsigned bus, uint8_t chip, uint8_t reg,
100 uint8_t *data)
101{
102 struct i2c_seg seg[2];
103
104 seg[0].read = 0;
105 seg[0].chip = chip;
106 seg[0].buf = &reg;
107 seg[0].len = 1;
108 seg[1].read = 1;
109 seg[1].chip = chip;
110 seg[1].buf = data;
111 seg[1].len = 1;
112
113 return i2c_transfer(bus, seg, ARRAY_SIZE(seg));
114}
115
116/**
117 * Write a byte with one segment in one frame.
118 *
119 * [start][slave addr][w][register addr][data][stop]
120 */
121static inline int i2c_writeb(unsigned bus, uint8_t chip, uint8_t reg,
122 uint8_t data)
123{
124 struct i2c_seg seg;
125 uint8_t buf[] = {reg, data};
126
127 seg.read = 0;
128 seg.chip = chip;
129 seg.buf = buf;
130 seg.len = ARRAY_SIZE(buf);
131
132 return i2c_transfer(bus, &seg, 1);
133}
David Hendricksf4c35082012-12-27 14:15:51 -0800134
David Hendrickscfb73602013-04-05 13:42:39 -0700135#endif /* _DEVICE_I2C_H_ */