1.1 --- a/pkg/devices/lib/i2c/src/jz4730.cc Sun Jan 03 17:53:36 2021 +0100
1.2 +++ b/pkg/devices/lib/i2c/src/jz4730.cc Wed Jan 06 00:46:11 2021 +0100
1.3 @@ -23,6 +23,8 @@
1.4 #include <l4/devices/hw_mmio_register_block.h>
1.5
1.6 #include <l4/sys/icu.h>
1.7 +#include <l4/sys/ipc.h>
1.8 +#include <l4/sys/irq.h>
1.9 #include <l4/util/util.h>
1.10
1.11 #include <cstdio>
1.12 @@ -73,8 +75,9 @@
1.13
1.14 I2c_jz4730_channel::I2c_jz4730_channel(l4_addr_t start,
1.15 Cpm_jz4730_chip *cpm,
1.16 - uint32_t frequency)
1.17 -: _cpm(cpm), _frequency(frequency)
1.18 + uint32_t frequency,
1.19 + l4_cap_idx_t irq)
1.20 +: _cpm(cpm), _frequency(frequency), _irq(irq)
1.21 {
1.22 _regs = new Hw::Mmio_register_block<32>(start);
1.23 }
1.24 @@ -132,20 +135,34 @@
1.25
1.26 // Present the address on the bus.
1.27
1.28 -void
1.29 +bool
1.30 I2c_jz4730_channel::set_address(uint8_t address, bool read)
1.31 {
1.32 + unsigned int limit = 10;
1.33 +
1.34 + do
1.35 + {
1.36 + if (!wait_for_irq(1000) && !(--limit))
1.37 + return false;
1.38 + }
1.39 + while (busy());
1.40 +
1.41 start();
1.42
1.43 _regs[I2c_data] = (address << 1) | (read ? 1 : 0);
1.44 - while (nack());
1.45
1.46 send_next();
1.47
1.48 - if (read)
1.49 - while ((data_valid() || !transferred()) && !nack());
1.50 - else
1.51 - while (data_valid() && !nack());
1.52 + return true;
1.53 +}
1.54 +
1.55 +// Wait up to the given timeout (in microseconds) for an interrupt request,
1.56 +// returning true if one was delivered.
1.57 +
1.58 +bool
1.59 +I2c_jz4730_channel::wait_for_irq(unsigned int timeout)
1.60 +{
1.61 + return !l4_error(l4_irq_receive(_irq, l4_timeout(L4_IPC_TIMEOUT_NEVER, l4util_micros2l4to(timeout))));
1.62 }
1.63
1.64 // Read data from the bus.
1.65 @@ -155,27 +172,39 @@
1.66 {
1.67 unsigned int nread = 0;
1.68
1.69 - set_address(address, true);
1.70 + if (!set_address(address, true))
1.71 + return 0;
1.72 +
1.73 + do
1.74 + {
1.75 + if (!wait_for_irq(1000000))
1.76 + printf("start (no irq): status = %x\n", (uint32_t) _regs[I2c_status]);
1.77 + }
1.78 + while (transferring() || (!data_valid() && !nack()));
1.79
1.80 - if (!nack())
1.81 + while (nread < length)
1.82 {
1.83 - if (length == 1)
1.84 + do
1.85 + {
1.86 + if (!wait_for_irq(1000000))
1.87 + {
1.88 + stop();
1.89 + return nread;
1.90 + }
1.91 + }
1.92 + while (!data_valid() && !nack());
1.93 +
1.94 + if (nack())
1.95 + break;
1.96 +
1.97 + if ((!nread && (length == 1)) || (nread == length - 2))
1.98 signal_last();
1.99
1.100 - while (nread < length)
1.101 - {
1.102 - while (!data_valid());
1.103 -
1.104 - if (nread == length - 2)
1.105 - signal_last();
1.106 -
1.107 - buf[nread++] = _regs[I2c_data];
1.108 - request_next();
1.109 - }
1.110 + buf[nread++] = _regs[I2c_data];
1.111 + clear_next();
1.112 }
1.113
1.114 stop();
1.115 -
1.116 return nread;
1.117 }
1.118
1.119 @@ -186,18 +215,44 @@
1.120 {
1.121 unsigned int nwritten = 0;
1.122
1.123 - set_address(address, false);
1.124 + if (!set_address(address, false))
1.125 + return 0;
1.126 +
1.127 + do
1.128 + {
1.129 + if (!wait_for_irq(1000000))
1.130 + {
1.131 + printf("write (no irq): status = %x\n", (uint32_t) _regs[I2c_status]);
1.132 + stop();
1.133 + return nwritten;
1.134 + }
1.135 + }
1.136 + while (data_valid() && !nack());
1.137
1.138 while ((nwritten < length) && !nack())
1.139 {
1.140 _regs[I2c_data] = buf[nwritten++];
1.141 send_next();
1.142
1.143 + do
1.144 + {
1.145 + if (!wait_for_irq(1000000))
1.146 + {
1.147 + printf("write (no irq): status = %x\n", (uint32_t) _regs[I2c_status]);
1.148 + stop();
1.149 + return nwritten;
1.150 + }
1.151 + }
1.152 while (data_valid() && !nack());
1.153 }
1.154
1.155 stop();
1.156
1.157 + do
1.158 + {
1.159 + if (!wait_for_irq(1000000))
1.160 + break;
1.161 + }
1.162 while (!transferred());
1.163
1.164 return nwritten;
1.165 @@ -214,7 +269,7 @@
1.166 // Request the next byte by clearing the data validity flag.
1.167
1.168 void
1.169 -I2c_jz4730_channel::request_next()
1.170 +I2c_jz4730_channel::clear_next()
1.171 {
1.172 _regs[I2c_status] = _regs[I2c_status] & ~I2c_status_data_valid;
1.173 }
1.174 @@ -243,6 +298,22 @@
1.175 _regs[I2c_control] = _regs[I2c_control] | I2c_control_nack;
1.176 }
1.177
1.178 +// Test for bus activity.
1.179 +
1.180 +bool
1.181 +I2c_jz4730_channel::busy()
1.182 +{
1.183 + return (_regs[I2c_status] & I2c_status_busy) ? true : false;
1.184 +}
1.185 +
1.186 +// Test for transfer activity.
1.187 +
1.188 +bool
1.189 +I2c_jz4730_channel::transferring()
1.190 +{
1.191 + return (_regs[I2c_status] & I2c_status_buffer_nempty) ? true : false;
1.192 +}
1.193 +
1.194 // Test for write transfer completion.
1.195
1.196 bool
1.197 @@ -281,10 +352,10 @@
1.198 // Obtain a channel object. Only one channel is supported.
1.199
1.200 I2c_jz4730_channel *
1.201 -I2c_jz4730_chip::get_channel(uint8_t channel)
1.202 +I2c_jz4730_chip::get_channel(uint8_t channel, l4_cap_idx_t irq)
1.203 {
1.204 if (channel == 0)
1.205 - return new I2c_jz4730_channel(_start, _cpm, _frequency);
1.206 + return new I2c_jz4730_channel(_start, _cpm, _frequency, irq);
1.207 else
1.208 throw -L4_EINVAL;
1.209 }
1.210 @@ -298,9 +369,9 @@
1.211 return (void *) new I2c_jz4730_chip(start, end, static_cast<Cpm_jz4730_chip *>(cpm), frequency);
1.212 }
1.213
1.214 -void *jz4730_i2c_get_channel(void *i2c, uint8_t channel)
1.215 +void *jz4730_i2c_get_channel(void *i2c, uint8_t channel, l4_cap_idx_t irq)
1.216 {
1.217 - return static_cast<I2c_jz4730_chip *>(i2c)->get_channel(channel);
1.218 + return static_cast<I2c_jz4730_chip *>(i2c)->get_channel(channel, irq);
1.219 }
1.220
1.221 void jz4730_i2c_disable(void *i2c_channel)