gem5  v20.1.0.0
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 }
Packet::makeAtomicResponse
void makeAtomicResponse()
Definition: packet.hh:1016
I2CBus::unserialize
void unserialize(CheckpointIn &cp) override
Unserialize an object.
Definition: bus.cc:227
BasicPioDevice::pioAddr
Addr pioAddr
Address that the device listens to.
Definition: io_device.hh:154
I2CBus::message
uint8_t message
8-bit buffer used to send and receive messages bit by bit.
Definition: bus.hh:100
I2CBus::i2cAddr
uint8_t i2cAddr
Key used to access a device in the slave devices map.
Definition: bus.hh:97
UNSERIALIZE_SCALAR
#define UNSERIALIZE_SCALAR(scalar)
Definition: serialize.hh:797
Packet::getAddr
Addr getAddr() const
Definition: packet.hh:754
I2CBus::scl
uint8_t scl
I2C clock wire (0, 1).
Definition: bus.hh:76
I2CBus::updateSignals
void updateSignals(PacketPtr pkt)
Update data (sda) and clock (scl) to match any transitions specified by pkt.
Definition: bus.cc:172
I2CBus::RECEIVING_DATA
@ RECEIVING_DATA
Definition: bus.hh:60
I2CBus::read
Tick read(PacketPtr pkt) override
Reads will always be to SB_CONTROLS.
Definition: bus.cc:70
Packet::setRaw
void setRaw(T v)
Set the value in the data pointer to v without byte swapping.
Definition: packet_access.hh:58
I2CBus::sda
uint8_t sda
I2C data wire (0, 1)
Definition: bus.hh:78
I2CBus::currBit
int currBit
Order of the bit of the current message that is being sent or received (0 - 7).
Definition: bus.hh:90
Tick
uint64_t Tick
Tick count type.
Definition: types.hh:63
I2CBus::I2CBus
I2CBus(const I2CBusParams *p)
4KB - see e.g.
Definition: bus.cc:54
I2CBus::state
enum I2CState state
State used by I2CBus::write to determine what stage of an i2c transmission it is currently in.
Definition: bus.hh:84
std::vector
STL vector class.
Definition: stl.hh:37
SERIALIZE_ENUM
#define SERIALIZE_ENUM(scalar)
Definition: serialize.hh:813
I2CBus::isStart
bool isStart(PacketPtr pkt) const
i2c start signal check
Definition: bus.cc:200
cp
Definition: cprintf.cc:40
device.hh
I2CBus
Definition: bus.hh:53
I2CBus::serialize
void serialize(CheckpointOut &cp) const override
Serialize an object.
Definition: bus.cc:215
DPRINTF
#define DPRINTF(x,...)
Definition: trace.hh:234
ArmISA::d
Bitfield< 9 > d
Definition: miscregs_types.hh:60
bus.hh
I2CBus::RECEIVING_ADDR
@ RECEIVING_ADDR
Definition: bus.hh:59
I2CBus::SB_CONTROLS
static const int SB_CONTROLS
Read [and Set] serial control bits: Bit [0] is SCL Bit [1] is SDA.
Definition: bus.hh:71
I2CBus::SENDING_DATA
@ SENDING_DATA
Definition: bus.hh:61
I2CBus::isEnd
bool isEnd(PacketPtr pkt) const
i2c end signal check
Definition: bus.cc:208
Addr
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition: types.hh:142
SERIALIZE_SCALAR
#define SERIALIZE_SCALAR(scalar)
Definition: serialize.hh:790
packet_access.hh
I2CBus::write
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
Packet::getRaw
T getRaw() const
Get the data in the packet without byte swapping.
Definition: packet_access.hh:49
X86ISA::vector
Bitfield< 15, 8 > vector
Definition: intmessage.hh:44
I2CBus::SB_CONTROLC
static const int SB_CONTROLC
Clear control bits.
Definition: bus.hh:73
Packet
A Packet is used to encapsulate a transfer between two objects in the memory system (e....
Definition: packet.hh:257
BasicPioDevice
Definition: io_device.hh:150
BasicPioDevice::pioDelay
Tick pioDelay
Delay that the device experinces on an access.
Definition: io_device.hh:160
CheckpointOut
std::ostream CheckpointOut
Definition: serialize.hh:63
I2CBus::IDLE
@ IDLE
Definition: bus.hh:58
UNSERIALIZE_ENUM
#define UNSERIALIZE_ENUM(scalar)
Definition: serialize.hh:820
trace.hh
I2CBus::devices
std::map< uint8_t, I2CDevice * > devices
All the slave i2c devices that are connected to this bus.
Definition: bus.hh:107
MipsISA::p
Bitfield< 0 > p
Definition: pra_constants.hh:323
CheckpointIn
Definition: serialize.hh:67
I2CBus::isClockSet
bool isClockSet(PacketPtr pkt) const
Clock set check.
Definition: bus.cc:192
panic
#define panic(...)
This implements a cprintf based panic() function.
Definition: logging.hh:171

Generated on Wed Sep 30 2020 14:02:11 for gem5 by doxygen 1.8.17