blob: 78817bb3002383657bbe21282f53f169f3b8a658 [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
48/*
49 * software_i2c is supposed to be a debug feature. It's usually not compiled in,
50 * but when it is it can be dynamically enabled at runtime for certain busses.
51 * Need this ugly stub to arbitrate since I2C device drivers hardcode
52 * 'i2c_transfer()' as their entry point.
53 */
54static inline int i2c_transfer(unsigned bus, struct i2c_seg *segments,
55 int count)
56{
57 if (CONFIG_SOFTWARE_I2C)
58 if (bus < SOFTWARE_I2C_MAX_BUS && software_i2c[bus])
59 return software_i2c_transfer(bus, segments, count);
60
61 return platform_i2c_transfer(bus, segments, count);
62}
Gabe Blackcdb61a62014-04-07 18:45:14 -070063
64/*
65 * Read a raw chunk of data in one segment and one frame.
66 *
67 * [start][slave addr][r][data][stop]
68 */
69static inline int i2c_read_raw(unsigned bus, uint8_t chip, uint8_t *data,
70 int len)
71{
72 struct i2c_seg seg =
73 { .read = 1, .chip = chip, .buf = data, .len = len };
74 return i2c_transfer(bus, &seg, 1);
75}
76
77/*
78 * Write a raw chunk of data in one segment and one frame.
79 *
80 * [start][slave addr][w][data][stop]
81 */
82static inline int i2c_write_raw(unsigned bus, uint8_t chip, uint8_t *data,
83 int len)
84{
85 struct i2c_seg seg =
86 { .read = 0, .chip = chip, .buf = data, .len = len };
87 return i2c_transfer(bus, &seg, 1);
88}
89
90/**
91 * Read a byte with two segments in one frame
92 *
93 * [start][slave addr][w][register addr][start][slave addr][r][data][stop]
94 */
95static inline int i2c_readb(unsigned bus, uint8_t chip, uint8_t reg,
96 uint8_t *data)
97{
98 struct i2c_seg seg[2];
99
100 seg[0].read = 0;
101 seg[0].chip = chip;
102 seg[0].buf = &reg;
103 seg[0].len = 1;
104 seg[1].read = 1;
105 seg[1].chip = chip;
106 seg[1].buf = data;
107 seg[1].len = 1;
108
109 return i2c_transfer(bus, seg, ARRAY_SIZE(seg));
110}
111
112/**
113 * Write a byte with one segment in one frame.
114 *
115 * [start][slave addr][w][register addr][data][stop]
116 */
117static inline int i2c_writeb(unsigned bus, uint8_t chip, uint8_t reg,
118 uint8_t data)
119{
120 struct i2c_seg seg;
121 uint8_t buf[] = {reg, data};
122
123 seg.read = 0;
124 seg.chip = chip;
125 seg.buf = buf;
126 seg.len = ARRAY_SIZE(buf);
127
128 return i2c_transfer(bus, &seg, 1);
129}
David Hendricksf4c35082012-12-27 14:15:51 -0800130
David Hendrickscfb73602013-04-05 13:42:39 -0700131#endif /* _DEVICE_I2C_H_ */