gem5  v20.0.0.2
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules 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 
38 #include "dev/i2c/bus.hh"
39 
40 #include "base/trace.hh"
41 #include "debug/Checkpoint.hh"
42 #include "dev/i2c/device.hh"
43 #include "mem/packet_access.hh"
44 
45 // clang complains about std::set being overloaded with Packet::set if
46 // we open up the entire namespace std
47 using std::vector;
48 using std::map;
49 
54 I2CBus::I2CBus(const I2CBusParams *p)
55  : BasicPioDevice(p, 0x1000), scl(1), sda(1), state(IDLE), currBit(7),
56  i2cAddr(0x00), message(0x00)
57 {
58  vector<I2CDevice*> devs = p->devices;
59 
60  for (auto d : p->devices) {
61  devices[d->i2cAddr()] = d;
62  }
63 }
64 
69 Tick
71 {
72  assert(pkt->getAddr() == pioAddr + SB_CONTROLS);
73 
74  pkt->setRaw<uint8_t>((sda << 1) | scl);
75  pkt->makeAtomicResponse();
76  return pioDelay;
77 }
78 
88 Tick
90 {
91  assert(pkt->getAddr() == pioAddr + SB_CONTROLS ||
92  pkt->getAddr() == pioAddr + SB_CONTROLC);
93 
94  updateSignals(pkt);
95 
96  // Check if the bus master is starting a new transmission.
97  if (isStart(pkt)) {
99  message = 0x00;
100  currBit = 7;
101  /* Most i2c devices expect something special (e.g., command,
102  * register address) in the first byte they receive so they
103  * must be notified somehow that this is a new transmission.
104  */
105  for (auto& d : devices) {
106  d.second->i2cStart();
107  }
108  return pioDelay;
109  }
110 
111  // Check if the bus master is ending a transmission.
112  if (isEnd(pkt)) {
113  state = IDLE;
114  return pioDelay;
115  }
116 
117  // Only change state when the clock is transitioning from low to high.
118  // This may not perfectly mimic physical i2c devices but the important
119  // part is to only do the following once per clock cycle.
120  if (isClockSet(pkt)) {
121  switch (state) {
122  case RECEIVING_ADDR:
123  if (currBit >= 0) {
124  message |= sda << currBit;
125  currBit--;
126  } else {
127  i2cAddr = message >> 1;
128  assert(devices.find(i2cAddr) != devices.end());
129  if (message & 0x01) {
131  message = devices[i2cAddr]->read();
132  } else {
134  message = 0x00;
135  }
136  currBit = 7;
137  sda = 0; /* Ack */
138  }
139  break;
140  case RECEIVING_DATA:
141  if (currBit >= 0) {
142  message |= sda << currBit;
143  currBit--;
144  } else {
145  devices[i2cAddr]->write(message);
146  message = 0x00;
147  currBit = 7;
148  sda = 0; /* Ack */
149  }
150  break;
151  case SENDING_DATA:
152  if (currBit >= 0) {
153  sda = (message >> currBit) & 0x01;
154  currBit--;
155  } else {
156  if (!sda) /* Check for ack from the bus master. */
157  message = devices[i2cAddr]->read();
158  currBit = 7;
159  }
160  break;
161  case IDLE:
162  default:
163  panic("Invalid state on posedge of clock in I2CBus::write.\n");
164  break;
165  }
166  }
167 
168  return pioDelay;
169 }
170 
171 void
173 {
174  uint8_t msg = pkt->getRaw<uint8_t>();
175  Addr daddr = pkt->getAddr() - pioAddr;
176 
177  switch (daddr) {
178  case SB_CONTROLS:
179  scl = (msg & 1) ? 1 : scl;
180  sda = (msg & 2) ? 1 : sda;
181  break;
182  case SB_CONTROLC:
183  scl = (msg & 1) ? 0 : scl;
184  sda = (msg & 2) ? 0 : sda;
185  break;
186  default:
187  break;
188  }
189 }
190 
191 bool
193 {
194  uint8_t msg = pkt->getRaw<uint8_t>();
195  Addr daddr = pkt->getAddr() - pioAddr;
196  return daddr == SB_CONTROLS && (msg & 1);
197 }
198 
199 bool
201 {
202  uint8_t msg = pkt->getRaw<uint8_t>();
203  Addr daddr = pkt->getAddr() - pioAddr;
204  return scl && (msg & 2) && daddr == SB_CONTROLC;
205 }
206 
207 bool
209 {
210  uint8_t msg = pkt->getRaw<uint8_t>();
211  Addr daddr = pkt->getAddr() - pioAddr;
212  return scl && (msg & 2) && daddr == SB_CONTROLS;
213 }
214 void
216 {
217  DPRINTF(Checkpoint, "Serializing I2C bus.\n");
224 }
225 
226 void
228 {
229  DPRINTF(Checkpoint, "Unserializing I2C bus.\n");
236 }
237 
238 I2CBus*
239 I2CBusParams::create()
240 {
241  return new I2CBus(this);
242 }
#define panic(...)
This implements a cprintf based panic() function.
Definition: logging.hh:163
#define DPRINTF(x,...)
Definition: trace.hh:222
bool isStart(PacketPtr pkt) const
i2c start signal check
Definition: bus.cc:200
std::map< uint8_t, I2CDevice * > devices
All the slave i2c devices that are connected to this bus.
Definition: bus.hh:107
enum I2CState state
State used by I2CBus::write to determine what stage of an i2c transmission it is currently in...
Definition: bus.hh:84
uint8_t i2cAddr
Key used to access a device in the slave devices map.
Definition: bus.hh:97
void setRaw(T v)
Set the value in the data pointer to v without byte swapping.
Definition: cprintf.cc:40
static const int SB_CONTROLS
Read [and Set] serial control bits: Bit [0] is SCL Bit [1] is SDA.
Definition: bus.hh:71
STL vector class.
Definition: stl.hh:37
uint8_t message
8-bit buffer used to send and receive messages bit by bit.
Definition: bus.hh:100
#define UNSERIALIZE_SCALAR(scalar)
Definition: serialize.hh:770
All i2c devices should derive from this class.
#define SERIALIZE_ENUM(scalar)
Definition: serialize.hh:786
void makeAtomicResponse()
Definition: packet.hh:943
uint64_t Tick
Tick count type.
Definition: types.hh:61
I2CBus(const I2CBusParams *p)
4KB - see e.g.
Definition: bus.cc:54
void updateSignals(PacketPtr pkt)
Update data (sda) and clock (scl) to match any transitions specified by pkt.
Definition: bus.cc:172
Bitfield< 9 > d
Tick read(PacketPtr pkt) override
Reads will always be to SB_CONTROLS.
Definition: bus.cc:70
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:89
void unserialize(CheckpointIn &cp) override
Unserialize an object.
Definition: bus.cc:227
Addr getAddr() const
Definition: packet.hh:720
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition: types.hh:140
A Packet is used to encapsulate a transfer between two objects in the memory system (e...
Definition: packet.hh:249
int currBit
Order of the bit of the current message that is being sent or received (0 - 7).
Definition: bus.hh:90
Bitfield< 15, 8 > vector
Definition: intmessage.hh:44
#define SERIALIZE_SCALAR(scalar)
Definition: serialize.hh:763
Definition: bus.hh:53
std::ostream CheckpointOut
Definition: serialize.hh:63
static const int SB_CONTROLC
Clear control bits.
Definition: bus.hh:73
T getRaw() const
Get the data in the packet without byte swapping.
bool isEnd(PacketPtr pkt) const
i2c end signal check
Definition: bus.cc:208
#define UNSERIALIZE_ENUM(scalar)
Definition: serialize.hh:793
void serialize(CheckpointOut &cp) const override
Serialize an object.
Definition: bus.cc:215
Tick pioDelay
Delay that the device experinces on an access.
Definition: io_device.hh:160
uint8_t scl
I2C clock wire (0, 1).
Definition: bus.hh:76
Bitfield< 0 > p
Addr pioAddr
Address that the device listens to.
Definition: io_device.hh:154
uint8_t sda
I2C data wire (0, 1)
Definition: bus.hh:78
Implementiation of an i2c bus.
bool isClockSet(PacketPtr pkt) const
Clock set check.
Definition: bus.cc:192

Generated on Mon Jun 8 2020 15:45:10 for gem5 by doxygen 1.8.13