root/i2c/trunk/kernel/i2c-algo-biths.h @ 3749

Revision 3749, 5.5 KB (checked in by kmalkki, 10 years ago)

(Kyösti) Use rdtscl() on x86 machines to get better resolution for bus

speed. Currently running this at 1 MHz (250ns delay) on a BT848
board with no problems so far. Falls back to udelay() with maximum
bus clock of 250 kHz if rdtscl() not defined.

Byte and bit level access functions now loop internally over write
and read buffer to remove a considerable amount of stack operations.

Divide flags to ctrl and errors, and other changes in
i2c_algo_biths_data.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/* ------------------------------------------------------------------------- */
2/* i2c-algo-biths.h i2c driver algorithms for faster bit-shift adapters      */
3/* ------------------------------------------------------------------------- */
4/*   Copyright (C) 1995-99 Simon G. Vogl
5
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 2 of the License, or
9    (at your option) any later version.
10
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.                */
19/* ------------------------------------------------------------------------- */
20
21/* With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi> and even
22   Frodo Looijaard <frodol@dds.nl> */
23
24/* $Id$ */
25
26#ifndef I2C_ALGO_BITHS_H
27#define I2C_ALGO_BITHS_H 1
28
29#include "i2c.h"
30#include <linux/sched.h>
31
32#if 1
33#define _HS_ATTR_
34#else
35#define _HS_ATTR_ __attribute__ ((regparm (2)))
36#endif
37
38#ifdef _HW_NO_INLINE_
39#define _HW_ATTR_ __attribute__ ((regparm (2)))
40#else
41#define _HW_ATTR_ inline
42#endif
43
44/* --- Defines for bit-adapters --------------------------------------- */
45/*
46 * This struct contains the hw-dependent functions of bit-style adapters to
47 * manipulate the line states, and to init any hw-specific features. This is
48 * only used if you have more than one hw-type of adapter running.
49 */
50struct i2c_algo_biths_data {
51        void *hw_data;          /* private data for lowlevel routines */
52        int hw_state;
53        void (*setscl)(struct i2c_algo_biths_data *adap) _HS_ATTR_ ;
54        void (*setsda)(struct i2c_algo_biths_data *adap) _HS_ATTR_ ;
55        int (*getscl) (struct i2c_algo_biths_data *adap) _HS_ATTR_ ;
56        int (*getsda) (struct i2c_algo_biths_data *adap) _HS_ATTR_ ;
57
58        void (*setstate)(struct i2c_algo_biths_data *adap) _HS_ATTR_ ;
59        void (*set_timer)(struct i2c_algo_biths_data *adap) _HS_ATTR_ ;
60        void (*run_timer)(struct i2c_algo_biths_data *adap) _HS_ATTR_ ;
61
62        short ctrl;
63        short errors;
64        char shiftreg;
65
66        /* local settings */
67        unsigned long bclock;
68        unsigned long xloops;   /* 1/4 clock-cycle time in x86 TSC ticks */
69                                /* i.e. bus clock is 250*0x10c6 / xloops kHz */
70
71        int timeout;            /* in jiffies */
72        char *name;             /* replicate i2c_adapter->name */
73        char *dstr;             /* protocol debug string */
74};
75
76#define I2C_BIT_ADAP_MAX        16
77
78#define _HS_SCL         0x0001
79#define _HS_SDA         0x0002
80#define _HS_SDA_FREE    0x0004  /* client has SDA control */
81#define _HS_STD_MODE    0x0008  /* drop speed to 100kHz */
82#define _HS_DBL_DT      0x0010  /* T_sclhi is twice longer */
83
84#define _HS_NAK         0x0001
85#define _HS_TIMEOUT     0x0002
86#define _HS_SDA_ARB     0x0004
87#define _HS_HW_FAIL     0x0008
88
89int i2c_biths_add_bus(struct i2c_adapter *);
90int i2c_biths_del_bus(struct i2c_adapter *);
91
92#endif /* I2C_ALGO_BITHS_H */
93
94#ifdef INCLUDE_BITHS_INLINES
95
96/* --- setting states on the bus with the right timing: --------------- */
97
98#define _hw_timer_set(adap) adap->set_timer(adap)
99#define _hw_timer_run(adap) adap->run_timer(adap)
100
101static inline int sda_not_set(struct i2c_algo_biths_data *adap, int rdcount)
102{
103    int sda;
104    /* allow some rise/fall time */
105    while ( rdcount-- ) {
106        sda = _hw_getsda(adap->hw_data);
107        if (adap->ctrl & _HS_SDA) {
108            if (sda)
109                return 0;
110            if (!rdcount) {
111                adap->errors |= _HS_SDA_ARB;
112                return -1;
113            }
114        } else { /* !(adap->ctrl & _HS_SDA) */
115            if (!sda)
116                return 0;
117            if (!rdcount) {
118                adap->errors |= _HS_HW_FAIL;
119                return -1;
120            }
121        }
122    }
123    return 0;
124}
125
126static inline void i2c_bit_setsda(struct i2c_algo_biths_data *adap)
127{
128    _hw_setsda(adap->hw_data, adap->hw_state);
129    if ( !(adap->ctrl & _HS_SDA_FREE) && sda_not_set(adap, 10)) {
130        return;
131    }
132    _hw_timer_set(adap);
133    _hw_timer_run(adap);
134}
135
136/*
137 * Raise scl line, and do check for delays. This is necessary for slower
138 * devices.
139 */
140
141static inline void i2c_bit_setscl(struct i2c_algo_biths_data *adap)
142{
143#ifndef HW_CANNOT_READ_SCL /* Not all adapters have scl sense line... */
144    int rdcount = 10;
145    _hw_setscl(adap->hw_data, adap->hw_state);
146    if (adap->ctrl & _HS_SCL) {
147        unsigned long start;
148        /* allow some rise time */
149        while (rdcount && !_hw_getscl(adap->hw_data)) rdcount--;
150        /* else clock synchronisation, give more time */
151        start = jiffies;
152        while (!rdcount && !_hw_getscl(adap->hw_data)) {
153            if ( time_after(jiffies, start+adap->timeout) ) {
154                adap->errors |= _HS_TIMEOUT; /* scl undef */
155                return;
156            }
157#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
158            if (current->need_resched)
159                schedule();
160#else
161            cond_resched();
162#endif
163        }
164        _hw_timer_set(adap);
165        /* test for SDA arbitration when SCL is high */
166        if ( !(adap->ctrl & _HS_SDA_FREE) && sda_not_set(adap, 1)) {
167            return;
168        }
169    } else {
170        /* allow some fall time */
171        while (rdcount && _hw_getscl(adap->hw_data)) rdcount--;
172        if ( !rdcount ) {
173            adap->errors |= _HS_HW_FAIL;
174            return;
175        }
176        _hw_timer_set(adap);
177    }
178#else
179    _hw_setscl(adap->hw_data, adap->hw_state);
180    _hw_timer_set(adap);
181#endif /* HW_CANNOT_READ_SCL */
182    _hw_timer_run(adap);
183}
184
185static inline int i2c_bit_getscl(struct i2c_algo_biths_data *adap)
186{
187    return _hw_getscl(adap->hw_data);
188}
189
190static inline int i2c_bit_getsda(struct i2c_algo_biths_data *adap)
191{
192    return _hw_getsda(adap->hw_data);
193}
194
195#endif
Note: See TracBrowser for help on using the browser.