blob: d4670a013cde5e1058eb95e2b5ebff6f723cc73e [file] [log] [blame]
Yidi Lind33ebd12016-03-15 14:38:44 +08001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright 2016 MediaTek 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
Duncan Laurieec009682016-06-07 15:38:14 -070016#include <device/device.h>
Yidi Lind33ebd12016-03-15 14:38:44 +080017#include <device/i2c.h>
Duncan Laurieec009682016-06-07 15:38:14 -070018#include <stdint.h>
19
20#if ENV_RAMSTAGE
21/* Return I2C operations for a bus */
22static inline const struct i2c_bus_operations *ops_i2c_bus(struct bus *bus)
23{
24 if (bus && bus->dev && bus->dev->ops)
25 return bus->dev->ops->ops_i2c_bus;
26 return NULL;
27}
28
29int i2c_dev_find_bus(struct device *dev)
30{
31 const struct i2c_bus_operations *ops;
32 struct bus *pbus;
33
34 if (!dev)
35 return -1;
36
37 /* Locate parent bus with I2C controller ops */
38 pbus = dev->bus;
39 while (pbus && pbus->dev && !ops_i2c_bus(pbus))
40 if (pbus->dev->bus != pbus)
41 pbus = pbus->dev->bus;
42
43 /* Check if this I2C controller ops implements dev_to_bus() */
44 ops = ops_i2c_bus(pbus);
45 if (!ops || !ops->dev_to_bus)
46 return -1;
47
48 /* Use controller ops to determine the bus number */
49 return ops->dev_to_bus(pbus->dev);
50}
51
52int i2c_dev_transfer(struct device *dev, struct i2c_seg *segments, int count)
53{
54 int bus = i2c_dev_find_bus(dev);
55 if (bus < 0)
56 return -1;
57 return i2c_transfer(bus, segments, count);
58}
59
60int i2c_dev_readb(struct device *dev, uint8_t reg, uint8_t *data)
61{
62 int bus = i2c_dev_find_bus(dev);
63 if (bus < 0)
64 return -1;
65 return i2c_readb(bus, dev->path.i2c.device, reg, data);
66}
67
68int i2c_dev_writeb(struct device *dev, uint8_t reg, uint8_t data)
69{
70 int bus = i2c_dev_find_bus(dev);
71 if (bus < 0)
72 return -1;
73 return i2c_writeb(bus, dev->path.i2c.device, reg, data);
74}
75
76int i2c_dev_read_bytes(struct device *dev, uint8_t reg, uint8_t *data, int len)
77{
78 int bus = i2c_dev_find_bus(dev);
79 if (bus < 0)
80 return -1;
81 return i2c_read_bytes(bus, dev->path.i2c.device, reg, data, len);
82}
83
84int i2c_dev_read_raw(struct device *dev, uint8_t *data, int len)
85{
86 int bus = i2c_dev_find_bus(dev);
87 if (bus < 0)
88 return -1;
89 return i2c_read_raw(bus, dev->path.i2c.device, data, len);
90}
91
92int i2c_dev_write_raw(struct device *dev, uint8_t *data, int len)
93{
94 int bus = i2c_dev_find_bus(dev);
95 if (bus < 0)
96 return -1;
97 return i2c_write_raw(bus, dev->path.i2c.device, data, len);
98}
99#endif
Yidi Lind33ebd12016-03-15 14:38:44 +0800100
101int i2c_read_field(unsigned bus, uint8_t chip, uint8_t reg, uint8_t *data,
102 uint8_t mask, uint8_t shift)
103{
104 int ret;
105 uint8_t buf = 0;
106
107 ret = i2c_readb(bus, chip, reg, &buf);
108
109 buf &= (mask << shift);
110 *data = (buf >> shift);
111
112 return ret;
113}
114
115int i2c_write_field(unsigned bus, uint8_t chip, uint8_t reg, uint8_t data,
116 uint8_t mask, uint8_t shift)
117{
118 int ret;
119 uint8_t buf = 0;
120
121 ret = i2c_readb(bus, chip, reg, &buf);
122
123 buf &= ~(mask << shift);
124 buf |= (data << shift);
125
126 ret |= i2c_writeb(bus, chip, reg, buf);
127
128 return ret;
129}