1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/pkg/devices/lib/i2c/src/common.cc Sun Oct 29 16:14:38 2023 +0100
1.3 @@ -0,0 +1,706 @@
1.4 +/*
1.5 + * I2C support for the JZ4780 and X1600.
1.6 + *
1.7 + * Copyright (C) 2017, 2018, 2021, 2023 Paul Boddie <paul@boddie.org.uk>
1.8 + *
1.9 + * This program is free software; you can redistribute it and/or
1.10 + * modify it under the terms of the GNU General Public License as
1.11 + * published by the Free Software Foundation; either version 2 of
1.12 + * the License, or (at your option) any later version.
1.13 + *
1.14 + * This program is distributed in the hope that it will be useful,
1.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
1.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1.17 + * GNU General Public License for more details.
1.18 + *
1.19 + * You should have received a copy of the GNU General Public License
1.20 + * along with this program; if not, write to the Free Software
1.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
1.22 + * Boston, MA 02110-1301, USA
1.23 + */
1.24 +
1.25 +#include <l4/devices/i2c-common.h>
1.26 +
1.27 +#include <l4/sys/icu.h>
1.28 +#include <l4/util/util.h>
1.29 +#include <sys/time.h>
1.30 +
1.31 +/* NOTE: The X1600 is very similar to the JZ4780 with the registers
1.32 + renamed to I2C from SMB, with a few high speed registers, the
1.33 + I2C_RINTST, I2C_TXFLR and I2C_RXFLR registers, and a few other
1.34 + registers added, with I2C_SDAHD appearing at a different location. */
1.35 +
1.36 +enum Regs
1.37 +{
1.38 + I2c_control = 0x000, // I2C_CON
1.39 + I2c_target_address = 0x004, // I2C_TAR
1.40 + I2c_slave_address = 0x008, // I2C_SAR
1.41 + I2c_master_code = 0x00c, // I2C_HS_MADDR
1.42 + I2c_data_command = 0x010, // I2C_DC
1.43 + Std_high_count = 0x014, // I2C_SHCNT
1.44 + Std_low_count = 0x018, // I2C_SLCNT
1.45 + Fast_high_count = 0x01c, // I2C_FHCNT
1.46 + Fast_low_count = 0x020, // I2C_FLCNT
1.47 + Int_status = 0x02c, // I2C_INTST (read-only)
1.48 + Int_mask = 0x030, // I2C_INTM
1.49 + Rx_fifo_thold = 0x038, // I2C_RXTL
1.50 + Tx_fifo_thold = 0x03c, // I2C_TXTL
1.51 + Int_combined_clear = 0x040, // I2C_CINT (read-only)
1.52 + Int_rx_uf_clear = 0x044, // I2C_CRXUF (read-only)
1.53 + Int_rx_of_clear = 0x048, // I2C_CRXOF (read-only)
1.54 + Int_tx_of_clear = 0x04c, // I2C_CTXOF (read-only)
1.55 + Int_rd_req_clear = 0x050, // I2C_CRXREQ (read-only)
1.56 + Int_tx_abort_clear = 0x054, // I2C_CTXABT (read-only)
1.57 + Int_rx_done_clear = 0x058, // I2C_CRXDN (read-only)
1.58 + Int_activity_clear = 0x05c, // I2C_CACT (read-only)
1.59 + Int_stop_clear = 0x060, // I2C_CSTP (read-only)
1.60 + Int_start_clear = 0x064, // I2C_CSTT (read-only)
1.61 + Int_call_clear = 0x068, // I2C_CGC (read-only)
1.62 + I2c_enable = 0x06c, // I2C_ENB
1.63 + I2c_status = 0x070, // I2C_ST (read-only)
1.64 + I2c_sda_hold_time = 0x07c, // I2C_SDAHD
1.65 + Trans_abort_status = 0x080, // I2C_ABTSRC (read-only)
1.66 + I2c_dma_ctrl = 0x088, // I2C_DMACR
1.67 + I2c_trans_data_lvl = 0x08c, // I2C_DMATDLR
1.68 + I2c_recv_data_lvl = 0x090, // I2C_DMARDLR
1.69 + I2c_sda_setup_time = 0x094, // I2C_SDASU
1.70 + I2c_ack_call = 0x098, // I2C_ACKGC
1.71 + I2c_enable_status = 0x09c, // I2C_ENBST (read-only)
1.72 +
1.73 + // X1600 only...
1.74 +
1.75 + High_high_count = 0x024, // I2C_HHCNT
1.76 + High_low_count = 0x028, // I2C_HLCNT
1.77 + Int_raw_status = 0x034, // I2C_RINTST (read-only)
1.78 + Tx_fifo_count = 0x074, // I2C_TXFLR (read-only)
1.79 + Rx_fifo_count = 0x078, // I2C_RXFLR (read-only)
1.80 + Slv_data_nack = 0x084, // I2CSDNACK
1.81 + I2c_spike_suppress = 0x0a0, // I2C_FSPKLEN
1.82 +
1.83 + // Register block spacing.
1.84 +
1.85 + I2c_block_offset = 0x1000
1.86 +};
1.87 +
1.88 +enum I2c_control_bits : unsigned
1.89 +{
1.90 + I2c_disable_slave = 0x40, // SLVDIS (slave disabled)
1.91 + I2c_enable_restart = 0x20, // RESTART
1.92 + I2c_master_10bit = 0x10, // MATP (read-only)
1.93 + I2c_slave_10bit = 0x08, // SATP
1.94 + I2c_speed_mode_mask = 0x06, // SPEED
1.95 + I2c_enable_master = 0x01, // MD (master enabled)
1.96 + I2c_speed_bit = 1, // SPD
1.97 +};
1.98 +
1.99 +enum I2c_speed_mode_values : unsigned
1.100 +{
1.101 + I2c_speed_standard = 1,
1.102 + I2c_speed_fast = 2,
1.103 + I2c_speed_high = 3,
1.104 +};
1.105 +
1.106 +enum I2c_enable_bits : unsigned
1.107 +{
1.108 + I2c_enable_enabled = 0x01, // I2CEN
1.109 +};
1.110 +
1.111 +enum I2c_status_bits : unsigned
1.112 +{
1.113 + I2c_status_master_act = 0x20, // MSTACT (master active)
1.114 + I2c_status_rx_nempty = 0x08, // RFNE (read queue not empty)
1.115 + I2c_status_tx_empty = 0x04, // TFE (write queue empty)
1.116 + I2c_status_tx_nfull = 0x02, // TFNF (write queue not full)
1.117 + I2c_status_active = 0x01, // ACT (device active as master or slave)
1.118 +};
1.119 +
1.120 +enum I2c_target_bits : unsigned
1.121 +{
1.122 + I2c_target_master_10bit = 0x1000,
1.123 + I2c_target_special = 0x0800, // SPECIAL: perform general call or start byte
1.124 + I2c_target_start_byte = 0x0400, // Special: start byte (1) or general call (0)
1.125 + I2c_target_10bits = 0x3ff, // Mask for 10-bit address
1.126 + I2c_target_7bits = 0x7f, // Mask for 7-bit address
1.127 +};
1.128 +
1.129 +enum I2c_hold_control_bits : unsigned
1.130 +{
1.131 + /* The hold enable flag has been removed since the JZ4780 and the hold time
1.132 + field widened. */
1.133 +
1.134 + I2c_hold_mask = 0xffff,
1.135 +};
1.136 +
1.137 +enum I2c_setup_control_bits : unsigned
1.138 +{
1.139 + I2c_setup_mask = 0x0ff, // SDASU
1.140 +};
1.141 +
1.142 +enum I2c_command_bits : unsigned
1.143 +{
1.144 + I2c_command_restart = 0x400, // RESTART: explicit restart before next byte
1.145 + I2c_command_stop = 0x200, // STOP: explicit stop after next byte
1.146 + I2c_command_no_stop = 0x000,
1.147 + I2c_command_read = 0x100, // CMD
1.148 + I2c_command_write = 0x000, // CMD
1.149 +};
1.150 +
1.151 +enum I2c_fifo_bits : unsigned
1.152 +{
1.153 + I2c_fifo_limit = 64, // RXTL, TXTL (256 noted in field description)
1.154 +};
1.155 +
1.156 +enum Int_bits : unsigned
1.157 +{
1.158 + Int_call = 0x800, // IGC (general call received)
1.159 + Int_start = 0x400, // ISTT (start/restart condition occurred)
1.160 + Int_stop = 0x200, // ISTP (stop condition occurred)
1.161 + Int_activity = 0x100, // IACT (bus activity interrupt)
1.162 + Int_rx_done = 0x080, // RXDN (read from master device done)
1.163 + Int_tx_abort = 0x040, // TXABT (transmit abort)
1.164 + Int_rd_req = 0x020, // RDREQ (read request from master device)
1.165 + Int_tx_empty = 0x010, // TXEMP (threshold reached or passed)
1.166 + Int_tx_of = 0x008, // TXOF (overflow when writing to queue)
1.167 + Int_rx_full = 0x004, // RXFL (threshold reached or exceeded)
1.168 + Int_rx_of = 0x002, // RXOF (overflow from device)
1.169 + Int_rx_uf = 0x001, // RXUF (underflow when reading from queue)
1.170 +};
1.171 +
1.172 +
1.173 +
1.174 +// Initialise a channel.
1.175 +
1.176 +I2c_channel::I2c_channel(l4_addr_t start,
1.177 + enum Clock_identifiers clock,
1.178 + Cpm_chip *cpm,
1.179 + uint32_t frequency)
1.180 +: _cpm(cpm), _frequency(frequency)
1.181 +{
1.182 + _regs = new Hw::Mmio_register_block<32>(start);
1.183 + _cpm->start_clock(clock);
1.184 +}
1.185 +
1.186 +// Enable the channel.
1.187 +
1.188 +void
1.189 +I2c_channel::enable()
1.190 +{
1.191 + _regs[I2c_enable] = I2c_enable_enabled;
1.192 + while (!(_regs[I2c_enable_status] & I2c_enable_enabled));
1.193 +}
1.194 +
1.195 +// Disable the channel.
1.196 +
1.197 +void
1.198 +I2c_channel::disable()
1.199 +{
1.200 + _regs[I2c_enable] = 0;
1.201 + while (_regs[I2c_enable_status] & I2c_enable_enabled);
1.202 +}
1.203 +
1.204 +// Return the configured frequency.
1.205 +
1.206 +uint32_t
1.207 +I2c_channel::get_frequency()
1.208 +{
1.209 + return _frequency;
1.210 +}
1.211 +
1.212 +// Set the frequency-related peripheral parameters.
1.213 +
1.214 +void
1.215 +I2c_channel::set_frequency()
1.216 +{
1.217 + // The APB clock (PCLK) is used to drive I2C transfers. Its value must be
1.218 + // obtained from the CPM unit. It is known as I2C_DEV_CLK here and is scaled
1.219 + // to kHz in order to keep the numbers easily representable, as is the bus
1.220 + // frequency.
1.221 +
1.222 + uint32_t i2c_dev_clk = _cpm->get_frequency(Clock_pclock) / 1000;
1.223 +
1.224 + // Note that this is not I2C_DEV_CLK but the actual I2C bus frequency.
1.225 +
1.226 + uint32_t i2c_clk = _frequency / 1000;
1.227 +
1.228 + // Select the appropriate speed.
1.229 +
1.230 + unsigned int speed = (i2c_clk <= 100) ? I2c_speed_standard
1.231 + : (i2c_clk <= 400 ? I2c_speed_fast
1.232 + : I2c_speed_high);
1.233 +
1.234 + // NOTE: Permit broader configuration elsewhere.
1.235 +
1.236 + _regs[I2c_control] = (speed << I2c_speed_bit) |
1.237 + I2c_disable_slave |
1.238 + I2c_enable_restart |
1.239 + I2c_enable_master;
1.240 +
1.241 + // According to the programming manual, if the PCLK period is T{I2C_DEV_CLK}
1.242 + // then the I2C clock period is...
1.243 +
1.244 + // T{SCL} = T{SCL_high} + T{SCL_low}
1.245 +
1.246 + // Where...
1.247 +
1.248 + // T{SCL_low} = T{I2C_DEV_CLK} * (#cycles for low signal)
1.249 + // T{SCL_high} = T{I2C_DEV_CLK} * (#cycles for high signal)
1.250 +
1.251 + // Since, with minimum periods being defined...
1.252 +
1.253 + // T{SCL} >= T{min_SCL}
1.254 + // T{SCL_low} >= T{min_SCL_low}
1.255 + // T{SCL_high} >= T{min_SCL_high}
1.256 + // T{min_SCL} = T{min_SCL_low} + T{min_SCL_high}
1.257 +
1.258 + // Then the following applies...
1.259 +
1.260 + // T{I2C_DEV_CLK} * (#cycles for low signal)) >= T{min_SCL_low}
1.261 + // T{I2C_DEV_CLK} * (#cycles for high signal) >= T{min_SCL_high}
1.262 +
1.263 + // To work with different clock speeds while maintaining the low-to-high
1.264 + // ratios:
1.265 +
1.266 + // T{min_SCL_low} = T{min_SCL} * T{min_SCL_low} / T{min_SCL}
1.267 + // = T{min_SCL} * (T{min_SCL_low} / (T{min_SCL_low} + T{min_SCL_high}))
1.268 +
1.269 + // T{min_SCL_high} = T{min_SCL} * T{min_SCL_high} / T{min_SCL}
1.270 + // = T{min_SCL} * (T{min_SCL_high} / (T{min_SCL_low} + T{min_SCL_high}))
1.271 +
1.272 + // Constraints are given with respect to the high and low count registers.
1.273 +
1.274 + // #cycles for high signal = I2CxHCNT + 8
1.275 + // #cycles for low signal = I2CxLCNT + 1
1.276 +
1.277 + // From earlier, this yields...
1.278 +
1.279 + // T{I2C_DEV_CLK} * (I2CxLCNT + 1) >= T{min_SCL_low}
1.280 + // T{I2C_DEV_CLK} * (I2CxHCNT + 8) >= T{min_SCL_high}
1.281 +
1.282 + // Rearranging...
1.283 +
1.284 + // I2CxLCNT >= (T{min_SCL_low} / T{I2C_DEV_CLK}) - 1
1.285 + // >= T{min_SCL_low} * I2C_DEV_CLK - 1
1.286 +
1.287 + // I2CxHCNT >= (T{min_SCL_high} / T{I2C_DEV_CLK}) - 8
1.288 + // >= T{min_SCL_high} * I2C_DEV_CLK - 8
1.289 +
1.290 + // Introducing the definitions for the high and low periods...
1.291 +
1.292 + // I2CxLCNT >= T{min_SCL} * (T{min_SCL_low} / (T{min_SCL_low} + T{min_SCL_high})) * I2C_DEV_CLK - 1
1.293 + // >= (T{min_SCL_low} / T{min_SCL}) * I2C_DEV_CLK / I2C_BUS_CLK - 1
1.294 +
1.295 + // I2CxHCNT >= T{min_SCL} * (T{min_SCL_high} / (T{min_SCL_low} + T{min_SCL_high})) * I2C_DEV_CLK - 8
1.296 + // >= (T{min_SCL_high} / T{min_SCL}) * I2C_DEV_CLK / I2C_BUS_CLK - 8
1.297 +
1.298 + uint32_t high_reg, low_reg;
1.299 + uint32_t high_count, low_count;
1.300 + int32_t hold_count;
1.301 + uint32_t setup_count;
1.302 +
1.303 + // Level hold times:
1.304 +
1.305 + // Standard Fast High
1.306 + // SCL low 4.7us 1.3us 0.5us
1.307 + // SCL high 4.0us 0.6us 0.26us +
1.308 + // SCL period 8.7us 1.9us 0.76us =
1.309 +
1.310 + // See: UM10204 "I2C-bus specification and user manual"
1.311 + // Table 10: t{LOW} and t{HIGH}
1.312 +
1.313 + if (i2c_clk <= 100) // 100 kHz
1.314 + {
1.315 + low_count = (i2c_dev_clk * 47) / (i2c_clk * 87) - 1;
1.316 + high_count = (i2c_dev_clk * 40) / (i2c_clk * 87) - 8;
1.317 + low_reg = Std_low_count;
1.318 + high_reg = Std_high_count;
1.319 + }
1.320 + else if (i2c_clk <= 400) // 400 kHz
1.321 + {
1.322 + low_count = (i2c_dev_clk * 13) / (i2c_clk * 19) - 1;
1.323 + high_count = (i2c_dev_clk * 6) / (i2c_clk * 19) - 8;
1.324 + low_reg = Fast_low_count;
1.325 + high_reg = Fast_high_count;
1.326 + }
1.327 + else // > 400 kHz
1.328 + {
1.329 + // Note how the frequencies are scaled to accommodate the extra precision
1.330 + // required.
1.331 +
1.332 + low_count = (i2c_dev_clk / 10 * 50) / (i2c_clk / 10 * 76) - 1;
1.333 + high_count = (i2c_dev_clk / 10 * 26) / (i2c_clk / 10 * 76) - 8;
1.334 + low_reg = High_low_count;
1.335 + high_reg = High_high_count;
1.336 + }
1.337 +
1.338 + // Minimum counts are 8 and 6 for low and high respectively.
1.339 +
1.340 + _regs[low_reg] = low_count < 8 ? 8 : low_count;
1.341 + _regs[high_reg] = high_count < 6 ? 6 : high_count;
1.342 +
1.343 + // Data hold and setup times:
1.344 +
1.345 + // Standard Fast High
1.346 + // t{HD;DAT} 300ns 300ns 300ns
1.347 + // t{SU;DAT} 250ns 100ns 50ns
1.348 +
1.349 + // See: UM10204 "I2C-bus specification and user manual"
1.350 + // Table 10: t{HD;DAT} and t{SU;DAT}, also note [3]
1.351 +
1.352 + // T{delay} = (I2CSDAHD + 2) * T{I2C_DEV_CLK}
1.353 + // I2CSDAHD = T{delay} / T{I2C_DEV_CLK} - 2
1.354 + // I2CSDAHD = I2C_DEV_CLK * T{delay} - 2
1.355 +
1.356 + // Since the device clock is in kHz (scaled down by 1000) and the times are
1.357 + // given in ns (scaled up by 1000000000), a division of 1000000 is introduced.
1.358 +
1.359 + hold_count = (i2c_dev_clk * 300) / 1000000 - 1;
1.360 +
1.361 + _regs[I2c_sda_hold_time] = (_regs[I2c_sda_hold_time] & ~I2c_hold_mask) |
1.362 + (hold_count < 0 ? 0
1.363 + : (hold_count < (int) I2c_hold_mask ? (uint32_t) hold_count
1.364 + : I2c_hold_mask));
1.365 +
1.366 + // I2C_SDASU is apparently not used in master mode.
1.367 +
1.368 + // T{delay} = (I2CSDASU - 1) * T{I2C_DEV_CLK}
1.369 + // I2CSDASU = T{delay} / T{I2C_DEV_CLK} + 1
1.370 + // I2CSDASU = I2C_DEV_CLK * T{delay} + 1
1.371 +
1.372 + if (i2c_clk <= 100)
1.373 + setup_count = (i2c_dev_clk * 250) / 1000000 + 1;
1.374 + else if (i2c_clk <= 400)
1.375 + setup_count = (i2c_dev_clk * 100) / 1000000 + 1;
1.376 + else
1.377 + setup_count = (i2c_dev_clk * 50) / 1000000 + 1;
1.378 +
1.379 + _regs[I2c_sda_setup_time] = (_regs[I2c_sda_setup_time] & ~I2c_setup_mask) |
1.380 + (setup_count < I2c_setup_mask ? setup_count : I2c_setup_mask);
1.381 +}
1.382 +
1.383 +// Set the target address and enable transfer.
1.384 +// NOTE: Only supporting 7-bit addresses currently.
1.385 +
1.386 +void
1.387 +I2c_channel::set_target(uint8_t address)
1.388 +{
1.389 + disable();
1.390 + set_frequency();
1.391 + _regs[I2c_target_address] = address & I2c_target_7bits;
1.392 + init_parameters();
1.393 + enable();
1.394 +}
1.395 +
1.396 +
1.397 +
1.398 +// Reset interrupt flags upon certain conditions.
1.399 +
1.400 +void
1.401 +I2c_channel::reset_flags()
1.402 +{
1.403 + volatile uint32_t r;
1.404 +
1.405 + _regs[Int_mask] = 0;
1.406 +
1.407 + // Read from the register to clear interrupts.
1.408 +
1.409 + r = _regs[Int_combined_clear];
1.410 + (void) r;
1.411 +}
1.412 +
1.413 +// Initialise interrupt flags and queue thresholds for reading and writing.
1.414 +
1.415 +void
1.416 +I2c_channel::init_parameters()
1.417 +{
1.418 + // Handle read queue conditions for data, write queue conditions for commands.
1.419 +
1.420 + reset_flags();
1.421 +
1.422 + _regs[Tx_fifo_thold] = 0; // write when 0 in queue
1.423 +}
1.424 +
1.425 +
1.426 +
1.427 +// Return whether the device is active.
1.428 +
1.429 +int
1.430 +I2c_channel::active()
1.431 +{
1.432 + return _regs[I2c_status] & I2c_status_master_act;
1.433 +}
1.434 +
1.435 +// Return whether data is available to receive.
1.436 +
1.437 +int
1.438 +I2c_channel::have_input()
1.439 +{
1.440 + return _regs[I2c_status] & I2c_status_rx_nempty;
1.441 +}
1.442 +
1.443 +// Return whether data is queued for sending.
1.444 +
1.445 +int
1.446 +I2c_channel::have_output()
1.447 +{
1.448 + return !(_regs[I2c_status] & I2c_status_tx_empty);
1.449 +}
1.450 +
1.451 +// Return whether data can be queued for sending.
1.452 +
1.453 +int
1.454 +I2c_channel::can_send()
1.455 +{
1.456 + return _regs[I2c_status] & I2c_status_tx_nfull;
1.457 +}
1.458 +
1.459 +// Return whether a receive operation has failed.
1.460 +
1.461 +int
1.462 +I2c_channel::read_failed()
1.463 +{
1.464 + return _regs[Int_status] & Int_rx_of;
1.465 +}
1.466 +
1.467 +// Return whether a send operation has failed.
1.468 +
1.469 +int
1.470 +I2c_channel::write_failed()
1.471 +{
1.472 + return _regs[Int_status] & Int_tx_abort;
1.473 +}
1.474 +
1.475 +int
1.476 +I2c_channel::read_done()
1.477 +{
1.478 + return _pos == _total;
1.479 +}
1.480 +
1.481 +int
1.482 +I2c_channel::write_done()
1.483 +{
1.484 + return (_reqpos == _total) && !have_output();
1.485 +}
1.486 +
1.487 +unsigned
1.488 +I2c_channel::have_read()
1.489 +{
1.490 + return _pos;
1.491 +}
1.492 +
1.493 +unsigned
1.494 +I2c_channel::have_written()
1.495 +{
1.496 + return _reqpos;
1.497 +}
1.498 +
1.499 +int
1.500 +I2c_channel::failed()
1.501 +{
1.502 + return _fail;
1.503 +}
1.504 +
1.505 +
1.506 +
1.507 +// Send read commands for empty queue entries.
1.508 +
1.509 +void
1.510 +I2c_channel::queue_reads()
1.511 +{
1.512 + unsigned int remaining = _total - _reqpos;
1.513 + unsigned int queued = _reqpos - _pos;
1.514 + unsigned int can_queue = I2c_fifo_limit - queued;
1.515 +
1.516 + // Keep the number of reads in progress below the length of the read queue.
1.517 +
1.518 + if (!can_queue)
1.519 + return;
1.520 +
1.521 + // At most, only queue as many reads as are remaining.
1.522 +
1.523 + if (remaining < can_queue)
1.524 + can_queue = remaining;
1.525 +
1.526 + // Queue read requests for any remaining queue entries.
1.527 +
1.528 + while (can_queue && can_send())
1.529 + {
1.530 + uint32_t stop = _stop && (_reqpos == _total - 1) ? I2c_command_stop : I2c_command_no_stop;
1.531 +
1.532 + _regs[I2c_data_command] = I2c_command_read | stop;
1.533 + _reqpos++;
1.534 + can_queue--;
1.535 + }
1.536 +
1.537 + // Update the threshold to be notified of any reduced remaining amount.
1.538 +
1.539 + set_read_threshold();
1.540 +}
1.541 +
1.542 +// Send write commands for empty queue entries.
1.543 +
1.544 +void
1.545 +I2c_channel::queue_writes()
1.546 +{
1.547 + unsigned int remaining = _total - _reqpos;
1.548 + unsigned int can_queue = I2c_fifo_limit;
1.549 +
1.550 + if (remaining < can_queue)
1.551 + can_queue = remaining;
1.552 +
1.553 + // Queue write requests for any remaining queue entries.
1.554 +
1.555 + while (can_queue && can_send())
1.556 + {
1.557 + uint32_t stop = _stop && (_reqpos == _total - 1) ? I2c_command_stop : I2c_command_no_stop;
1.558 +
1.559 + _regs[I2c_data_command] = I2c_command_write | _buf[_reqpos] | stop;
1.560 + _reqpos++;
1.561 + can_queue--;
1.562 + }
1.563 +}
1.564 +
1.565 +// Store read command results from the queue.
1.566 +
1.567 +void
1.568 +I2c_channel::store_reads()
1.569 +{
1.570 + // Read any input and store it in the buffer.
1.571 +
1.572 + while (have_input() && (_pos < _reqpos))
1.573 + {
1.574 + _buf[_pos] = _regs[I2c_data_command] & 0xff;
1.575 + _pos++;
1.576 + }
1.577 +}
1.578 +
1.579 +void
1.580 +I2c_channel::set_read_threshold()
1.581 +{
1.582 + unsigned int queued = _reqpos - _pos;
1.583 +
1.584 + if (!queued)
1.585 + return;
1.586 +
1.587 + // Read all expected.
1.588 +
1.589 + _regs[Rx_fifo_thold] = queued - 1;
1.590 +}
1.591 +
1.592 +// Read from the target device.
1.593 +
1.594 +void
1.595 +I2c_channel::start_read(uint8_t buf[], unsigned int total, int stop)
1.596 +{
1.597 + _buf = buf;
1.598 + _total = total;
1.599 + _pos = 0;
1.600 + _reqpos = 0;
1.601 + _fail = 0;
1.602 + _stop = stop;
1.603 +
1.604 + reset_flags();
1.605 +
1.606 + _regs[Int_mask] = Int_rx_full | // read condition (reading needed)
1.607 + Int_rx_of | // abort condition
1.608 + Int_tx_abort; // general abort condition
1.609 +
1.610 + // Perform initial read requests.
1.611 +
1.612 + read();
1.613 +}
1.614 +
1.615 +void
1.616 +I2c_channel::read()
1.617 +{
1.618 + // Test for the general transfer abort condition.
1.619 +
1.620 + if (read_failed() || write_failed())
1.621 + {
1.622 + _fail = 1;
1.623 + _regs[Int_mask] = 0;
1.624 + disable();
1.625 + enable();
1.626 + return;
1.627 + }
1.628 +
1.629 + if (_regs[Int_status] & Int_rx_full)
1.630 + store_reads();
1.631 +
1.632 + // Always attempt to queue more read requests.
1.633 +
1.634 + queue_reads();
1.635 +}
1.636 +
1.637 +// Write to the target device.
1.638 +
1.639 +void
1.640 +I2c_channel::start_write(uint8_t buf[], unsigned int total, int stop)
1.641 +{
1.642 + _buf = buf;
1.643 + _total = total;
1.644 + _reqpos = 0;
1.645 + _fail = 0;
1.646 + _stop = stop;
1.647 +
1.648 + reset_flags();
1.649 +
1.650 + // Enable interrupts for further writes.
1.651 +
1.652 + _regs[Int_mask] = Int_tx_empty | // write condition (writing needed)
1.653 + Int_tx_abort; // abort condition
1.654 +
1.655 + // Perform initial writes.
1.656 +
1.657 + write();
1.658 +}
1.659 +
1.660 +void
1.661 +I2c_channel::write()
1.662 +{
1.663 + if (write_failed())
1.664 + {
1.665 + _fail = 1;
1.666 + _regs[Int_mask] = 0;
1.667 + disable();
1.668 + enable();
1.669 + return;
1.670 + }
1.671 +
1.672 + if (_regs[Int_status] & Int_tx_empty)
1.673 + queue_writes();
1.674 +}
1.675 +
1.676 +// Explicitly stop communication.
1.677 +
1.678 +void
1.679 +I2c_channel::stop()
1.680 +{
1.681 +}
1.682 +
1.683 +
1.684 +
1.685 +// Initialise the I2C controller.
1.686 +
1.687 +I2c_chip::I2c_chip(l4_addr_t start, l4_addr_t end,
1.688 + Cpm_chip *cpm,
1.689 + uint32_t frequency)
1.690 +: _start(start), _end(end), _cpm(cpm), _frequency(frequency)
1.691 +{
1.692 +}
1.693 +
1.694 +// Obtain a channel object.
1.695 +
1.696 +I2c_channel *
1.697 +I2c_chip::get_channel(uint8_t channel)
1.698 +{
1.699 + l4_addr_t block = _start + channel * I2c_block_offset;
1.700 +
1.701 + // NOTE: Defining all the possible clocks.
1.702 +
1.703 + enum Clock_identifiers clocks[] = {Clock_i2c0, Clock_i2c1, Clock_i2c2, Clock_i2c3, Clock_i2c4};
1.704 +
1.705 + if (channel < num_channels())
1.706 + return new I2c_channel(block, clocks[channel], _cpm, _frequency);
1.707 + else
1.708 + throw -L4_EINVAL;
1.709 +}