1 /* 2 * I2C support for the JZ4730. 3 * 4 * Copyright (C) 2017, 2018, 2019, 2020 Paul Boddie <paul@boddie.org.uk> 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU General Public License as 8 * published by the Free Software Foundation; either version 2 of 9 * the License, or (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, 19 * Boston, MA 02110-1301, USA 20 */ 21 22 #pragma once 23 24 #include <l4/sys/types.h> 25 #include <stdint.h> 26 27 28 29 #ifdef __cplusplus 30 31 #include <l4/devices/cpm-jz4730.h> 32 #include <l4/devices/hw_mmio_register_block.h> 33 34 35 36 // State machine states. 37 38 enum I2c_jz4730_state 39 { 40 I2c_jz4730_end = 0, 41 I2c_jz4730_pre_start, 42 I2c_jz4730_start_read, 43 I2c_jz4730_perform_read, 44 I2c_jz4730_perform_write, 45 I2c_jz4730_stop_write 46 }; 47 48 49 50 // I2C channel. 51 52 class I2c_jz4730_channel 53 { 54 private: 55 Hw::Register_block<32> _regs; 56 Cpm_jz4730_chip *_cpm; 57 uint32_t _frequency; 58 l4_cap_idx_t _irq=L4_INVALID_CAP; 59 60 public: 61 I2c_jz4730_channel(l4_addr_t start, Cpm_jz4730_chip *cpm, 62 uint32_t frequency, l4_cap_idx_t irq); 63 64 void disable(); 65 void enable(); 66 67 unsigned int read(uint8_t address, uint8_t buf[], unsigned int length); 68 unsigned int write(uint8_t address, uint8_t buf[], unsigned int length); 69 70 protected: 71 void set_frequency(); 72 73 // State machine activities. 74 75 unsigned int _nread, _nwritten, _length, _limit; 76 uint8_t _address; 77 uint8_t *_buf; 78 bool _read; 79 80 void communicate(); 81 82 enum I2c_jz4730_state pre_start(); 83 enum I2c_jz4730_state start_read(); 84 enum I2c_jz4730_state perform_read(); 85 enum I2c_jz4730_state perform_write(); 86 enum I2c_jz4730_state stop_write(); 87 88 // Transaction control. 89 90 bool set_address(uint8_t address, bool read); 91 92 void clear_next(); 93 void send_next(); 94 void signal_last(); 95 96 void start(); 97 void stop(); 98 99 bool wait_for_irq(unsigned int timeout); 100 101 // Specific status conditions. 102 103 bool busy(); 104 bool data_valid(); 105 bool nack(); 106 bool transferred(); 107 bool transferring(); 108 }; 109 110 // I2C device control. 111 112 class I2c_jz4730_chip 113 { 114 private: 115 l4_addr_t _start, _end; 116 Cpm_jz4730_chip *_cpm; 117 uint32_t _frequency; 118 119 public: 120 I2c_jz4730_chip(l4_addr_t start, l4_addr_t end, Cpm_jz4730_chip *cpm, 121 uint32_t frequency); 122 123 I2c_jz4730_channel *get_channel(uint8_t channel, l4_cap_idx_t irq); 124 }; 125 126 #endif /* __cplusplus */ 127 128 129 130 /* C language interface. */ 131 132 EXTERN_C_BEGIN 133 134 void *jz4730_i2c_init(l4_addr_t start, l4_addr_t end, void *cpm, 135 uint32_t frequency); 136 137 void *jz4730_i2c_get_channel(void *i2c, uint8_t channel, l4_cap_idx_t irq); 138 139 void jz4730_i2c_disable(void *i2c_channel); 140 141 void jz4730_i2c_enable(void *i2c_channel); 142 143 unsigned int jz4730_i2c_read(void *i2c_channel, uint8_t address, uint8_t buf[], unsigned int length); 144 145 unsigned int jz4730_i2c_write(void *i2c_channel, uint8_t address, uint8_t buf[], unsigned int length); 146 147 EXTERN_C_END