1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/pkg/devices/lib/i2c/include/i2c-x1600.h Sat Oct 14 22:02:07 2023 +0200
1.3 @@ -0,0 +1,161 @@
1.4 +/*
1.5 + * I2C support for the X1600.
1.6 + *
1.7 + * Copyright (C) 2017, 2018, 2019, 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 +#pragma once
1.26 +
1.27 +#include <l4/sys/types.h>
1.28 +#include <stdint.h>
1.29 +
1.30 +
1.31 +
1.32 +#ifdef __cplusplus
1.33 +
1.34 +#include <l4/devices/cpm-x1600.h>
1.35 +#include <l4/devices/hw_mmio_register_block.h>
1.36 +
1.37 +// I2C channel.
1.38 +
1.39 +class I2c_x1600_channel
1.40 +{
1.41 +private:
1.42 + Hw::Register_block<32> _regs;
1.43 + Cpm_x1600_chip *_cpm;
1.44 + uint32_t _frequency;
1.45 +
1.46 + // Buffer management.
1.47 +
1.48 + unsigned int _pos, _reqpos, _total;
1.49 + uint8_t *_buf;
1.50 +
1.51 + // Status conditions.
1.52 +
1.53 + int _fail;
1.54 + int _stop;
1.55 +
1.56 +public:
1.57 + I2c_x1600_channel(l4_addr_t start, Cpm_x1600_chip *cpm,
1.58 + uint32_t frequency);
1.59 +
1.60 + uint32_t get_frequency();
1.61 + void set_target(uint8_t addr);
1.62 +
1.63 + // Reading initiation and execution.
1.64 +
1.65 + void start_read(uint8_t buf[], unsigned int total, int stop = 0);
1.66 + void read();
1.67 +
1.68 + // Writing initiation and execution.
1.69 +
1.70 + void start_write(uint8_t buf[], unsigned int total, int stop = 0);
1.71 + void write();
1.72 +
1.73 + // Transaction control.
1.74 +
1.75 + void stop();
1.76 + void disable();
1.77 +
1.78 + // Specific status conditions.
1.79 +
1.80 + unsigned int have_read();
1.81 + unsigned int have_written();
1.82 + int read_done();
1.83 + int write_done();
1.84 +
1.85 + int failed();
1.86 + int read_failed();
1.87 + int write_failed();
1.88 +
1.89 +private:
1.90 + void enable();
1.91 +
1.92 + int active();
1.93 + int have_input();
1.94 + int have_output();
1.95 + int can_send();
1.96 +
1.97 + void reset_flags();
1.98 + void init_parameters();
1.99 + void set_frequency();
1.100 +
1.101 + void set_read_threshold();
1.102 + void queue_reads();
1.103 + void queue_writes();
1.104 + void store_reads();
1.105 +};
1.106 +
1.107 +// I2C device control.
1.108 +
1.109 +class I2c_x1600_chip
1.110 +{
1.111 +private:
1.112 + l4_addr_t _start, _end;
1.113 + Cpm_x1600_chip *_cpm;
1.114 + uint32_t _frequency;
1.115 +
1.116 +public:
1.117 + I2c_x1600_chip(l4_addr_t start, l4_addr_t end, Cpm_x1600_chip *cpm,
1.118 + uint32_t frequency);
1.119 +
1.120 + I2c_x1600_channel *get_channel(uint8_t channel);
1.121 +};
1.122 +
1.123 +#endif /* __cplusplus */
1.124 +
1.125 +
1.126 +
1.127 +/* C language interface. */
1.128 +
1.129 +EXTERN_C_BEGIN
1.130 +
1.131 +void *x1600_i2c_init(l4_addr_t start, l4_addr_t end, void *cpm,
1.132 + uint32_t frequency);
1.133 +
1.134 +void x1600_i2c_disable(void *i2c_channel);
1.135 +
1.136 +void *x1600_i2c_get_channel(void *i2c, uint8_t channel);
1.137 +
1.138 +uint32_t x1600_i2c_get_frequency(void *i2c_channel);
1.139 +
1.140 +void x1600_i2c_set_target(void *i2c_channel, uint8_t addr);
1.141 +
1.142 +void x1600_i2c_start_read(void *i2c_channel, uint8_t buf[], unsigned int total,
1.143 + int stop);
1.144 +
1.145 +void x1600_i2c_read(void *i2c_channel);
1.146 +
1.147 +void x1600_i2c_start_write(void *i2c_channel, uint8_t buf[], unsigned int total,
1.148 + int stop);
1.149 +
1.150 +void x1600_i2c_write(void *i2c_channel);
1.151 +
1.152 +int x1600_i2c_read_done(void *i2c_channel);
1.153 +
1.154 +int x1600_i2c_write_done(void *i2c_channel);
1.155 +
1.156 +unsigned int x1600_i2c_have_read(void *i2c_channel);
1.157 +
1.158 +unsigned int x1600_i2c_have_written(void *i2c_channel);
1.159 +
1.160 +int x1600_i2c_failed(void *i2c_channel);
1.161 +
1.162 +void x1600_i2c_stop(void *i2c_channel);
1.163 +
1.164 +EXTERN_C_END
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
3.2 +++ b/pkg/devices/lib/i2c/src/x1600.cc Sat Oct 14 22:02:07 2023 +0200
3.3 @@ -0,0 +1,780 @@
3.4 +/*
3.5 + * I2C support for the X1600.
3.6 + *
3.7 + * Copyright (C) 2017, 2018, 2021, 2023 Paul Boddie <paul@boddie.org.uk>
3.8 + *
3.9 + * This program is free software; you can redistribute it and/or
3.10 + * modify it under the terms of the GNU General Public License as
3.11 + * published by the Free Software Foundation; either version 2 of
3.12 + * the License, or (at your option) any later version.
3.13 + *
3.14 + * This program is distributed in the hope that it will be useful,
3.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
3.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3.17 + * GNU General Public License for more details.
3.18 + *
3.19 + * You should have received a copy of the GNU General Public License
3.20 + * along with this program; if not, write to the Free Software
3.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
3.22 + * Boston, MA 02110-1301, USA
3.23 + */
3.24 +
3.25 +#include <l4/devices/i2c-x1600.h>
3.26 +#include <l4/devices/hw_mmio_register_block.h>
3.27 +
3.28 +#include <l4/sys/icu.h>
3.29 +#include <l4/util/util.h>
3.30 +#include <sys/time.h>
3.31 +
3.32 +/* NOTE: This peripheral is very similar to the JZ4780 with the registers
3.33 + renamed to I2C from SMB, with a few high speed registers added, and
3.34 + with I2C_SDAHD appearing at a different location. */
3.35 +
3.36 +enum Regs
3.37 +{
3.38 + I2c_control = 0x000, // I2C_CON
3.39 + I2c_target_address = 0x004, // I2C_TAR
3.40 + I2c_slave_address = 0x008, // I2C_SAR
3.41 + I2c_master_code = 0x00c, // I2C_HS_MADDR
3.42 + I2c_data_command = 0x010, // I2C_DC
3.43 + Std_high_count = 0x014, // I2C_SHCNT
3.44 + Std_low_count = 0x018, // I2C_SLCNT
3.45 + Fast_high_count = 0x01c, // I2C_FHCNT
3.46 + Fast_low_count = 0x020, // I2C_FLCNT
3.47 + High_high_count = 0x024, // I2C_HHCNT
3.48 + High_low_count = 0x028, // I2C_HLCNT
3.49 + Int_status = 0x02c, // I2C_INTST (read-only)
3.50 + Int_mask = 0x030, // I2C_INTM
3.51 + Int_raw_status = 0x034, // I2C_RINTST (read-only)
3.52 + Rx_fifo_thold = 0x038, // I2C_RXTL
3.53 + Tx_fifo_thold = 0x03c, // I2C_TXTL
3.54 + Int_combined_clear = 0x040, // I2C_CINT (read-only)
3.55 + Int_rx_uf_clear = 0x044, // I2C_CRXUF (read-only)
3.56 + Int_rx_of_clear = 0x048, // I2C_CRXOF (read-only)
3.57 + Int_tx_of_clear = 0x04c, // I2C_CTXOF (read-only)
3.58 + Int_rd_req_clear = 0x050, // I2C_CRXREQ (read-only)
3.59 + Int_tx_abort_clear = 0x054, // I2C_CTXABT (read-only)
3.60 + Int_rx_done_clear = 0x058, // I2C_CRXDN (read-only)
3.61 + Int_activity_clear = 0x05c, // I2C_CACT (read-only)
3.62 + Int_stop_clear = 0x060, // I2C_CSTP (read-only)
3.63 + Int_start_clear = 0x064, // I2C_CSTT (read-only)
3.64 + Int_call_clear = 0x068, // I2C_CGC (read-only)
3.65 + I2c_enable = 0x06c, // I2C_ENB
3.66 + I2c_status = 0x070, // I2C_ST (read-only)
3.67 + Tx_fifo_count = 0x074, // I2C_TXFLR (read-only)
3.68 + Rx_fifo_count = 0x078, // I2C_RXFLR (read-only)
3.69 + I2c_sda_hold_time = 0x07c, // I2C_SDAHD
3.70 + Trans_abort_status = 0x080, // I2C_ABTSRC (read-only)
3.71 + Slv_data_nack = 0x084, // I2CSDNACK
3.72 + I2c_dma_ctrl = 0x088, // I2C_DMACR
3.73 + I2c_trans_data_lvl = 0x08c, // I2C_DMATDLR
3.74 + I2c_recv_data_lvl = 0x090, // I2C_DMARDLR
3.75 + I2c_sda_setup_time = 0x094, // I2C_SDASU
3.76 + I2c_ack_call = 0x098, // I2C_ACKGC
3.77 + I2c_enable_status = 0x09c, // I2C_ENBST (read-only)
3.78 + I2c_spike_suppress = 0x0a0, // I2C_FSPKLEN
3.79 +
3.80 + I2c_block_offset = 0x1000
3.81 +};
3.82 +
3.83 +enum I2c_control_bits : unsigned
3.84 +{
3.85 + I2c_disable_slave = 0x40, // SLVDIS (slave disabled)
3.86 + I2c_enable_restart = 0x20, // RESTART
3.87 + I2c_master_10bit = 0x10, // MATP (read-only)
3.88 + I2c_slave_10bit = 0x08, // SATP
3.89 + I2c_speed_mode_mask = 0x06, // SPEED
3.90 + I2c_enable_master = 0x01, // MD (master enabled)
3.91 + I2c_speed_bit = 1, // SPD
3.92 +};
3.93 +
3.94 +enum I2c_speed_mode_values : unsigned
3.95 +{
3.96 + I2c_speed_standard = 1,
3.97 + I2c_speed_fast = 2,
3.98 + I2c_speed_high = 3,
3.99 +};
3.100 +
3.101 +enum I2c_enable_bits : unsigned
3.102 +{
3.103 + I2c_enable_enabled = 0x01, // I2CEN
3.104 +};
3.105 +
3.106 +enum I2c_status_bits : unsigned
3.107 +{
3.108 + I2c_status_master_act = 0x20, // MSTACT (master active)
3.109 + I2c_status_rx_nempty = 0x08, // RFNE (read queue not empty)
3.110 + I2c_status_tx_empty = 0x04, // TFE (write queue empty)
3.111 + I2c_status_tx_nfull = 0x02, // TFNF (write queue not full)
3.112 + I2c_status_active = 0x01, // ACT (device active as master or slave)
3.113 +};
3.114 +
3.115 +enum I2c_target_bits : unsigned
3.116 +{
3.117 + I2c_target_master_10bit = 0x1000,
3.118 + I2c_target_special = 0x0800, // SPECIAL: perform general call or start byte
3.119 + I2c_target_start_byte = 0x0400, // Special: start byte (1) or general call (0)
3.120 + I2c_target_10bits = 0x3ff, // Mask for 10-bit address
3.121 + I2c_target_7bits = 0x7f, // Mask for 7-bit address
3.122 +};
3.123 +
3.124 +enum I2c_hold_control_bits : unsigned
3.125 +{
3.126 + /* The hold enable flag has been removed since the JZ4780 and the hold time
3.127 + field widened. */
3.128 +
3.129 + I2c_hold_mask = 0xffff,
3.130 +};
3.131 +
3.132 +enum I2c_setup_control_bits : unsigned
3.133 +{
3.134 + I2c_setup_mask = 0x0ff, // SDASU
3.135 +};
3.136 +
3.137 +enum I2c_command_bits : unsigned
3.138 +{
3.139 + I2c_command_restart = 0x400, // RESTART: explicit restart before next byte
3.140 + I2c_command_stop = 0x200, // STOP: explicit stop after next byte
3.141 + I2c_command_no_stop = 0x000,
3.142 + I2c_command_read = 0x100, // CMD
3.143 + I2c_command_write = 0x000, // CMD
3.144 +};
3.145 +
3.146 +enum I2c_fifo_bits : unsigned
3.147 +{
3.148 + I2c_fifo_limit = 64, // RXTL, TXTL (256 noted in field description)
3.149 +};
3.150 +
3.151 +enum Int_bits : unsigned
3.152 +{
3.153 + Int_call = 0x800, // IGC (general call received)
3.154 + Int_start = 0x400, // ISTT (start/restart condition occurred)
3.155 + Int_stop = 0x200, // ISTP (stop condition occurred)
3.156 + Int_activity = 0x100, // IACT (bus activity interrupt)
3.157 + Int_rx_done = 0x080, // RXDN (read from master device done)
3.158 + Int_tx_abort = 0x040, // TXABT (transmit abort)
3.159 + Int_rd_req = 0x020, // RDREQ (read request from master device)
3.160 + Int_tx_empty = 0x010, // TXEMP (threshold reached or passed)
3.161 + Int_tx_of = 0x008, // TXOF (overflow when writing to queue)
3.162 + Int_rx_full = 0x004, // RXFL (threshold reached or exceeded)
3.163 + Int_rx_of = 0x002, // RXOF (overflow from device)
3.164 + Int_rx_uf = 0x001, // RXUF (underflow when reading from queue)
3.165 +};
3.166 +
3.167 +
3.168 +
3.169 +// Initialise a channel.
3.170 +
3.171 +I2c_x1600_channel::I2c_x1600_channel(l4_addr_t start,
3.172 + Cpm_x1600_chip *cpm,
3.173 + uint32_t frequency)
3.174 +: _cpm(cpm), _frequency(frequency)
3.175 +{
3.176 + _regs = new Hw::Mmio_register_block<32>(start);
3.177 +}
3.178 +
3.179 +// Enable the channel.
3.180 +
3.181 +void
3.182 +I2c_x1600_channel::enable()
3.183 +{
3.184 + _regs[I2c_enable] = I2c_enable_enabled;
3.185 + while (!(_regs[I2c_enable_status] & I2c_enable_enabled));
3.186 +}
3.187 +
3.188 +// Disable the channel.
3.189 +
3.190 +void
3.191 +I2c_x1600_channel::disable()
3.192 +{
3.193 + _regs[I2c_enable] = 0;
3.194 + while (_regs[I2c_enable_status] & I2c_enable_enabled);
3.195 +}
3.196 +
3.197 +// Return the configured frequency.
3.198 +
3.199 +uint32_t
3.200 +I2c_x1600_channel::get_frequency()
3.201 +{
3.202 + return _frequency;
3.203 +}
3.204 +
3.205 +// Set the frequency-related peripheral parameters.
3.206 +
3.207 +void
3.208 +I2c_x1600_channel::set_frequency()
3.209 +{
3.210 + // The APB clock (PCLK) is used to drive I2C transfers. Its value must be
3.211 + // obtained from the CPM unit. It is known as I2C_DEV_CLK here and is scaled
3.212 + // to kHz in order to keep the numbers easily representable, as is the bus
3.213 + // frequency.
3.214 +
3.215 + uint32_t i2c_dev_clk = _cpm->get_frequency(Clock_pclock) / 1000;
3.216 +
3.217 + // Note that this is not I2C_DEV_CLK but the actual I2C bus frequency.
3.218 +
3.219 + uint32_t i2c_clk = _frequency / 1000;
3.220 +
3.221 + // Select the appropriate speed.
3.222 +
3.223 + unsigned int speed = (i2c_clk <= 100) ? I2c_speed_standard
3.224 + : (i2c_clk <= 400 ? I2c_speed_fast
3.225 + : I2c_speed_high);
3.226 +
3.227 + // NOTE: Permit broader configuration elsewhere.
3.228 +
3.229 + _regs[I2c_control] = (speed << I2c_speed_bit) |
3.230 + I2c_disable_slave |
3.231 + I2c_enable_restart |
3.232 + I2c_enable_master;
3.233 +
3.234 + // According to the programming manual, if the PCLK period is T{I2C_DEV_CLK}
3.235 + // then the I2C clock period is...
3.236 +
3.237 + // T{SCL} = T{SCL_high} + T{SCL_low}
3.238 +
3.239 + // Where...
3.240 +
3.241 + // T{SCL_low} = T{I2C_DEV_CLK} * (#cycles for low signal)
3.242 + // T{SCL_high} = T{I2C_DEV_CLK} * (#cycles for high signal)
3.243 +
3.244 + // Since, with minimum periods being defined...
3.245 +
3.246 + // T{SCL} >= T{min_SCL}
3.247 + // T{SCL_low} >= T{min_SCL_low}
3.248 + // T{SCL_high} >= T{min_SCL_high}
3.249 + // T{min_SCL} = T{min_SCL_low} + T{min_SCL_high}
3.250 +
3.251 + // Then the following applies...
3.252 +
3.253 + // T{I2C_DEV_CLK} * (#cycles for low signal)) >= T{min_SCL_low}
3.254 + // T{I2C_DEV_CLK} * (#cycles for high signal) >= T{min_SCL_high}
3.255 +
3.256 + // To work with different clock speeds while maintaining the low-to-high
3.257 + // ratios:
3.258 +
3.259 + // T{min_SCL_low} = T{min_SCL} * T{min_SCL_low} / T{min_SCL}
3.260 + // = T{min_SCL} * (T{min_SCL_low} / (T{min_SCL_low} + T{min_SCL_high}))
3.261 +
3.262 + // T{min_SCL_high} = T{min_SCL} * T{min_SCL_high} / T{min_SCL}
3.263 + // = T{min_SCL} * (T{min_SCL_high} / (T{min_SCL_low} + T{min_SCL_high}))
3.264 +
3.265 + // Constraints are given with respect to the high and low count registers.
3.266 +
3.267 + // #cycles for high signal = I2CxHCNT + 8
3.268 + // #cycles for low signal = I2CxLCNT + 1
3.269 +
3.270 + // From earlier, this yields...
3.271 +
3.272 + // T{I2C_DEV_CLK} * (I2CxLCNT + 1) >= T{min_SCL_low}
3.273 + // T{I2C_DEV_CLK} * (I2CxHCNT + 8) >= T{min_SCL_high}
3.274 +
3.275 + // Rearranging...
3.276 +
3.277 + // I2CxLCNT >= (T{min_SCL_low} / T{I2C_DEV_CLK}) - 1
3.278 + // >= T{min_SCL_low} * I2C_DEV_CLK - 1
3.279 +
3.280 + // I2CxHCNT >= (T{min_SCL_high} / T{I2C_DEV_CLK}) - 8
3.281 + // >= T{min_SCL_high} * I2C_DEV_CLK - 8
3.282 +
3.283 + // Introducing the definitions for the high and low periods...
3.284 +
3.285 + // I2CxLCNT >= T{min_SCL} * (T{min_SCL_low} / (T{min_SCL_low} + T{min_SCL_high})) * I2C_DEV_CLK - 1
3.286 + // >= (T{min_SCL_low} / T{min_SCL}) * I2C_DEV_CLK / I2C_BUS_CLK - 1
3.287 +
3.288 + // I2CxHCNT >= T{min_SCL} * (T{min_SCL_high} / (T{min_SCL_low} + T{min_SCL_high})) * I2C_DEV_CLK - 8
3.289 + // >= (T{min_SCL_high} / T{min_SCL}) * I2C_DEV_CLK / I2C_BUS_CLK - 8
3.290 +
3.291 + uint32_t high_reg, low_reg;
3.292 + uint32_t high_count, low_count;
3.293 + int32_t hold_count;
3.294 + uint32_t setup_count;
3.295 +
3.296 + // Level hold times:
3.297 +
3.298 + // Standard Fast High
3.299 + // SCL low 4.7us 1.3us 0.5us
3.300 + // SCL high 4.0us 0.6us 0.26us +
3.301 + // SCL period 8.7us 1.9us 0.76us =
3.302 +
3.303 + // See: UM10204 "I2C-bus specification and user manual"
3.304 + // Table 10: t{LOW} and t{HIGH}
3.305 +
3.306 + if (i2c_clk <= 100) // 100 kHz
3.307 + {
3.308 + low_count = (i2c_dev_clk * 47) / (i2c_clk * 87) - 1;
3.309 + high_count = (i2c_dev_clk * 40) / (i2c_clk * 87) - 8;
3.310 + low_reg = Std_low_count;
3.311 + high_reg = Std_high_count;
3.312 + }
3.313 + else if (i2c_clk <= 400) // 400 kHz
3.314 + {
3.315 + low_count = (i2c_dev_clk * 13) / (i2c_clk * 19) - 1;
3.316 + high_count = (i2c_dev_clk * 6) / (i2c_clk * 19) - 8;
3.317 + low_reg = Fast_low_count;
3.318 + high_reg = Fast_high_count;
3.319 + }
3.320 + else // > 400 kHz
3.321 + {
3.322 + // Note how the frequencies are scaled to accommodate the extra precision
3.323 + // required.
3.324 +
3.325 + low_count = (i2c_dev_clk / 10 * 50) / (i2c_clk / 10 * 76) - 1;
3.326 + high_count = (i2c_dev_clk / 10 * 26) / (i2c_clk / 10 * 76) - 8;
3.327 + low_reg = High_low_count;
3.328 + high_reg = High_high_count;
3.329 + }
3.330 +
3.331 + // Minimum counts are 8 and 6 for low and high respectively.
3.332 +
3.333 + _regs[low_reg] = low_count < 8 ? 8 : low_count;
3.334 + _regs[high_reg] = high_count < 6 ? 6 : high_count;
3.335 +
3.336 + // Data hold and setup times:
3.337 +
3.338 + // Standard Fast High
3.339 + // t{HD;DAT} 300ns 300ns 300ns
3.340 + // t{SU;DAT} 250ns 100ns 50ns
3.341 +
3.342 + // See: UM10204 "I2C-bus specification and user manual"
3.343 + // Table 10: t{HD;DAT} and t{SU;DAT}, also note [3]
3.344 +
3.345 + // T{delay} = (I2CSDAHD + 2) * T{I2C_DEV_CLK}
3.346 + // I2CSDAHD = T{delay} / T{I2C_DEV_CLK} - 2
3.347 + // I2CSDAHD = I2C_DEV_CLK * T{delay} - 2
3.348 +
3.349 + // Since the device clock is in kHz (scaled down by 1000) and the times are
3.350 + // given in ns (scaled up by 1000000000), a division of 1000000 is introduced.
3.351 +
3.352 + hold_count = (i2c_dev_clk * 300) / 1000000 - 1;
3.353 +
3.354 + _regs[I2c_sda_hold_time] = (_regs[I2c_sda_hold_time] & ~I2c_hold_mask) |
3.355 + (hold_count < 0 ? 0
3.356 + : (hold_count < (int) I2c_hold_mask ? (uint32_t) hold_count
3.357 + : I2c_hold_mask));
3.358 +
3.359 + // I2C_SDASU is apparently not used in master mode.
3.360 +
3.361 + // T{delay} = (I2CSDASU - 1) * T{I2C_DEV_CLK}
3.362 + // I2CSDASU = T{delay} / T{I2C_DEV_CLK} + 1
3.363 + // I2CSDASU = I2C_DEV_CLK * T{delay} + 1
3.364 +
3.365 + if (i2c_clk <= 100)
3.366 + setup_count = (i2c_dev_clk * 250) / 1000000 + 1;
3.367 + else if (i2c_clk <= 400)
3.368 + setup_count = (i2c_dev_clk * 100) / 1000000 + 1;
3.369 + else
3.370 + setup_count = (i2c_dev_clk * 50) / 1000000 + 1;
3.371 +
3.372 + _regs[I2c_sda_setup_time] = (_regs[I2c_sda_setup_time] & ~I2c_setup_mask) |
3.373 + (setup_count < I2c_setup_mask ? setup_count : I2c_setup_mask);
3.374 +}
3.375 +
3.376 +// Set the target address and enable transfer.
3.377 +// NOTE: Only supporting 7-bit addresses currently.
3.378 +
3.379 +void
3.380 +I2c_x1600_channel::set_target(uint8_t address)
3.381 +{
3.382 + disable();
3.383 + set_frequency();
3.384 + _regs[I2c_target_address] = address & I2c_target_7bits;
3.385 + init_parameters();
3.386 + enable();
3.387 +}
3.388 +
3.389 +
3.390 +
3.391 +// Reset interrupt flags upon certain conditions.
3.392 +
3.393 +void
3.394 +I2c_x1600_channel::reset_flags()
3.395 +{
3.396 + volatile uint32_t r;
3.397 +
3.398 + _regs[Int_mask] = 0;
3.399 +
3.400 + // Read from the register to clear interrupts.
3.401 +
3.402 + r = _regs[Int_combined_clear];
3.403 + (void) r;
3.404 +}
3.405 +
3.406 +// Initialise interrupt flags and queue thresholds for reading and writing.
3.407 +
3.408 +void
3.409 +I2c_x1600_channel::init_parameters()
3.410 +{
3.411 + // Handle read queue conditions for data, write queue conditions for commands.
3.412 +
3.413 + reset_flags();
3.414 +
3.415 + _regs[Tx_fifo_thold] = 0; // write when 0 in queue
3.416 +}
3.417 +
3.418 +
3.419 +
3.420 +// Return whether the device is active.
3.421 +
3.422 +int
3.423 +I2c_x1600_channel::active()
3.424 +{
3.425 + return _regs[I2c_status] & I2c_status_master_act;
3.426 +}
3.427 +
3.428 +// Return whether data is available to receive.
3.429 +
3.430 +int
3.431 +I2c_x1600_channel::have_input()
3.432 +{
3.433 + return _regs[I2c_status] & I2c_status_rx_nempty;
3.434 +}
3.435 +
3.436 +// Return whether data is queued for sending.
3.437 +
3.438 +int
3.439 +I2c_x1600_channel::have_output()
3.440 +{
3.441 + return !(_regs[I2c_status] & I2c_status_tx_empty);
3.442 +}
3.443 +
3.444 +// Return whether data can be queued for sending.
3.445 +
3.446 +int
3.447 +I2c_x1600_channel::can_send()
3.448 +{
3.449 + return _regs[I2c_status] & I2c_status_tx_nfull;
3.450 +}
3.451 +
3.452 +// Return whether a receive operation has failed.
3.453 +
3.454 +int
3.455 +I2c_x1600_channel::read_failed()
3.456 +{
3.457 + return _regs[Int_status] & Int_rx_of;
3.458 +}
3.459 +
3.460 +// Return whether a send operation has failed.
3.461 +
3.462 +int
3.463 +I2c_x1600_channel::write_failed()
3.464 +{
3.465 + return _regs[Int_status] & Int_tx_abort;
3.466 +}
3.467 +
3.468 +int
3.469 +I2c_x1600_channel::read_done()
3.470 +{
3.471 + return _pos == _total;
3.472 +}
3.473 +
3.474 +int
3.475 +I2c_x1600_channel::write_done()
3.476 +{
3.477 + return (_reqpos == _total) && !have_output();
3.478 +}
3.479 +
3.480 +unsigned
3.481 +I2c_x1600_channel::have_read()
3.482 +{
3.483 + return _pos;
3.484 +}
3.485 +
3.486 +unsigned
3.487 +I2c_x1600_channel::have_written()
3.488 +{
3.489 + return _reqpos;
3.490 +}
3.491 +
3.492 +int
3.493 +I2c_x1600_channel::failed()
3.494 +{
3.495 + return _fail;
3.496 +}
3.497 +
3.498 +
3.499 +
3.500 +// Send read commands for empty queue entries.
3.501 +
3.502 +void
3.503 +I2c_x1600_channel::queue_reads()
3.504 +{
3.505 + unsigned int remaining = _total - _reqpos;
3.506 + unsigned int queued = _reqpos - _pos;
3.507 + unsigned int can_queue = I2c_fifo_limit - queued;
3.508 +
3.509 + // Keep the number of reads in progress below the length of the read queue.
3.510 +
3.511 + if (!can_queue)
3.512 + return;
3.513 +
3.514 + // At most, only queue as many reads as are remaining.
3.515 +
3.516 + if (remaining < can_queue)
3.517 + can_queue = remaining;
3.518 +
3.519 + // Queue read requests for any remaining queue entries.
3.520 +
3.521 + while (can_queue && can_send())
3.522 + {
3.523 + uint32_t stop = _stop && (_reqpos == _total - 1) ? I2c_command_stop : I2c_command_no_stop;
3.524 +
3.525 + _regs[I2c_data_command] = I2c_command_read | stop;
3.526 + _reqpos++;
3.527 + can_queue--;
3.528 + }
3.529 +
3.530 + // Update the threshold to be notified of any reduced remaining amount.
3.531 +
3.532 + set_read_threshold();
3.533 +}
3.534 +
3.535 +// Send write commands for empty queue entries.
3.536 +
3.537 +void
3.538 +I2c_x1600_channel::queue_writes()
3.539 +{
3.540 + unsigned int remaining = _total - _reqpos;
3.541 + unsigned int can_queue = I2c_fifo_limit;
3.542 +
3.543 + if (remaining < can_queue)
3.544 + can_queue = remaining;
3.545 +
3.546 + // Queue write requests for any remaining queue entries.
3.547 +
3.548 + while (can_queue && can_send())
3.549 + {
3.550 + uint32_t stop = _stop && (_reqpos == _total - 1) ? I2c_command_stop : I2c_command_no_stop;
3.551 +
3.552 + _regs[I2c_data_command] = I2c_command_write | _buf[_reqpos] | stop;
3.553 + _reqpos++;
3.554 + can_queue--;
3.555 + }
3.556 +}
3.557 +
3.558 +// Store read command results from the queue.
3.559 +
3.560 +void
3.561 +I2c_x1600_channel::store_reads()
3.562 +{
3.563 + // Read any input and store it in the buffer.
3.564 +
3.565 + while (have_input() && (_pos < _reqpos))
3.566 + {
3.567 + _buf[_pos] = _regs[I2c_data_command] & 0xff;
3.568 + _pos++;
3.569 + }
3.570 +}
3.571 +
3.572 +void
3.573 +I2c_x1600_channel::set_read_threshold()
3.574 +{
3.575 + unsigned int queued = _reqpos - _pos;
3.576 +
3.577 + if (!queued)
3.578 + return;
3.579 +
3.580 + // Read all expected.
3.581 +
3.582 + _regs[Rx_fifo_thold] = queued - 1;
3.583 +}
3.584 +
3.585 +// Read from the target device.
3.586 +
3.587 +void
3.588 +I2c_x1600_channel::start_read(uint8_t buf[], unsigned int total, int stop)
3.589 +{
3.590 + _buf = buf;
3.591 + _total = total;
3.592 + _pos = 0;
3.593 + _reqpos = 0;
3.594 + _fail = 0;
3.595 + _stop = stop;
3.596 +
3.597 + reset_flags();
3.598 +
3.599 + _regs[Int_mask] = Int_rx_full | // read condition (reading needed)
3.600 + Int_rx_of | // abort condition
3.601 + Int_tx_abort; // general abort condition
3.602 +
3.603 + // Perform initial read requests.
3.604 +
3.605 + read();
3.606 +}
3.607 +
3.608 +void
3.609 +I2c_x1600_channel::read()
3.610 +{
3.611 + // Test for the general transfer abort condition.
3.612 +
3.613 + if (read_failed() || write_failed())
3.614 + {
3.615 + _fail = 1;
3.616 + _regs[Int_mask] = 0;
3.617 + disable();
3.618 + enable();
3.619 + return;
3.620 + }
3.621 +
3.622 + if (_regs[Int_status] & Int_rx_full)
3.623 + store_reads();
3.624 +
3.625 + // Always attempt to queue more read requests.
3.626 +
3.627 + queue_reads();
3.628 +}
3.629 +
3.630 +// Write to the target device.
3.631 +
3.632 +void
3.633 +I2c_x1600_channel::start_write(uint8_t buf[], unsigned int total, int stop)
3.634 +{
3.635 + _buf = buf;
3.636 + _total = total;
3.637 + _reqpos = 0;
3.638 + _fail = 0;
3.639 + _stop = stop;
3.640 +
3.641 + reset_flags();
3.642 +
3.643 + // Enable interrupts for further writes.
3.644 +
3.645 + _regs[Int_mask] = Int_tx_empty | // write condition (writing needed)
3.646 + Int_tx_abort; // abort condition
3.647 +
3.648 + // Perform initial writes.
3.649 +
3.650 + write();
3.651 +}
3.652 +
3.653 +void
3.654 +I2c_x1600_channel::write()
3.655 +{
3.656 + if (write_failed())
3.657 + {
3.658 + _fail = 1;
3.659 + _regs[Int_mask] = 0;
3.660 + disable();
3.661 + enable();
3.662 + return;
3.663 + }
3.664 +
3.665 + if (_regs[Int_status] & Int_tx_empty)
3.666 + queue_writes();
3.667 +}
3.668 +
3.669 +// Explicitly stop communication.
3.670 +
3.671 +void
3.672 +I2c_x1600_channel::stop()
3.673 +{
3.674 +}
3.675 +
3.676 +
3.677 +
3.678 +// Initialise the I2C controller.
3.679 +
3.680 +I2c_x1600_chip::I2c_x1600_chip(l4_addr_t start, l4_addr_t end,
3.681 + Cpm_x1600_chip *cpm,
3.682 + uint32_t frequency)
3.683 +: _start(start), _end(end), _cpm(cpm), _frequency(frequency)
3.684 +{
3.685 +}
3.686 +
3.687 +// Obtain a channel object.
3.688 +
3.689 +I2c_x1600_channel *
3.690 +I2c_x1600_chip::get_channel(uint8_t channel)
3.691 +{
3.692 + l4_addr_t block = _start + channel * I2c_block_offset;
3.693 + enum Clock_identifiers bits[] = {Clock_i2c0, Clock_i2c1};
3.694 +
3.695 + if (channel < 2)
3.696 + {
3.697 + _cpm->start_clock(bits[channel]);
3.698 + return new I2c_x1600_channel(block, _cpm, _frequency);
3.699 + }
3.700 + else
3.701 + throw -L4_EINVAL;
3.702 +}
3.703 +
3.704 +
3.705 +
3.706 +// C language interface functions.
3.707 +
3.708 +void *x1600_i2c_init(l4_addr_t start, l4_addr_t end, void *cpm, uint32_t frequency)
3.709 +{
3.710 + return (void *) new I2c_x1600_chip(start, end, static_cast<Cpm_x1600_chip *>(cpm), frequency);
3.711 +}
3.712 +
3.713 +void x1600_i2c_disable(void *i2c_channel)
3.714 +{
3.715 + static_cast<I2c_x1600_channel *>(i2c_channel)->disable();
3.716 +}
3.717 +
3.718 +void *x1600_i2c_get_channel(void *i2c, uint8_t channel)
3.719 +{
3.720 + return static_cast<I2c_x1600_chip *>(i2c)->get_channel(channel);
3.721 +}
3.722 +
3.723 +uint32_t x1600_i2c_get_frequency(void *i2c_channel)
3.724 +{
3.725 + return static_cast<I2c_x1600_channel *>(i2c_channel)->get_frequency();
3.726 +}
3.727 +
3.728 +void x1600_i2c_set_target(void *i2c_channel, uint8_t addr)
3.729 +{
3.730 + static_cast<I2c_x1600_channel *>(i2c_channel)->set_target(addr);
3.731 +}
3.732 +
3.733 +void x1600_i2c_start_read(void *i2c_channel, uint8_t buf[], unsigned int total,
3.734 + int stop)
3.735 +{
3.736 + static_cast<I2c_x1600_channel *>(i2c_channel)->start_read(buf, total, stop);
3.737 +}
3.738 +
3.739 +void x1600_i2c_read(void *i2c_channel)
3.740 +{
3.741 + static_cast<I2c_x1600_channel *>(i2c_channel)->read();
3.742 +}
3.743 +
3.744 +void x1600_i2c_start_write(void *i2c_channel, uint8_t buf[], unsigned int total,
3.745 + int stop)
3.746 +{
3.747 + static_cast<I2c_x1600_channel *>(i2c_channel)->start_write(buf, total, stop);
3.748 +}
3.749 +
3.750 +void x1600_i2c_write(void *i2c_channel)
3.751 +{
3.752 + static_cast<I2c_x1600_channel *>(i2c_channel)->write();
3.753 +}
3.754 +
3.755 +int x1600_i2c_read_done(void *i2c_channel)
3.756 +{
3.757 + return static_cast<I2c_x1600_channel *>(i2c_channel)->read_done();
3.758 +}
3.759 +
3.760 +int x1600_i2c_write_done(void *i2c_channel)
3.761 +{
3.762 + return static_cast<I2c_x1600_channel *>(i2c_channel)->write_done();
3.763 +}
3.764 +
3.765 +unsigned int x1600_i2c_have_read(void *i2c_channel)
3.766 +{
3.767 + return static_cast<I2c_x1600_channel *>(i2c_channel)->have_read();
3.768 +}
3.769 +
3.770 +unsigned int x1600_i2c_have_written(void *i2c_channel)
3.771 +{
3.772 + return static_cast<I2c_x1600_channel *>(i2c_channel)->have_written();
3.773 +}
3.774 +
3.775 +int x1600_i2c_failed(void *i2c_channel)
3.776 +{
3.777 + return static_cast<I2c_x1600_channel *>(i2c_channel)->failed();
3.778 +}
3.779 +
3.780 +void x1600_i2c_stop(void *i2c_channel)
3.781 +{
3.782 + static_cast<I2c_x1600_channel *>(i2c_channel)->stop();
3.783 +}