summaryrefslogtreecommitdiffstats
path: root/sys/contrib/octeon-sdk/cvmx-twsi-raw.c
blob: 0b82325af4c0052dcc37060cb65217aa54aabbd4 (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
/***********************license start***************
 * Copyright (c) 2003-2007, Cavium Networks. All rights reserved.
 *
 * This software file (the "File") is owned and distributed by Cavium
 * Networks ("Cavium") under the following dual licensing option: The dual
 * licensing option gives you, the licensee, the choice between the following
 * alternative licensing terms.  Once you have made an election to use the
 * File under one of the following alternative licensing terms (license
 * types) you are bound by the respective terms and you may distribute the
 * file (or any derivative thereof), to the extent allowed by the respective
 * licensing term, only if you (i) delete this introductory statement
 * regarding the dual licensing option from the file you will distribute,
 * (ii) delete the licensing term that you have elected NOT to use from the
 * file you will distribute and (iii) follow the respective licensing term
 * that you have elected to use with respect to the correct attribution or
 * licensing term that you have to include with your distribution.
 *
 * ***
 * OCTEON SDK License Type 2:
 *
 * IMPORTANT: Read this Agreement carefully before clicking on the "I accept"
 * button to download the Software and/or before using the Software.  This
 * License Agreement (the "Agreement") is a legal agreement between you,
 * either an individual or a single legal entity ("You" or "you"), and Cavium
 * Networks ("Cavium").  This Agreement governs your use of the Cavium
 * software that can be downloaded after accepting this Agreement and/or that
 * is accompanied by this Agreement (the "Software").  You must accept the
 * terms of this Agreement before downloading and/or using the Software.  By
 * clicking on the "I accept" button to download and/or by using the
 * Software, you are indicating that you have read and understood, and assent
 * to be bound by, the terms of this Agreement.  If you do not agree to the
 * terms of the Agreement, you are not granted any rights whatsoever in the
 * Software.  If you are not willing to be bound by these terms and
 * conditions, you should not use or cease all use of the Software.  This
 * Software is the property of Cavium Networks and constitutes the
 * proprietary information of Cavium Networks.  You agree to take reasonable
 * steps to prevent the disclosure, unauthorized use or unauthorized
 * distribution of the Software to any third party.
 *
 * License Grant.  Subject to the terms and conditions of this Agreement,
 * Cavium grants you a nonexclusive, non-transferable, worldwide, fully-paid
 * and royalty-free license to
 *
 * (a) install, reproduce, and execute the executable version of the Software
 * solely for your internal use and only (a) on hardware manufactured by
 * Cavium, or (b) software of Cavium that simulates Cavium hardware;
 *
 * (b) create derivative works of any portions of the Software provided to
 * you by Cavium in source code form, which portions enable features of the
 * Cavium hardware products you or your licensees are entitled to use,
 * provided that any such derivative works must be used only (a) on hardware
 * manufactured by Cavium, or (b) software of Cavium that simulates Cavium
 * hardware; and
 *
 * (c) distribute derivative works you created in accordance with clause (b)
 * above, only in executable form and only if such distribution (i)
 * reproduces the copyright notice that can be found at the very end of this
 * Agreement and (ii) is pursuant to a binding license agreement that
 * contains terms no less restrictive and no less protective of Cavium than
 * this Agreement.  You will immediately notify Cavium if you become aware of
 * any breach of any such license agreement.
 *
 * Restrictions.  The rights granted to you in this Agreement are subject to
 * the following restrictions: Except as expressly set forth in this
 * Agreement (a) you will not license, sell, rent, lease, transfer, assign,
 * display, host, outsource, disclose or otherwise commercially exploit or
 * make the Software, or any derivatives you create under this Agreement,
 * available to any third party; (b) you will not modify or create derivative
 * works of any part of the Software; (c) you will not access or use the
 * Software in order to create similar or competitive products, components,
 * or services; and (d), no part of the Software may be copied (except for
 * the making of a single archival copy), reproduced, distributed,
 * republished, downloaded, displayed, posted or transmitted in any form or
 * by any means.
 *
 * Ownership.  You acknowledge and agree that, subject to the license grant
 * contained in this Agreement and as between you and Cavium (a) Cavium owns
 * all copies of and intellectual property rights to the Software, however
 * made, and retains all rights in and to the Software, including all
 * intellectual property rights therein, and (b) you own all the derivate
 * works of the Software created by you under this Agreement, subject to
 * Cavium's rights in the Software.  There are no implied licenses under this
 * Agreement, and any rights not expressly granted to your hereunder are
 * reserved by Cavium.  You will not, at any time, contest anywhere in the
 * world Cavium's ownership of the intellectual property rights in and to the
 * Software.
 *
 * Disclaimer of Warranties.  The Software is provided to you free of charge,
 * and on an "As-Is" basis.  Cavium provides no technical support, warranties
 * or remedies for the Software.  Cavium and its suppliers disclaim all
 * express, implied or statutory warranties relating to the Software,
 * including but not limited to, merchantability, fitness for a particular
 * purpose, title, and non-infringement.  Cavium does not warrant that the
 * Software and the use thereof will be error-free, that defects will be
 * corrected, or that the Software is free of viruses or other harmful
 * components.  If applicable law requires any warranties with respect to the
 * Software, all such warranties are limited in duration to thirty (30) days
 * from the date of download or first use, whichever comes first.
 *
 * Limitation of Liability.  Neither Cavium nor its suppliers shall be
 * responsible or liable with respect to any subject matter of this Agreement
 * or terms or conditions related thereto under any contract, negligence,
 * strict liability or other theory (a) for loss or inaccuracy of data or
 * cost of procurement of substitute goods, services or technology, or (b)
 * for any indirect, incidental or consequential damages including, but not
 * limited to loss of revenues and loss of profits.  Cavium's aggregate
 * cumulative liability hereunder shall not exceed the greater of Fifty U.S.
 * Dollars (U.S.$50.00) or the amount paid by you for the Software that
 * caused the damage.  Certain states and/or jurisdictions do not allow the
 * exclusion of implied warranties or limitation of liability for incidental
 * or consequential damages, so the exclusions set forth above may not apply
 * to you.
 *
 * Basis of Bargain.  The warranty disclaimer and limitation of liability set
 * forth above are fundamental elements of the basis of the agreement between
 * Cavium and you.  Cavium would not provide the Software without such
 * limitations.  The warranty disclaimer and limitation of liability inure to
 * the benefit of Cavium and Cavium's suppliers.
 *
 * Term and Termination.  This Agreement and the licenses granted hereunder
 * are effective on the date you accept the terms of this Agreement, download
 * the Software, or use the Software, whichever comes first, and shall
 * continue unless this Agreement is terminated pursuant to this section.
 * This Agreement immediately terminates in the event that you materially
 * breach any of the terms hereof.  You may terminate this Agreement at any
 * time, with or without cause, by destroying any copies of the Software in
 * your possession.  Upon termination, the license granted hereunder shall
 * terminate but the Sections titled "Restrictions", "Ownership", "Disclaimer
 * of Warranties", "Limitation of Liability", "Basis of Bargain", "Term and
 * Termination", "Export", and "Miscellaneous" will remain in effect.
 *
 * Export.  The Software and related technology are subject to U.S.  export
 * control laws and may be subject to export or import regulations in other
 * countries.  You agree to strictly comply with all such laws and
 * regulations and acknowledges that you have the responsibility to obtain
 * authorization to export, re-export, or import the Software and related
 * technology, as may be required.  You will indemnify and hold Cavium
 * harmless from any and all claims, losses, liabilities, damages, fines,
 * penalties, costs and expenses (including attorney's fees) arising from or
 * relating to any breach by you of your obligations under this section.
 * Your obligations under this section shall survive the expiration or
 * termination of this Agreement.
 *
 * Miscellaneous.  Neither the rights nor the obligations arising under this
 * Agreement are assignable by you, and any such attempted assignment or
 * transfer shall be void and without effect.  This Agreement shall be
 * governed by and construed in accordance with the laws of the State of
 * California without regard to any conflicts of laws provisions that would
 * require application of the laws of another jurisdiction.  Any action under
 * or relating to this Agreement shall be brought in the state and federal
 * courts located in California, with venue in the courts located in Santa
 * Clara County and each party hereby submits to the personal jurisdiction of
 * such courts; provided, however, that nothing herein will operate to
 * prohibit or restrict Cavium from filing for and obtaining injunctive
 * relief from any court of competent jurisdiction.  The United Nations
 * Convention on Contracts for the International Sale of Goods shall not
 * apply to this Agreement.  In the event that any provision of this
 * Agreement is found to be contrary to law, then such provision shall be
 * construed as nearly as possible to reflect the intention of the parties,
 * with the other provisions remaining in full force and effect.  Any notice
 * to you may be provided by email.  This Agreement constitutes the entire
 * agreement between the parties and supersedes all prior or contemporaneous,
 * agreements, understandings and communications between the parties, whether
 * written or oral, pertaining to the subject matter hereof.  Any
 * modifications of this Agreement must be in writing and agreed to by both
 * parties.
 *
 * Copyright (c) 2003-2007, Cavium Networks. All rights reserved.
 *
 * ***
 *
 * OCTEON SDK License Type 4:
 *
 * Author: Cavium Networks
 *
 * Contact: support@caviumnetworks.com
 * This file is part of the OCTEON SDK
 *
 * Copyright (c) 2007 Cavium Networks
 *
 * This file is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License, Version 2, as published by
 * the Free Software Foundation.
 *
 * This file is distributed in the hope that it will be useful,
 * but AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or NONINFRINGEMENT.
 * See the GNU General Public License for more details.
 * it under the terms of the GNU General Public License, Version 2, as published by
 * the Free Software Foundation.
 *
 * You should have received a copy of the GNU General Public License
 * along with this file; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
 * or visit http://www.gnu.org/licenses/.
 *
 * This file may also be available under a different license from Cavium.
 * Contact Cavium Networks for more information
 ***********************license end**************************************/


/*
 * This code is an example of using twsi core in raw mode, bypasing High 
 * Level Controller (HLC). It is recommended to use HLC if only possible as 
 * it is more efficient and robust mechanism. 
 * The example code shows use of twsi for generating long (more that 8 bytes HLC limit) 
 * read - write transactions using 7-bit addressing. Different types of 
 * transactions can be generated if needed. Make sure that commands written to twsi core 
 * follow core state transitions outlinged in OCTEON documentation. The core state is 
 * reported in stat register after the command colpletion. In each state core will accept
 *  only the allowed commands.
 */
 
#include <stdio.h>
#include <cvmx.h>
#include <cvmx-csr-typedefs.h>
#include "cvmx-twsi-raw.h"

/*
 * uint8_t cvmx_twsix_read_ctr(int twsi_id, uint8_t reg)
 * twsi core register read
 * twsi_id - twsi core index
 * reg 0 - 8-bit register
 * returns 8-bit register contetn
 */
uint8_t cvmx_twsix_read_ctr(int twsi_id, uint8_t reg)
{
    cvmx_mio_twsx_sw_twsi_t sw_twsi_val;

    sw_twsi_val.u64 = 0;
    sw_twsi_val.s.v = 1;
    sw_twsi_val.s.op = 6;
    sw_twsi_val.s.eop_ia = reg;
    sw_twsi_val.s.r = 1;
    cvmx_write_csr(CVMX_MIO_TWSX_SW_TWSI(twsi_id), sw_twsi_val.u64);
    while (((cvmx_mio_twsx_sw_twsi_t)(sw_twsi_val.u64 = cvmx_read_csr(CVMX_MIO_TWSX_SW_TWSI(twsi_id)))).s.v)
        ;
    return sw_twsi_val.s.d ;
}

/*
 * uint8_t cvmx_twsix_write_ctr(int twsi_id, uint8_t reg, uint8_t data)
 *
 * twsi core register write
 * twsi_id - twsi core index
 * reg 0 - 8-bit register
 * data - data to write
 * returns 0;
 */

int cvmx_twsix_write_ctr(int twsi_id, uint8_t reg, uint8_t data)
{
    cvmx_mio_twsx_sw_twsi_t sw_twsi_val;

    sw_twsi_val.u64 = 0;
    sw_twsi_val.s.v = 1;
    sw_twsi_val.s.op = 6;
    sw_twsi_val.s.eop_ia = reg;
    sw_twsi_val.s.d = data;
    cvmx_write_csr(CVMX_MIO_TWSX_SW_TWSI(twsi_id), sw_twsi_val.u64);
    while (((cvmx_mio_twsx_sw_twsi_t)(sw_twsi_val.u64 = cvmx_read_csr(CVMX_MIO_TWSX_SW_TWSI(twsi_id)))).s.v)
        ;

    return 0;
}

/*
 * cvmx_twsi_wait_iflg(int twsi_id)
 * cvmx_twsi_wait_stop(int twsi_id)
 *
 * Helper functions. 
 * Busy wait for interrupt flag or stop bit on control register. This implementation is for OS-less 
 * application. With OS services available it could be implemented with semaphore
 * block and interrupt wake up. 
 * TWSI_WAIT for loop must be defined large enough to allow on-wire transaction to finish - that is 
 * about 10 twsi clocks
 */
#define TWSI_WAIT 10000000
static inline int cvmx_twsi_wait_iflg(int twsi_id)
{
    octeon_twsi_ctl_t ctl_reg;
    int wait = TWSI_WAIT;
    do{
        ctl_reg.u8 = cvmx_twsix_read_ctr(twsi_id, TWSI_CTL_REG);
    } while((ctl_reg.s.iflg ==0) && (wait-- >0));
    if(wait == 0) return -1;
    return 0;
}

static inline int cvmx_twsi_wait_stop(int twsi_id)
{
    octeon_twsi_ctl_t ctl_reg;
    int wait = TWSI_WAIT;
    do{
        ctl_reg.u8 = cvmx_twsix_read_ctr(twsi_id, TWSI_CTL_REG);
    } while((ctl_reg.s.stp ==1) && (wait-- >0));
    if(wait == 0) return -1;
    return 0;
}


/*
 * uint8_t octeon_twsi_read_byte(int twsi_id, uint8_t* byte, int ack) 
 * uint8_t octeon_twsi_write_byte(int twsi_id, uint8_t byte)
 *
 * helper functions - read or write byte to data reg and reads the TWSI core status
 */
static uint8_t octeon_twsi_read_byte(int twsi_id, uint8_t* byte, int ack)
{
    octeon_twsi_ctl_t ctl_reg;
    octeon_twsi_data_t data;
    octeon_twsi_stat_t stat;

    /* clear interrupt flag, set aak for requested ACK signal level */
    ctl_reg.u8 =0;
    ctl_reg.s.aak = (ack==0) ?0:1;
    ctl_reg.s.enab =1;
    cvmx_twsix_write_ctr(twsi_id, TWSI_CTL_REG, ctl_reg.u8);

    /* wait for  twsi_ctl[iflg] to be set */
    if(cvmx_twsi_wait_iflg(twsi_id)) goto error;

    /* read the byte */
    data.u8 =cvmx_twsix_read_ctr(twsi_id, TWSI_DATA_REG);
    *byte = data.s.data;
error:
    /* read the status */
    stat.u8 = cvmx_twsix_read_ctr(twsi_id, TWSI_STAT_REG);
    return stat.s.stat;
}

static uint8_t octeon_twsi_write_byte(int twsi_id, uint8_t byte)
{
    octeon_twsi_ctl_t ctl_reg;
    octeon_twsi_data_t data;
    octeon_twsi_stat_t stat;

    /* tx data byte - write to twsi_data reg, then clear twsi_ctl[iflg] */
    data.s.data = byte;
    cvmx_twsix_write_ctr(twsi_id, TWSI_DATA_REG, data.u8);

    ctl_reg.u8 = cvmx_twsix_read_ctr(twsi_id, TWSI_CTL_REG);
    ctl_reg.s.iflg =0;
    cvmx_twsix_write_ctr(twsi_id, TWSI_CTL_REG, ctl_reg.u8);

    /* wait for  twsi_ctl[iflg] to be set */
    if(cvmx_twsi_wait_iflg(twsi_id)) goto error;
error:
     /* read the status */
     stat.u8 = cvmx_twsix_read_ctr(twsi_id, TWSI_STAT_REG);
     return stat.s.stat;
}

/*
 * int octeon_i2c_xfer_msg_raw(struct i2c_msg *msg)
 *
 * Send (read or write) a message with 7-bit address device over direct control of 
 * TWSI core, bypassind HLC. Will try to finish the transaction on failure, so core state
 * expected to be idle with HLC enabled on exit.
 *
 * dev - TWSI controller index (0 for cores with single controler)
 * msg - message to transfer
 * returns 0 on success, TWSI core state on error. Will try to finish the transaction on failure, so core state expected to be idle
 */
int octeon_i2c_xfer_msg_raw(int twsi_id, struct i2c_msg *msg)
{
    int i =0;
    octeon_twsi_ctl_t ctl_reg;
    octeon_twsi_addr_t addr;
    octeon_twsi_stat_t stat;
    int is_read = msg->flags & I2C_M_RD;
    int ret =0;

    /* check the core state, quit if not idle */
    stat.u8 =cvmx_twsix_read_ctr(twsi_id, TWSI_STAT_REG);
    if(stat.s.stat != TWSI_IDLE) {
       msg->len =0; return stat.s.stat;
    }

    /* first send start - set twsi_ctl[sta] to 1 */
    ctl_reg.u8 =0;
    ctl_reg.s.enab =1;
    ctl_reg.s.sta =1;
    ctl_reg.s.iflg =0;
    cvmx_twsix_write_ctr(twsi_id, TWSI_CTL_REG, ctl_reg.u8);
    /* wait for  twsi_ctl[iflg] to be set */
    if(cvmx_twsi_wait_iflg(twsi_id)) goto stop;

    /* Write 7-bit addr to twsi_data; set read bit */
    addr.s.slave_addr7 = msg->addr;
    if(is_read) addr.s.r =1;
    else addr.s.r =0;
    stat.s.stat =octeon_twsi_write_byte(twsi_id, addr.u8);

    /* Data read loop */
    if( is_read) {
    /* any status but ACK_RXED means failure - we try to send stop and go idle */
      if(!(stat.s.stat == TWSI_ADDR_R_TX_ACK_RXED)) {
      ret = stat.s.stat;
      msg->len =0;
      goto stop;
     }
     /* We read data from the buffer and send ACK back.
       The last byte we read with negative ACK */
      for(i =0; i<msg->len-1; i++)
      {
        stat.s.stat =octeon_twsi_read_byte(twsi_id, &msg->buf[i], 1);
        if(stat.s.stat != TWSI_DATA_RX_ACK_TXED)
           goto stop;
      }
      /* last read we send negACK */
      stat.s.stat =octeon_twsi_read_byte(twsi_id, &msg->buf[i], 0);
        if(stat.s.stat != TWSI_DATA_RX_NACK_TXED)
             return stat.s.stat;
    } /* read loop */

    /* Data write loop */
    else {
    /* any status but ACK_RXED means failure - we try to send stop and go idle */
      if(stat.s.stat != TWSI_ADDR_W_TX_ACK_RXED) {
          ret = stat.s.stat;
          msg->len =0;
          goto stop;
      }
      /* We write data to the buffer and check for ACK. */
      for(i =0; i<msg->len; i++)
      {
          stat.s.stat =octeon_twsi_write_byte(twsi_id, msg->buf[i]);
          if(stat.s.stat == TWSI_DATA_TX_NACK_RXED) {
              /* Negative ACK means slave can not RX more */
              msg->len =i-1;
              goto stop;
          }
          else if(stat.s.stat != TWSI_DATA_TX_ACK_RXED) {
              /* lost arbitration? try to send stop and go idle. This current byte likely was not written */
              msg->len = (i-2) >0? (i-2):0;
              goto stop;
          }
      }
    }  /* write loop */

stop:
    ctl_reg.u8 =cvmx_twsix_read_ctr(twsi_id, TWSI_CTL_REG);
    ctl_reg.s.stp =1;
    ctl_reg.s.iflg =0;
    cvmx_twsix_write_ctr(twsi_id, TWSI_CTL_REG, ctl_reg.u8);
    /* wait for  twsi_ctl[stp] to clear */
    cvmx_twsi_wait_stop(twsi_id);
#if 0
    stat.u8 = cvmx_twsix_read_ctr(twsi_id, TWSI_STAT_REG);
    if(stat.s.stat == TWSI_IDLE)
#endif
    /* Leave TWSI core with HLC eabled */
    {
       ctl_reg.u8 =0;
       ctl_reg.s.ce =1;
       ctl_reg.s.enab =1;
       ctl_reg.s.aak =1;
       cvmx_twsix_write_ctr(twsi_id, TWSI_CTL_REG, ctl_reg.u8);
    }

    return ret;
}

OpenPOWER on IntegriCloud