1.1 --- a/pkg/devices/lib/i2c/include/i2c-jz4780.h Sun Jul 21 22:23:06 2019 +0200
1.2 +++ b/pkg/devices/lib/i2c/include/i2c-jz4780.h Mon Jul 22 00:17:30 2019 +0200
1.3 @@ -52,9 +52,16 @@
1.4 uint32_t frequency);
1.5
1.6 void set_target(uint8_t addr);
1.7 +
1.8 + // Reading initiation and execution.
1.9 +
1.10 void start_read(uint8_t buf[], unsigned int total);
1.11 void read();
1.12 - void write(uint8_t buf[], unsigned int total);
1.13 +
1.14 + // Writing initiation and execution.
1.15 +
1.16 + void start_write(uint8_t buf[], unsigned int total);
1.17 + void write();
1.18
1.19 // Transaction control.
1.20
1.21 @@ -64,8 +71,11 @@
1.22 // Specific status conditions.
1.23
1.24 unsigned int have_read();
1.25 + unsigned int have_written();
1.26 int read_done();
1.27 - int read_incomplete();
1.28 + int write_done();
1.29 +
1.30 + int failed();
1.31 int read_failed();
1.32 int write_failed();
1.33
1.34 @@ -83,7 +93,7 @@
1.35
1.36 void set_read_threshold();
1.37 void queue_reads();
1.38 - void queue_writes(uint8_t buf[], unsigned int *pos, unsigned int total);
1.39 + void queue_writes();
1.40 void store_reads();
1.41 };
1.42
1.43 @@ -124,13 +134,19 @@
1.44
1.45 void jz4780_i2c_read(void *i2c_channel);
1.46
1.47 +void jz4780_i2c_start_write(void *i2c_channel, uint8_t buf[], unsigned int total);
1.48 +
1.49 +void jz4780_i2c_write(void *i2c_channel);
1.50 +
1.51 int jz4780_i2c_read_done(void *i2c_channel);
1.52
1.53 +int jz4780_i2c_write_done(void *i2c_channel);
1.54 +
1.55 unsigned int jz4780_i2c_have_read(void *i2c_channel);
1.56
1.57 -int jz4780_i2c_read_incomplete(void *i2c_channel);
1.58 +unsigned int jz4780_i2c_have_written(void *i2c_channel);
1.59
1.60 -void jz4780_i2c_write(void *i2c_channel, uint8_t buf[], unsigned int total);
1.61 +int jz4780_i2c_failed(void *i2c_channel);
1.62
1.63 void jz4780_i2c_stop(void *i2c_channel);
1.64
2.1 --- a/pkg/devices/lib/i2c/src/jz4780.cc Sun Jul 21 22:23:06 2019 +0200
2.2 +++ b/pkg/devices/lib/i2c/src/jz4780.cc Mon Jul 22 00:17:30 2019 +0200
2.3 @@ -422,6 +422,36 @@
2.4 return _regs[Int_status] & Int_tx_abort;
2.5 }
2.6
2.7 +int
2.8 +I2c_jz4780_channel::read_done()
2.9 +{
2.10 + return _pos == _total;
2.11 +}
2.12 +
2.13 +int
2.14 +I2c_jz4780_channel::write_done()
2.15 +{
2.16 + return _reqpos == _total;
2.17 +}
2.18 +
2.19 +unsigned
2.20 +I2c_jz4780_channel::have_read()
2.21 +{
2.22 + return _pos;
2.23 +}
2.24 +
2.25 +unsigned
2.26 +I2c_jz4780_channel::have_written()
2.27 +{
2.28 + return _reqpos;
2.29 +}
2.30 +
2.31 +int
2.32 +I2c_jz4780_channel::failed()
2.33 +{
2.34 + return _fail;
2.35 +}
2.36 +
2.37
2.38
2.39 // Send read commands for empty queue entries.
2.40 @@ -447,12 +477,12 @@
2.41
2.42 // Queue read requests for any remaining queue entries.
2.43
2.44 - for (unsigned int i = 0; i < can_queue; i++)
2.45 + while (can_queue && can_send())
2.46 + {
2.47 _regs[Smb_data_command] = Smb_command_read;
2.48 -
2.49 - // Track queued messages and requested positions.
2.50 -
2.51 - _reqpos += can_queue;
2.52 + _reqpos++;
2.53 + can_queue--;
2.54 + }
2.55
2.56 // Issue the stop condition after the final read request.
2.57 // In practice, an extra read request works better since it does not risk a
2.58 @@ -461,19 +491,30 @@
2.59 if (_total == _reqpos)
2.60 _regs[Smb_data_command] = Smb_command_read;
2.61 //stop();
2.62 +
2.63 + // Update the threshold to be notified of any reduced remaining amount.
2.64 +
2.65 + set_read_threshold();
2.66 }
2.67
2.68 // Send write commands for empty queue entries.
2.69
2.70 void
2.71 -I2c_jz4780_channel::queue_writes(uint8_t buf[], unsigned int *pos, unsigned int total)
2.72 +I2c_jz4780_channel::queue_writes()
2.73 {
2.74 + unsigned int remaining = _total - _reqpos;
2.75 + unsigned int can_queue = Smb_fifo_limit;
2.76 +
2.77 + if (remaining < can_queue)
2.78 + can_queue = remaining;
2.79 +
2.80 // Queue write requests for any remaining queue entries.
2.81
2.82 - while ((*pos < total) && can_send() && !write_failed())
2.83 + while (can_queue && can_send())
2.84 {
2.85 - _regs[Smb_data_command] = Smb_command_write | buf[*pos];
2.86 - (*pos)++;
2.87 + _regs[Smb_data_command] = Smb_command_write | _buf[_reqpos];
2.88 + _reqpos++;
2.89 + can_queue--;
2.90 }
2.91 }
2.92
2.93 @@ -482,36 +523,27 @@
2.94 void
2.95 I2c_jz4780_channel::store_reads()
2.96 {
2.97 - int have_read = 0;
2.98 -
2.99 // Read any input and store it in the buffer.
2.100
2.101 - while (have_input() && (_pos < _total))
2.102 + while (have_input() && (_pos < _reqpos))
2.103 {
2.104 _buf[_pos] = _regs[Smb_data_command] & 0xff;
2.105 _pos++;
2.106 -
2.107 - have_read = 1;
2.108 }
2.109 -
2.110 - // Update the threshold to be notified of any reduced remaining amount.
2.111 -
2.112 - if (have_read)
2.113 - set_read_threshold();
2.114 }
2.115
2.116 void
2.117 I2c_jz4780_channel::set_read_threshold()
2.118 {
2.119 - unsigned int remaining = _total - _pos;
2.120 + unsigned int queued = _reqpos - _pos;
2.121
2.122 - if (!remaining)
2.123 + if (!queued)
2.124 return;
2.125
2.126 - // Read all remaining.
2.127 + // Read all expected.
2.128
2.129 - if (remaining <= Smb_fifo_limit)
2.130 - _regs[Rx_fifo_thold] = remaining - 1;
2.131 + if (queued <= Smb_fifo_limit)
2.132 + _regs[Rx_fifo_thold] = queued - 1;
2.133
2.134 // Read to limit.
2.135
2.136 @@ -538,53 +570,38 @@
2.137 {
2.138 if (read_failed() || write_failed())
2.139 {
2.140 -#if 0
2.141 - printf("intst*=%x\n", (uint32_t) _regs[Int_status]);
2.142 - printf("rxfifo=%d\n", (uint32_t) _regs[Rx_fifo_count] & 0x3f);
2.143 - printf("smbabtsrc=%x\n", (uint32_t) _regs[Trans_abort_status0]);
2.144 -#endif
2.145 _fail = 1;
2.146 return;
2.147 }
2.148
2.149 - if (_pos < _total)
2.150 - {
2.151 - if (_regs[Int_status] & Int_rx_full)
2.152 - store_reads();
2.153 - if (_regs[Int_status] & Int_tx_empty)
2.154 - queue_reads();
2.155 - }
2.156 -}
2.157 -
2.158 -int
2.159 -I2c_jz4780_channel::read_done()
2.160 -{
2.161 - return _pos == _total;
2.162 -}
2.163 -
2.164 -unsigned
2.165 -I2c_jz4780_channel::have_read()
2.166 -{
2.167 - return _pos;
2.168 -}
2.169 -
2.170 -int
2.171 -I2c_jz4780_channel::read_incomplete()
2.172 -{
2.173 - return _fail;
2.174 + if (_regs[Int_status] & Int_rx_full)
2.175 + store_reads();
2.176 + if (_regs[Int_status] & Int_tx_empty)
2.177 + queue_reads();
2.178 }
2.179
2.180 // Write to the target device.
2.181
2.182 void
2.183 -I2c_jz4780_channel::write(uint8_t buf[], unsigned int total)
2.184 +I2c_jz4780_channel::start_write(uint8_t buf[], unsigned int total)
2.185 {
2.186 - unsigned int pos = 0;
2.187 + _buf = buf;
2.188 + _total = total;
2.189 + _reqpos = 0;
2.190 + _fail = 0;
2.191 +}
2.192
2.193 - while ((pos < total) && !write_failed())
2.194 +void
2.195 +I2c_jz4780_channel::write()
2.196 +{
2.197 + if (write_failed())
2.198 {
2.199 - queue_writes(buf, &pos, total);
2.200 + _fail = 1;
2.201 + return;
2.202 }
2.203 +
2.204 + if (_regs[Int_status] & Int_tx_empty)
2.205 + queue_writes();
2.206 }
2.207
2.208 // Explicitly stop communication.
2.209 @@ -656,24 +673,39 @@
2.210 static_cast<I2c_jz4780_channel *>(i2c_channel)->read();
2.211 }
2.212
2.213 +void jz4780_i2c_start_write(void *i2c_channel, uint8_t buf[], unsigned int total)
2.214 +{
2.215 + static_cast<I2c_jz4780_channel *>(i2c_channel)->start_write(buf, total);
2.216 +}
2.217 +
2.218 +void jz4780_i2c_write(void *i2c_channel)
2.219 +{
2.220 + static_cast<I2c_jz4780_channel *>(i2c_channel)->write();
2.221 +}
2.222 +
2.223 int jz4780_i2c_read_done(void *i2c_channel)
2.224 {
2.225 return static_cast<I2c_jz4780_channel *>(i2c_channel)->read_done();
2.226 }
2.227
2.228 +int jz4780_i2c_write_done(void *i2c_channel)
2.229 +{
2.230 + return static_cast<I2c_jz4780_channel *>(i2c_channel)->write_done();
2.231 +}
2.232 +
2.233 unsigned int jz4780_i2c_have_read(void *i2c_channel)
2.234 {
2.235 return static_cast<I2c_jz4780_channel *>(i2c_channel)->have_read();
2.236 }
2.237
2.238 -int jz4780_i2c_read_incomplete(void *i2c_channel)
2.239 +unsigned int jz4780_i2c_have_written(void *i2c_channel)
2.240 {
2.241 - return static_cast<I2c_jz4780_channel *>(i2c_channel)->read_incomplete();
2.242 + return static_cast<I2c_jz4780_channel *>(i2c_channel)->have_written();
2.243 }
2.244
2.245 -void jz4780_i2c_write(void *i2c_channel, uint8_t buf[], unsigned int total)
2.246 +int jz4780_i2c_failed(void *i2c_channel)
2.247 {
2.248 - static_cast<I2c_jz4780_channel *>(i2c_channel)->write(buf, total);
2.249 + return static_cast<I2c_jz4780_channel *>(i2c_channel)->failed();
2.250 }
2.251
2.252 void jz4780_i2c_stop(void *i2c_channel)
3.1 --- a/pkg/landfall-examples/ci20_i2c/ci20_i2c.c Sun Jul 21 22:23:06 2019 +0200
3.2 +++ b/pkg/landfall-examples/ci20_i2c/ci20_i2c.c Mon Jul 22 00:17:30 2019 +0200
3.3 @@ -28,6 +28,7 @@
3.4 #include <stdio.h>
3.5 #include <unistd.h>
3.6 #include <stdint.h>
3.7 +#include <string.h>
3.8
3.9
3.10
3.11 @@ -77,8 +78,8 @@
3.12 printf("No reply from bus.\n");
3.13 }
3.14
3.15 -static unsigned int i2c_read(void *i2c_channel, uint8_t *buf, unsigned length,
3.16 - l4_cap_idx_t irqcap)
3.17 +static long i2c_read(void *i2c_channel, uint8_t *buf, unsigned length,
3.18 + l4_cap_idx_t irqcap)
3.19 {
3.20 l4_msgtag_t tag;
3.21 long err;
3.22 @@ -87,30 +88,46 @@
3.23
3.24 while (!jz4780_i2c_read_done(i2c_channel))
3.25 {
3.26 - if (jz4780_i2c_read_incomplete(i2c_channel))
3.27 - {
3.28 - printf("Failed\n");
3.29 - break;
3.30 - }
3.31 -
3.32 tag = l4_irq_receive(irqcap, l4_timeout(L4_IPC_TIMEOUT_NEVER, l4_timeout_rel(1, 20)));
3.33
3.34 if ((err = l4_ipc_error(tag, l4_utcb())))
3.35 - {
3.36 - printf("Error on IRQ receive: %ld\n", err);
3.37 - break;
3.38 - }
3.39 + return err;
3.40 +
3.41 + if (jz4780_i2c_failed(i2c_channel))
3.42 + return 0;
3.43
3.44 jz4780_i2c_read(i2c_channel);
3.45 }
3.46
3.47 - jz4780_i2c_stop(i2c_channel);
3.48 return jz4780_i2c_have_read(i2c_channel);
3.49 }
3.50
3.51 +static long i2c_write(void *i2c_channel, uint8_t *buf, unsigned length,
3.52 + l4_cap_idx_t irqcap)
3.53 +{
3.54 + l4_msgtag_t tag;
3.55 + long err;
3.56 +
3.57 + jz4780_i2c_start_write(i2c_channel, buf, length);
3.58 +
3.59 + while (!jz4780_i2c_write_done(i2c_channel))
3.60 + {
3.61 + tag = l4_irq_receive(irqcap, l4_timeout(L4_IPC_TIMEOUT_NEVER, l4_timeout_rel(1, 20)));
3.62 +
3.63 + if ((err = l4_ipc_error(tag, l4_utcb())))
3.64 + return err;
3.65 +
3.66 + if (jz4780_i2c_failed(i2c_channel))
3.67 + return 0;
3.68 +
3.69 + jz4780_i2c_write(i2c_channel);
3.70 + }
3.71 +
3.72 + return jz4780_i2c_have_written(i2c_channel);
3.73 +}
3.74 +
3.75 static void i2c_scan(void *i2c_channel, l4_cap_idx_t irqcap)
3.76 {
3.77 - l4_msgtag_t tag;
3.78 uint8_t buf[1];
3.79 unsigned int address;
3.80
3.81 @@ -128,25 +145,11 @@
3.82
3.83 jz4780_i2c_set_target(i2c_channel, address);
3.84 buf[0] = 0;
3.85 - jz4780_i2c_write(i2c_channel, buf, 1);
3.86 - jz4780_i2c_start_read(i2c_channel, buf, 1);
3.87 -
3.88 - while (!jz4780_i2c_read_done(i2c_channel))
3.89 - {
3.90 - if (jz4780_i2c_read_incomplete(i2c_channel))
3.91 - break;
3.92 -
3.93 - tag = l4_irq_receive(irqcap, l4_timeout(L4_IPC_TIMEOUT_NEVER, l4_timeout_rel(2, 10)));
3.94 -
3.95 - if (l4_ipc_error(tag, l4_utcb()))
3.96 - break;
3.97 -
3.98 - jz4780_i2c_read(i2c_channel);
3.99 - }
3.100 -
3.101 + i2c_write(i2c_channel, buf, 1, irqcap);
3.102 + i2c_read(i2c_channel, buf, 1, irqcap);
3.103 jz4780_i2c_stop(i2c_channel);
3.104
3.105 - if (jz4780_i2c_have_read(i2c_channel))
3.106 + if (!jz4780_i2c_failed(i2c_channel))
3.107 printf("%02x ", address);
3.108 else
3.109 printf("?? ");
3.110 @@ -163,7 +166,7 @@
3.111 /* Buffer for reading. */
3.112
3.113 uint8_t buf[128];
3.114 - unsigned int pos;
3.115 + long pos;
3.116
3.117 /* DDC EDID details. */
3.118
3.119 @@ -176,11 +179,17 @@
3.120
3.121 jz4780_i2c_set_target(i2c_channel, 0x50);
3.122 buf[0] = 0;
3.123 - jz4780_i2c_write(i2c_channel, buf, 1);
3.124 + i2c_write(i2c_channel, buf, 1, irqcap);
3.125 + memset(buf, 0, 128);
3.126 + pos = i2c_read(i2c_channel, buf, 128, irqcap);
3.127 + jz4780_i2c_stop(i2c_channel);
3.128
3.129 - printf("Waiting...\n");
3.130 + if (pos <= 0)
3.131 + {
3.132 + printf("Read failed.\n");
3.133 + return;
3.134 + }
3.135
3.136 - pos = i2c_read(i2c_channel, buf, 128, irqcap);
3.137 show_data(buf, pos);
3.138
3.139 /* Attempt to decode EDID information. */
3.140 @@ -201,25 +210,37 @@
3.141
3.142 jz4780_i2c_set_target(i2c_channel, 0x5a);
3.143 buf[0] = 0x32;
3.144 - jz4780_i2c_write(i2c_channel, buf, 1);
3.145 + i2c_write(i2c_channel, buf, 1, irqcap);
3.146 i2c_read(i2c_channel, buf, 1, irqcap);
3.147 - printf("Read %02x\n", buf[0]);
3.148 + jz4780_i2c_stop(i2c_channel);
3.149 +
3.150 + if (!jz4780_i2c_failed(i2c_channel))
3.151 + printf("Read: %02x\n", buf[0]);
3.152 + else
3.153 + printf("Read failed.\n");
3.154
3.155 #if 0
3.156 /* Disable the regulator. */
3.157
3.158 printf("Updating...\n");
3.159 +
3.160 buf[1] = buf[0] & ~0x80;
3.161 buf[0] = 0x32;
3.162 - jz4780_i2c_write(i2c_channel, buf, 2);
3.163 + i2c_write(i2c_channel, buf, 2, irqcap);
3.164 + jz4780_i2c_stop(i2c_channel);
3.165
3.166 /* Read back from the register. Seemed to give 0xff, which makes no real
3.167 sense, although the regulator did bring the voltage level low. */
3.168
3.169 buf[0] = 0x32;
3.170 - jz4780_i2c_write(i2c_channel, buf, 1);
3.171 + i2c_write(i2c_channel, buf, 1, irqcap);
3.172 i2c_read(i2c_channel, buf, 1, irqcap);
3.173 - printf("Read %02x\n", buf[0]);
3.174 + jz4780_i2c_stop(i2c_channel);
3.175 +
3.176 + if (!jz4780_i2c_failed(i2c_channel))
3.177 + printf("Read: %02x\n", buf[0]);
3.178 + else
3.179 + printf("Read failed.\n");
3.180 #endif
3.181 }
3.182