gem5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
bus.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2012 ARM Limited
3  * All rights reserved
4  *
5  * The license below extends only to copyright in the software and shall
6  * not be construed as granting a license to any other intellectual
7  * property including but not limited to intellectual property relating
8  * to a hardware implementation of the functionality of the software
9  * licensed hereunder. You may use the software subject to the license
10  * terms below provided that you ensure that this notice is replicated
11  * unmodified and in its entirety in all distributions of the software,
12  * modified or unmodified, in source code or in binary form.
13  *
14  * Redistribution and use in source and binary forms, with or without
15  * modification, are permitted provided that the following conditions are
16  * met: redistributions of source code must retain the above copyright
17  * notice, this list of conditions and the following disclaimer;
18  * redistributions in binary form must reproduce the above copyright
19  * notice, this list of conditions and the following disclaimer in the
20  * documentation and/or other materials provided with the distribution;
21  * neither the name of the copyright holders nor the names of its
22  * contributors may be used to endorse or promote products derived from
23  * this software without specific prior written permission.
24  *
25  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36  *
37  * Authors: Peter Enns
38  */
39 
40 #include "dev/i2c/bus.hh"
41 
42 #include "debug/Checkpoint.hh"
43 #include "dev/i2c/device.hh"
44 #include "mem/packet_access.hh"
45 
46 // clang complains about std::set being overloaded with Packet::set if
47 // we open up the entire namespace std
48 using std::vector;
49 using std::map;
50 
55 I2CBus::I2CBus(const I2CBusParams *p)
56  : BasicPioDevice(p, 0xfff), scl(1), sda(1), state(IDLE), currBit(7),
57  i2cAddr(0x00), message(0x00)
58 {
59  vector<I2CDevice*> devs = p->devices;
60 
61  for (auto d : p->devices) {
62  devices[d->i2cAddr()] = d;
63  }
64 }
65 
70 Tick
72 {
73  assert(pkt->getAddr() == pioAddr + SB_CONTROLS);
74 
75  pkt->set<uint8_t>((sda << 1) | scl);
76  pkt->makeAtomicResponse();
77  return pioDelay;
78 }
79 
89 Tick
91 {
92  assert(pkt->getAddr() == pioAddr + SB_CONTROLS ||
93  pkt->getAddr() == pioAddr + SB_CONTROLC);
94 
95  updateSignals(pkt);
96 
97  // Check if the bus master is starting a new transmission.
98  if (isStart(pkt)) {
100  message = 0x00;
101  currBit = 7;
102  /* Most i2c devices expect something special (e.g., command,
103  * register address) in the first byte they receive so they
104  * must be notified somehow that this is a new transmission.
105  */
106  for (auto& d : devices) {
107  d.second->i2cStart();
108  }
109  return pioDelay;
110  }
111 
112  // Check if the bus master is ending a transmission.
113  if (isEnd(pkt)) {
114  state = IDLE;
115  return pioDelay;
116  }
117 
118  // Only change state when the clock is transitioning from low to high.
119  // This may not perfectly mimic physical i2c devices but the important
120  // part is to only do the following once per clock cycle.
121  if (isClockSet(pkt)) {
122  switch (state) {
123  case RECEIVING_ADDR:
124  if (currBit >= 0) {
125  message |= sda << currBit;
126  currBit--;
127  } else {
128  i2cAddr = message >> 1;
129  assert(devices.find(i2cAddr) != devices.end());
130  if (message & 0x01) {
132  message = devices[i2cAddr]->read();
133  } else {
135  message = 0x00;
136  }
137  currBit = 7;
138  sda = 0; /* Ack */
139  }
140  break;
141  case RECEIVING_DATA:
142  if (currBit >= 0) {
143  message |= sda << currBit;
144  currBit--;
145  } else {
146  devices[i2cAddr]->write(message);
147  message = 0x00;
148  currBit = 7;
149  sda = 0; /* Ack */
150  }
151  break;
152  case SENDING_DATA:
153  if (currBit >= 0) {
154  sda = (message >> currBit) & 0x01;
155  currBit--;
156  } else {
157  if (!sda) /* Check for ack from the bus master. */
158  message = devices[i2cAddr]->read();
159  currBit = 7;
160  }
161  break;
162  case IDLE:
163  default:
164  panic("Invalid state on posedge of clock in I2CBus::write.\n");
165  break;
166  }
167  }
168 
169  return pioDelay;
170 }
171 
172 void
174 {
175  uint8_t msg = pkt->get<uint8_t>();
176  Addr daddr = pkt->getAddr() - pioAddr;
177 
178  switch (daddr) {
179  case SB_CONTROLS:
180  scl = (msg & 1) ? 1 : scl;
181  sda = (msg & 2) ? 1 : sda;
182  break;
183  case SB_CONTROLC:
184  scl = (msg & 1) ? 0 : scl;
185  sda = (msg & 2) ? 0 : sda;
186  break;
187  default:
188  break;
189  }
190 }
191 
192 bool
194 {
195  uint8_t msg = pkt->get<uint8_t>();
196  Addr daddr = pkt->getAddr() - pioAddr;
197  return daddr == SB_CONTROLS && (msg & 1);
198 }
199 
200 bool
202 {
203  uint8_t msg = pkt->get<uint8_t>();
204  Addr daddr = pkt->getAddr() - pioAddr;
205  return scl && (msg & 2) && daddr == SB_CONTROLC;
206 }
207 
208 bool
210 {
211  uint8_t msg = pkt->get<uint8_t>();
212  Addr daddr = pkt->getAddr() - pioAddr;
213  return scl && (msg & 2) && daddr == SB_CONTROLS;
214 }
215 void
217 {
218  DPRINTF(Checkpoint, "Serializing I2C bus.\n");
225 }
226 
227 void
229 {
230  DPRINTF(Checkpoint, "Unserializing I2C bus.\n");
237 }
238 
239 I2CBus*
240 I2CBusParams::create()
241 {
242  return new I2CBus(this);
243 }
#define DPRINTF(x,...)
Definition: trace.hh:212
void set(T v, ByteOrder endian)
Set the value in the data pointer to v using the specified endianness.
#define panic(...)
Definition: misc.hh:153
std::map< uint8_t, I2CDevice * > devices
All the slave i2c devices that are connected to this bus.
Definition: bus.hh:109
enum I2CState state
State used by I2CBus::write to determine what stage of an i2c transmission it is currently in...
Definition: bus.hh:86
uint8_t i2cAddr
Key used to access a device in the slave devices map.
Definition: bus.hh:99
bool isClockSet(PacketPtr pkt) const
Clock set check.
Definition: bus.cc:193
static const int SB_CONTROLS
Read [and Set] serial control bits: Bit [0] is SCL Bit [1] is SDA.
Definition: bus.hh:73
STL vector class.
Definition: stl.hh:40
T get(ByteOrder endian) const
Get the data in the packet byte swapped from the specified endianness.
uint8_t message
8-bit buffer used to send and receive messages bit by bit.
Definition: bus.hh:102
#define UNSERIALIZE_SCALAR(scalar)
Definition: serialize.hh:145
All i2c devices should derive from this class.
void makeAtomicResponse()
Definition: packet.hh:857
uint64_t Tick
Tick count type.
Definition: types.hh:63
I2CBus(const I2CBusParams *p)
4KB - see e.g.
Definition: bus.cc:55
void updateSignals(PacketPtr pkt)
Update data (sda) and clock (scl) to match any transitions specified by pkt.
Definition: bus.cc:173
Bitfield< 9 > d
Definition: miscregs.hh:1375
Tick read(PacketPtr pkt) override
Reads will always be to SB_CONTROLS.
Definition: bus.cc:71
Tick write(PacketPtr pkt) override
The default i2c bus driver used by the realview pbx board writes to this device one bit at a time...
Definition: bus.cc:90
void unserialize(CheckpointIn &cp) override
Unserialize an object.
Definition: bus.cc:228
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition: types.hh:142
A Packet is used to encapsulate a transfer between two objects in the memory system (e...
Definition: packet.hh:245
int currBit
Order of the bit of the current message that is being sent or received (0 - 7).
Definition: bus.hh:92
Bitfield< 15, 8 > vector
Definition: intmessage.hh:45
bool isEnd(PacketPtr pkt) const
i2c end signal check
Definition: bus.cc:209
#define SERIALIZE_SCALAR(scalar)
Definition: serialize.hh:143
#define UNSERIALIZE_ENUM(scalar)
Definition: serialize.hh:151
Definition: bus.hh:55
std::ostream CheckpointOut
Definition: serialize.hh:67
static const int SB_CONTROLC
Clear control bits.
Definition: bus.hh:75
void serialize(CheckpointOut &cp) const override
Serialize an object.
Definition: bus.cc:216
Tick pioDelay
Delay that the device experinces on an access.
Definition: io_device.hh:145
uint8_t scl
I2C clock wire (0, 1).
Definition: bus.hh:78
bool isStart(PacketPtr pkt) const
i2c start signal check
Definition: bus.cc:201
Bitfield< 0 > p
Addr pioAddr
Address that the device listens to.
Definition: io_device.hh:139
uint8_t sda
I2C data wire (0, 1)
Definition: bus.hh:80
Implementiation of an i2c bus.
#define SERIALIZE_ENUM(scalar)
Definition: serialize.hh:149
Addr getAddr() const
Definition: packet.hh:639

Generated on Fri Jun 9 2017 13:03:46 for gem5 by doxygen 1.8.6