1 | /* $Id$ */ |
---|
2 | |
---|
3 | /* Trivial i2c driver for reading "2-byte eeproms". |
---|
4 | * On 'open' the read-pointer is reset to 0, subsequent |
---|
5 | * read operations slurp data from there... |
---|
6 | */ |
---|
7 | |
---|
8 | /* Author: Till Straumann, 2005 */ |
---|
9 | |
---|
10 | |
---|
11 | #include <rtems.h> |
---|
12 | #include <rtems/libi2c.h> |
---|
13 | |
---|
14 | #include <libchip/i2c-2b-eeprom.h> |
---|
15 | #include <rtems/libio.h> |
---|
16 | |
---|
17 | #define EEPROM_PG_SZ 32 |
---|
18 | #define ALGN(x) (((uint32_t)(x) + EEPROM_PG_SZ) & ~(EEPROM_PG_SZ-1)) |
---|
19 | |
---|
20 | static rtems_status_code |
---|
21 | send_file_ptr (rtems_device_minor_number minor, unsigned pos, int tout) |
---|
22 | { |
---|
23 | int sc; |
---|
24 | unsigned char bytes[2]; |
---|
25 | |
---|
26 | bytes[0] = (pos >> 8) & 0xff; |
---|
27 | bytes[1] = (pos) & 0xff; |
---|
28 | |
---|
29 | /* poll addressing the next page; if 'tout' is <=0 we only try once |
---|
30 | * and return the status. If 'tout' is positive, we try 'tout' times |
---|
31 | * and return RTEMS_TIMEOUT if it didnt work |
---|
32 | */ |
---|
33 | while ((sc = rtems_libi2c_start_write_bytes (minor, bytes, 2)) < 0) { |
---|
34 | if (--tout <= 0) |
---|
35 | return tout ? -sc : RTEMS_TIMEOUT; |
---|
36 | rtems_task_wake_after (1); |
---|
37 | } |
---|
38 | return RTEMS_SUCCESSFUL; |
---|
39 | } |
---|
40 | |
---|
41 | static rtems_status_code |
---|
42 | i2c_2b_eeprom_write (rtems_device_major_number major, |
---|
43 | rtems_device_minor_number minor, void *arg) |
---|
44 | { |
---|
45 | rtems_libio_rw_args_t *rwargs = arg; |
---|
46 | unsigned off = rwargs->offset; |
---|
47 | int cnt = rwargs->count; |
---|
48 | char *buf = rwargs->buffer; |
---|
49 | int sc; |
---|
50 | unsigned end; |
---|
51 | int l; |
---|
52 | |
---|
53 | if (cnt <= 0) |
---|
54 | return RTEMS_SUCCESSFUL; |
---|
55 | |
---|
56 | if ((sc = send_file_ptr (minor, off, 0))) |
---|
57 | return sc; |
---|
58 | |
---|
59 | do { |
---|
60 | /* write up to next page boundary */ |
---|
61 | end = ALGN (off); |
---|
62 | l = end - off; |
---|
63 | if (l > cnt) |
---|
64 | l = cnt; |
---|
65 | |
---|
66 | sc = rtems_libi2c_write_bytes (minor, buf, l); |
---|
67 | if (sc < 0) |
---|
68 | return -sc; |
---|
69 | |
---|
70 | sc = rtems_libi2c_send_stop (minor); |
---|
71 | if (sc) |
---|
72 | return sc; |
---|
73 | |
---|
74 | rwargs->bytes_moved += l; |
---|
75 | |
---|
76 | buf += l; |
---|
77 | cnt -= l; |
---|
78 | off += l; |
---|
79 | |
---|
80 | /* poll addressing the next page */ |
---|
81 | if ((sc = send_file_ptr (minor, off, 100))) |
---|
82 | return sc; |
---|
83 | |
---|
84 | } while (cnt > 0); |
---|
85 | |
---|
86 | return rtems_libi2c_send_stop (minor); |
---|
87 | } |
---|
88 | |
---|
89 | static rtems_status_code |
---|
90 | i2c_2b_eeprom_read (rtems_device_major_number major, |
---|
91 | rtems_device_minor_number minor, void *arg) |
---|
92 | { |
---|
93 | int sc; |
---|
94 | rtems_libio_rw_args_t *rwargs = arg; |
---|
95 | |
---|
96 | if (RTEMS_SUCCESSFUL != (sc = send_file_ptr (minor, rwargs->offset, 0))) |
---|
97 | return -sc; |
---|
98 | |
---|
99 | sc = rtems_libi2c_start_read_bytes (minor, rwargs->buffer, rwargs->count); |
---|
100 | |
---|
101 | if (sc < 0) { |
---|
102 | rwargs->bytes_moved = 0; |
---|
103 | return -sc; |
---|
104 | } |
---|
105 | rwargs->bytes_moved = sc; |
---|
106 | |
---|
107 | return rtems_libi2c_send_stop (minor); |
---|
108 | } |
---|
109 | |
---|
110 | static rtems_driver_address_table myops = { |
---|
111 | read_entry: i2c_2b_eeprom_read, |
---|
112 | write_entry: i2c_2b_eeprom_write, |
---|
113 | }; |
---|
114 | |
---|
115 | static rtems_libi2c_drv_t my_drv_tbl = { |
---|
116 | ops: &myops, |
---|
117 | size: sizeof (my_drv_tbl), |
---|
118 | }; |
---|
119 | |
---|
120 | /* provide a second table for R/O access */ |
---|
121 | static rtems_driver_address_table my_ro_ops = { |
---|
122 | read_entry: i2c_2b_eeprom_read, |
---|
123 | }; |
---|
124 | |
---|
125 | static rtems_libi2c_drv_t my_ro_drv_tbl = { |
---|
126 | ops: &my_ro_ops, |
---|
127 | size: sizeof (my_ro_drv_tbl), |
---|
128 | }; |
---|
129 | |
---|
130 | |
---|
131 | rtems_libi2c_drv_t *i2c_2b_eeprom_driver_descriptor = &my_drv_tbl; |
---|
132 | rtems_libi2c_drv_t *i2c_2b_eeprom_ro_driver_descriptor = &my_ro_drv_tbl; |
---|