summaryrefslogtreecommitdiffstats
path: root/src/usr/pore/poreve/porevesrc/fasti2c.H
blob: 724c3fa2ae72cb5f6a61a8a89da658226bfb246a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/usr/pore/poreve/porevesrc/fasti2c.H $                     */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* COPYRIGHT International Business Machines Corp. 2012,2014              */
/*                                                                        */
/* Licensed under the Apache License, Version 2.0 (the "License");        */
/* you may not use this file except in compliance with the License.       */
/* You may obtain a copy of the License at                                */
/*                                                                        */
/*     http://www.apache.org/licenses/LICENSE-2.0                         */
/*                                                                        */
/* Unless required by applicable law or agreed to in writing, software    */
/* distributed under the License is distributed on an "AS IS" BASIS,      */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or        */
/* implied. See the License for the specific language governing           */
/* permissions and limitations under the License.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */
#ifndef __VSBE_FASTI2C_H
#define __VSBE_FASTI2C_H

// $Id: fasti2c.H,v 1.7 2012/10/05 23:20:32 bcbrock Exp $

/// \file fasti2c.H
/// \brief The "fast-mode" I2C controllers and memory models used
/// to implement the OTPROM, PNOR and SEEPROM interfaces.

#include <fapi.H>

#include <stddef.h>
#include <stdint.h>

#include "bebits.H"
#include "bus.H"

namespace vsbe {

    class FastI2cController;
    class LpcController;
    class I2cMemory;

    /// \defgroup fasti2c_speeds Fast-Mode I2C Controller Speeds
    ///
    /// Note that all speeds are considered "legal", and the model does not
    /// interpret the speed setting.
    ///
    /// @{
    
    const int FASTI2C_SPEED_100K  = 0;
    const int FASTI2C_SPEED_400K  = 1;
    const int FASTI2C_SPEED_3400K = 2;
    const int FASTI2C_SPEED_50K   = 3;

    /// @}

    /// \defgroup fasti2c_offsets Fast-Mode I2C Controller Register Offsets (PIB) and limits
    ///
    /// The last two offsets are only valid on the LpcController model.
    /// @{

    const uint32_t FASTI2C_CONTROL_OFFSET  = 0x0;
    const uint32_t FASTI2C_RESET_OFFSET    = 0x1;
    const uint32_t FASTI2C_STATUS_OFFSET   = 0x2;
    const uint32_t FASTI2C_DATA_OFFSET     = 0x3;
    const size_t   FASTI2C_REGISTERS       = 0x4;

    const uint32_t LPCM_ECC_START_OFFSET   = 0x4;
    const uint32_t LPCM_ECC_STOP_OFFSET    = 0x5;
    const size_t   LPCM_REGISTERS          = 0x6;

    /// @}

    /// The maximum memory size supported by the LPC controller (64MB)
    const uint32_t LPC_MEMORY_MAX_SIZE = (1 << 26);


    // These register layouts are copied/modified from the PMX model. If they
    // need to be modified here then they will also need to be modified in the
    // PMX model.

    /// Fast-Mode I2C Controller Control Register Layout
    typedef union {

        uint64_t value;
        struct {
#ifdef _BIG_ENDIAN
            uint32_t high_order;
            uint32_t low_order;
#else
            uint32_t low_order;
            uint32_t high_order;
#endif // _BIG_ENDIAN
        } words;
        struct {
#ifdef _BIG_ENDIAN
            uint64_t with_start : 1;
            uint64_t with_address : 1;
            uint64_t read_continue : 1;
            uint64_t with_stop : 1;
            uint64_t data_length : 4;
            uint64_t device_address : 7;
            uint64_t read_not_write : 1;
            uint64_t speed : 2;
            uint64_t port_number : 5;
            uint64_t address_range : 3;
            uint64_t _reserved0 : 6;
            uint64_t data0 : 8;
            uint64_t data1 : 8;
            uint64_t data2 : 8;
            uint64_t data3 : 8;
#else
            uint64_t data3 : 8;
            uint64_t data2 : 8;
            uint64_t data1 : 8;
            uint64_t data0 : 8;
            uint64_t _reserved0 : 6;
            uint64_t address_range : 3;
            uint64_t port_number : 5;
            uint64_t speed : 2;
            uint64_t read_not_write : 1;
            uint64_t device_address : 7;
            uint64_t data_length : 4;
            uint64_t with_stop : 1;
            uint64_t read_continue : 1;
            uint64_t with_address : 1;
            uint64_t with_start : 1;
#endif // _BIG_ENDIAN
        } fields;
    } FastI2cControlRegister;


    /// Fast-Mode I2C Controller Reset Register Layout
    typedef union {

        uint64_t value;
        struct {
#ifdef _BIG_ENDIAN
            uint32_t high_order;
            uint32_t low_order;
#else
            uint32_t low_order;
            uint32_t high_order;
#endif // _BIG_ENDIAN
        } words;
        struct {
#ifdef _BIG_ENDIAN
            uint64_t value : 64;
#else
            uint64_t value : 64;
#endif // _BIG_ENDIAN
        } fields;
    } FastI2cResetRegister;


    /// Fast-Mode I2C Controller Status Register Layout
    typedef union {

        uint64_t value;
        struct {
#ifdef _BIG_ENDIAN
            uint32_t high_order;
            uint32_t low_order;
#else
            uint32_t low_order;
            uint32_t high_order;
#endif // _BIG_ENDIAN
        } words;
        struct {
#ifdef _BIG_ENDIAN
            uint64_t pib_address_invalid : 1;
            uint64_t pib_write_invalid : 1;
            uint64_t pib_read_invalid : 1;
            uint64_t pib_address_parity_error : 1;
            uint64_t pib_parity_error : 1;
            uint64_t lb_parity_error : 1;
            uint64_t read_data : 32;
            uint64_t _reserved0 : 6;
            uint64_t i2c_macro_busy : 1;
            uint64_t i2c_invalid_command : 1;
            uint64_t i2c_parity_error : 1;
            uint64_t i2c_back_end_overrun_error : 1;
            uint64_t i2c_back_end_access_error : 1;
            uint64_t i2c_arbitration_lost : 1;
            uint64_t i2c_nack_received : 1;
            uint64_t i2c_data_request : 1;
            uint64_t i2c_command_complete : 1;
            uint64_t i2c_stop_error : 1;
            uint64_t i2c_port_busy : 1;
            uint64_t i2c_interface_busy : 1;
            uint64_t i2c_fifo_entry_count : 8;
#else
            uint64_t i2c_fifo_entry_count : 8;
            uint64_t i2c_interface_busy : 1;
            uint64_t i2c_port_busy : 1;
            uint64_t i2c_stop_error : 1;
            uint64_t i2c_command_complete : 1;
            uint64_t i2c_data_request : 1;
            uint64_t i2c_nack_received : 1;
            uint64_t i2c_arbitration_lost : 1;
            uint64_t i2c_back_end_access_error : 1;
            uint64_t i2c_back_end_overrun_error : 1;
            uint64_t i2c_parity_error : 1;
            uint64_t i2c_invalid_command : 1;
            uint64_t i2c_macro_busy : 1;
            uint64_t _reserved0 : 6;
            uint64_t read_data : 32;
            uint64_t lb_parity_error : 1;
            uint64_t pib_parity_error : 1;
            uint64_t pib_address_parity_error : 1;
            uint64_t pib_read_invalid : 1;
            uint64_t pib_write_invalid : 1;
            uint64_t pib_address_invalid : 1;
#endif // _BIG_ENDIAN
        } fields;
    } FastI2cStatusRegister;

};


////////////////////////////////////////////////////////////////////////////
// I2cMemory
////////////////////////////////////////////////////////////////////////////


/// An I2C memory model
///
/// The I2cMemory is a subclass of the Memory.  It adds a device address for
/// mapping onto an I2c bus, and also supports I2C memory operations such as
/// addressWrite() and dataRead().

class
vsbe::I2cMemory : public Memory
{

public:

    //////////////////////////////   Types  //////////////////////////////

    ////////////////////////////// Creators //////////////////////////////

    /// Create an I2c Memory
    I2cMemory();

    virtual ~I2cMemory();

    ///////////////////////////// Accessors //////////////////////////////

    //////////////////////////// Manipulators ////////////////////////////

    /// Configure the number of address bytes
    ///
    /// \param[in] i_addressBytes The number of address bytes (1-4) in a
    /// memory address for this devie.
    void
    configure(const uint8_t i_addressBytes);

    /// Perform an I2C address write to an attached device.
    ///
    /// \param[in] i_bytes The number of address bytes, which must match the
    /// configuration. 
    ///
    /// \param[in] i_address The memory address.
    ///
    /// \retval me ModelError return code
    ModelError 
    addressWrite(const size_t i_bytes, const uint32_t i_address);

    /// Perform an I2C data read from an attached device.
    ///
    /// \param[in] i_bytes The number of data bytes to read
    ///
    /// \param[out] o_data The data, right justified
    ///
    /// The read has a side effect of incrementing the address held in the
    /// device by \a i_bytes.
    ///
    /// \retval me ModelError return code
    ModelError 
    dataRead(const size_t i_bytes, uint64_t& o_data);

    /// Perform an I2C data write to an attached device.
    ///
    /// \param[in] i_bytes The number of data bytes to write
    ///
    /// \param[in] i_data The data, right justified
    ///
    /// The write has a side effect of incrementing the address held in the
    /// device by \a i_bytes.
    ///
    /// \retval me ModelError return code
    ModelError 
    dataWrite(const size_t i_bytes, const uint64_t i_data);


    ////////////////////////// Implementation ////////////////////////////

protected:

    /// The number of address bytes (1-4)
    uint8_t iv_addressBytes;

    /// The address register, auto-incremented on data reads and writes
    uint32_t iv_address;

    ///////////////////////////// Safety //////////////////////////////////

private:
    I2cMemory(const I2cMemory& i_rhs);
    I2cMemory& operator=(const I2cMemory& i_rhs);
};


////////////////////////////////////////////////////////////////////////////
// I2cDevice
////////////////////////////////////////////////////////////////////////////

namespace vsbe {

/// A simple I2C device/bus model
///
/// This simple device/bus model is used by the FastI2cController to model the
/// atachment of multiple I2cMemory to the physical busses (ports) controlled
/// by each controller.  Normally only 1 or two devices are attached to each
/// controller so it's easiest to model all devices under control of a
/// controller as a single list.

typedef struct I2cDevice {

    /// The controller port number - associated with a physical I2C bus
    unsigned iv_port;

    /// The device address of the device on the bus
    unsigned iv_deviceAddress;

    /// The I2cMemory 
    I2cMemory* iv_memory;

    /// The next I2cdevice in the list of devices
    struct I2cDevice* next;

} I2cDevice;

};    

////////////////////////////////////////////////////////////////////////////
// FastI2cController
////////////////////////////////////////////////////////////////////////////


/// A model of a "fast-mode" I2C Controller
///
/// The PORE engine only uses the new "fast-mode" protocol to communicate with
/// "I2C Controllers" that implement the physical memory interfaces for SBE
/// memories. These controllers may be either real I2C controllers (like for
/// SEEPROM) or pseudo-I2C-controllers like the PNOR and OTPROM controllers.
/// The "fast-mode" is a new subset of the full I2C controller interface that
/// only uses 4 registers.  This model only models fast-mode accesses, and
/// only in the precise way that PORE engines use fast-mode controllers for
/// memory fetches, loads and stores.  It will return errors for use of the
/// legacy mode registers or otherwise legal sequences that are simply not
/// modeled.
///
/// Each controller manages a number of "ports".  Each port is a physical I2C
/// bus, and devices attached to each port (bus) must have unique device IDs.
/// We model the devices attached to a port independently.  Each controller
/// maintains a list of I2cDevice mapped to its ports.  The underlying
/// devices are currently all of the I2cMemory class.

class 
vsbe::FastI2cController : public PibSlave
{
    
public:

    //////////////////////////////   Types  //////////////////////////////

    /// \enum FastI2cState
    ///
    /// The state of the controller.  Sequences of register operations are
    /// only allowed in a prescribed sequence, depending on the state of the
    /// controller. The ERROR state represents a bug in the model and is
    /// non-recoverable.
    enum FastI2cState {
        ERROR,
        IDLE,
        ADDRESS_WRITE_ONGOING,
        DATA_READ_ONGOING,
        DATA_AVAILABLE,
        WRITE_COMMAND_EXPECTED,
        DATA_WRITE_ONGOING
    };

    ////////////////////////////// Creators //////////////////////////////

    FastI2cController();

    virtual ~FastI2cController();

    ///////////////////////////// Accessors //////////////////////////////

    //////////////////////////// Manipulators ////////////////////////////

    /// Attach a memory model to the controller
    ///
    /// \param[in] i_memory A configured I2cMemory
    ///
    /// \param[in] i_port The port (bus) number the memory is attached to
    ///
    /// \param[in] i_deviceAddress The device ID of the memory device on the bus
    ///
    /// \retval me Either 0 for success, ME_INVALID_ARGUMENT or
    /// ME_AMBIGUOUS_CONFIGURATION.
    ModelError
    attachMemory(I2cMemory* i_memory, 
                 const unsigned i_port, 
                 const unsigned i_deviceAddress);

    /// Handle a PIB transaction
    ///
    /// \param[in,out] io_transaction An abstract PIB transaction
    ///
    /// The FastI2cController is an indirect memory. In general several PIB
    /// transactions are required to fetch a single doubleword of code or data
    /// from the memory.
    ///
    /// \retval rc Either an "OK" return code for success, or a code
    /// describing the error.
    virtual fapi::ReturnCode
    operation(Transaction& io_transaction);

    ////////////////////////// Implementation ////////////////////////////

protected:

    /// Find a device in the list of devices attached to this controller
    ///
    /// \param[in] i_port The port number to search
    ///
    /// \param[in] i_deviceAddress The device address to search
    ///
    /// \retval device A pointer to the device if found, otherwise 0.
    I2cDevice* findDevice(const unsigned i_port, 
                          const unsigned i_deviceAddress);

    /// Extract the I2C address from the CONTROL register
    ///
    /// \param[in] i_control The FastI2cControl register
    ///
    /// \retval address The indirect I2C address, taken from bytes 4-7 of the
    /// control register depending on how many address bytes are indicated in
    /// the control.
    uint32_t getI2cAddress(const FastI2cControlRegister i_control);

    /// Perform an I2C address write to an attached device.
    ///
    /// \retval me A ModelError return code in the event of errors, otherwise
    /// 0.
    ModelError addressWrite();

    /// Perform an I2C data read from an attached device.
    ///
    /// \retval me A ModelError return code in the event of errors, otherwise
    /// 0.
    ModelError dataRead();

    /// Begin an I2C data write an attached device.
    ///
    /// \retval me A ModelError return code in the event of errors, otherwise
    /// 0.
    ModelError initialDataWrite();

    /// Finalize an I2C data write an attached device.
    ///
    /// \param[in] i_data The final bytes of a data write, left justtified.
    ///
    /// \retval me A ModelError return code in the event of errors, otherwise
    /// 0.
    ModelError finalDataWrite(const uint64_t i_data);

    /// A list of I2cDevice, each of which is assigned to a controler port and
    /// maintains a unique device ID for that port.
    I2cDevice* iv_devices;

    /// The abstract state of the controller
    FastI2cState iv_state;

    /// The last value written to the control register
    FastI2cControlRegister iv_control;

    /// The last value generated in the status register
    FastI2cStatusRegister iv_status;

    /// The last value written to the data register
    uint64_t iv_data;

    /// The data FIFO.  Data is left-justified in this register.
    uint64_t iv_fifo;


    ///////////////////////////// Safety //////////////////////////////////

private:
    FastI2cController(const FastI2cController& i_rhs);
    FastI2cController& operator=(const FastI2cController& i_rhs);
};



////////////////////////////////////////////////////////////////////////////
// LpcController
////////////////////////////////////////////////////////////////////////////

/// Simplified model of the LPC controller as a fast-mode I2C controller
///
/// The LPC controller appears as a pseudo-FastI2cController with a couple of
/// extra specializations.  
///
/// - The fast-mode I2C controller specification is extended with two extra
/// registers : The ECC start and stop addresses. We do not model ECC in our
/// model, therefore this model only allows accesses that fall within the ECC
/// window.  The SBE will never address outside of the ECC window.

class
vsbe::LpcController : public FastI2cController
{

public:

    //////////////////////////////   Types  //////////////////////////////

    ////////////////////////////// Creators //////////////////////////////

    LpcController();

    virtual ~LpcController();

    ///////////////////////////// Accessors //////////////////////////////

    //////////////////////////// Manipulators ////////////////////////////

    /// Handle a PIB transaction
    ///
    /// \param[in,out] io_transaction An abstract PIB transaction
    ///
    /// The LpcController is an indirect memory. In general several PIB
    /// transactions are required to fetch a single doubleword of code or data
    /// from the memory.  The LpcController passes all transactions through to
    /// the underlying FastI2cController except for reads/writes to the ECC
    /// control registers.  We require that any change to the ECC bounds be
    /// made while the controller is in its IDLE state.
    ///
    /// \retval rc Either an "OK" return code for success, or a code
    /// describing the error.
    virtual fapi::ReturnCode
    operation(Transaction& io_transaction);

    ////////////////////////// Implementation ////////////////////////////

protected:

    /// The ECC start address register
    uint64_t iv_eccStart;

    /// The ECC stop address register
    uint64_t iv_eccStop;
};


#endif  // __VSBE_FASTI2C_H
OpenPOWER on IntegriCloud