| /* | |
| * include/aml_i2c.h | |
| * | |
| * Copyright (C) 2015 Amlogic, Inc. All rights reserved. | |
| * | |
| * This program is free software; you can redistribute it and/or modify | |
| * it under the terms of the GNU General Public License as published by | |
| * the Free Software Foundation; either version 2 of the License, or | |
| * (at your option) any later version. | |
| * | |
| * This program is distributed in the hope that it will be useful, but WITHOUT | |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | |
| * more details. | |
| * | |
| * You should have received a copy of the GNU General Public License along | |
| * with this program; if not, write to the Free Software Foundation, Inc., | |
| * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |
| */ | |
| #ifndef __AML_I2C_H__ | |
| #define __AML_I2C_H__ | |
| #include <common.h> | |
| #include <linux/compiler.h> | |
| #include <asm/arch/i2c.h> | |
| #define AML_I2C_MAX_TOKENS 8 | |
| /*I2C_CONTROL_REG 0x2140/0x2148*/ | |
| struct aml_i2c_reg_ctrl { | |
| unsigned int start:1; /*[0] Set to 1 to start list processing*/ | |
| /*Setting this bit to 0 while the list processor is operating causes the list | |
| processor to abort the current I2C operation and generate an I2C STOP | |
| command on the I2C bus. Normally this bit is set to 1 and left high | |
| until processing is complete. To re-start the list processor with a | |
| new list (after a previous list has been exhausted), simply set this | |
| bit to zero then to one.*/ | |
| unsigned int ack_ignore:1; /*[1] Set to 1 to disable I2C ACK detection.*/ | |
| /*The I2C bus uses an ACK signal after every byte transfer to detect | |
| problems during the transfer. Current Software implementations of the | |
| I2C bus ignore this ACK. This bit is for compatibility with the current | |
| Amlogic software. This bit should be set to 0 to allow NACK | |
| operations to abort I2C bus transactions. If a NACK occurs, the ERROR | |
| bit above will be set. */ | |
| unsigned int status:1; /*[2] the status of the List processor*/ | |
| #define I2C_IDLE 0 | |
| #define I2C_RUNNING 1 | |
| /* 0: IDLE | |
| 1: Running. The list processor will enter this state on the clock cycle | |
| after the START bit is set. The software can poll the status register to | |
| determine when processing is complete. | |
| */ | |
| unsigned int error:1; /*[3] */ | |
| /*This read only bit is set if the I2C device generates a NACK during writing. | |
| This bit is cleared at on the clock cycle after the START bit is set to 1 | |
| indicating the start of list processing. Errors can be ignored by setting | |
| the ACK_IGNORE bit below. Errors will be generated on Writes to | |
| devices that return NACK instead of ACK. A NACK is returned by a | |
| device if it is unable to accept any more data (for example because it | |
| is processing some other real-time function). In the event of an | |
| ERROR, the I2C module will automatically generate a STOP condition | |
| on the bus.*/ | |
| unsigned int cur_token:4; /*[7:4] the current token being processed*/ | |
| unsigned int rd_data_cnt:4;/*[11:8] number of bytes READ over the I2C bus*/ | |
| /*If this value is zero, then no data has been read. If this value is 1, then | |
| bits [7:0] in TOKEN_RDATA_REG0 contains valid data. The software can | |
| read this register after an I2C transaction to get the number of bytes to | |
| read from the I2C device*/ | |
| unsigned int clk_delay:10; /*[21:12] Quarter clock delay*/ | |
| /*This value corresponds to period of the SCL clock divided by 4 | |
| Quarter Clock Delay = * System Clock Frequency | |
| For example, if the system clock is 133Mhz, and the I2C clock period | |
| is 10uS (100khz), then | |
| Quarter Clock Delay = * 133 Mhz = 332 | |
| */ | |
| unsigned int manual_en:1; /*[22] enable manual mode. */ | |
| /*Manual I2C mode is controlled by bits 12,13,14 and 15 above.*/ | |
| unsigned int wrscl:1; /*[23] Sets the level of the SCL line */ | |
| /*if manual mode is enabled. If this bit is '0', then the SCL line is | |
| pulled low. If this bit is '1' then the SCL line is tri-stated.*/ | |
| unsigned int wrsda:1; /*[24] Sets the level of the SDA line */ | |
| /*if manual mode is enabled. If this bit is '0', then the SDA line is | |
| pulled low. If this bit is '1' then the SDA line is tri-stated.*/ | |
| unsigned int rdscl:1; /*[25] Read back level of the SCL line*/ | |
| unsigned int rdsda:1; /*[26] Read back level of the SDA line*/ | |
| #if 1 | |
| unsigned int unused:1; /*[27]*/ | |
| unsigned int clk_delay_ext:2; /*[29:28]*/ | |
| unsigned int unused2:2; /*[31:30]*/ | |
| #else | |
| unsigned int unused:5; /*[31:27]*/ | |
| #endif | |
| }; | |
| struct aml_i2c_reg_slave_addr { | |
| unsigned int slave_addr:8; /*[7:0] SLAVE ADDRESS.*/ | |
| /*This is a 7-bit value for a 7-bit I2C device, or (0xF0 | {A9,A8}) for a | |
| 10 bit I2C device. By convention, the slave address is typically | |
| stored in by first left shifting it so that it's MSB is D7 (The I2C bus | |
| assumes the 7-bit address is left shifted one). Additionally, since | |
| the SLAVE address is always an 7-bit value, D0 is always 0. | |
| NOTE: The I2C always transfers 8-bits even for address. The I2C | |
| hardware will use D0 to dictate the direction of the bus. Therefore, | |
| D0 should always be '0' when this register is set. | |
| */ | |
| unsigned int sda_filter:3; /*[10:8] SDA FILTER*/ | |
| /*A filter was added in the SCL input path to allow for filtering of slow | |
| rise times. 0 = no filtering, 7 = max filtering*/ | |
| unsigned int scl_filter:3; /*[13:11] SCL FILTER*/ | |
| /*A filter was added in the SCL input path to allow for filtering of slow | |
| rise times. 0 = no filtering, 7 = max filtering*/ | |
| #if 1 | |
| unsigned int unused:2; /*[15:14]*/ | |
| unsigned int clk_low_delay:12; /*[27:16]*/ | |
| unsigned int clk_low_delay_en:1; /*[28]*/ | |
| unsigned int unused2:3; /*[31:29]*/ | |
| #else | |
| unsigned int unused:18; /*[31:14]*/ | |
| #endif | |
| }; | |
| /*Write data associated with the DATA token should be placed into the | |
| I2C_TOKEN_WDATA_REG0 or I2C_TOKEN_WDATA_REG1 registers. | |
| Read data associated with the DATA or DATA-LAST token can be read from | |
| the I2C_TOKEN_RDATA_REG0 or I2C_TOKEN_RDATA_REG1 registers*/ | |
| enum aml_i2c_token { | |
| TOKEN_END, | |
| TOKEN_START, | |
| TOKEN_SLAVE_ADDR_WRITE, | |
| TOKEN_SLAVE_ADDR_READ, | |
| TOKEN_DATA, | |
| TOKEN_DATA_LAST, | |
| TOKEN_STOP | |
| }; | |
| struct aml_i2c_reg_master { | |
| volatile unsigned int i2c_ctrl; | |
| volatile unsigned int i2c_slave_addr; | |
| volatile unsigned int i2c_token_list_0; | |
| volatile unsigned int i2c_token_list_1; | |
| volatile unsigned int i2c_token_wdata_0; | |
| volatile unsigned int i2c_token_wdata_1; | |
| volatile unsigned int i2c_token_rdata_0; | |
| volatile unsigned int i2c_token_rdata_1; | |
| }; | |
| struct aml_i2c_reg_slave_ctrl { | |
| unsigned int samp_rate:7; /*[6:0] sampling rate*/ | |
| /*Defined as MPEG system clock / (value + 1). The SDA and SCL inputs into | |
| the slave module are sampled as a way of filtering the inputs. A | |
| rising or falling edge is determined by when 3 successive samples are | |
| either high or low respectively*/ | |
| unsigned int enable:1; /*[7] A '1' enables the I2C slave state machine*/ | |
| unsigned int hold_time:8; /*[15:8]*/ | |
| /*Data hold time after the falling edge of SCL. | |
| Hold time = (MPEG system clock period) * (value + 1). | |
| */ | |
| unsigned int slave_addr:8; /*[23-16]*/ | |
| /*Bits [7:1] are used to identify the device. | |
| Bit [0] is ignored since this corresponds to the R/W bit.*/ | |
| unsigned int ack_always:1; /*[24]*/ | |
| /*Typically the ACK of a slave I2C device is dependent upon the | |
| availability of data (if reading) and room to store data (when we are | |
| being written). Our I2C module has a status register that can be read | |
| continuously. This bit can be set if the I2C master wants to | |
| continually read the status register. */ | |
| unsigned int irq_en:1; /*[25]*/ | |
| /*If this bit is set, then an interrupt will be sent to the ARC whenever 4 | |
| bytes have been read or 4 bytes have been written to the I2C slave | |
| module.*/ | |
| unsigned int busy:1; /*[26] */ | |
| /*Read only status bit. '1' indicates that the I2C slave module is sending | |
| or receiving data.*/ | |
| unsigned int rx_rdy:1; /*[27] */ | |
| /*This bit is set to '1' by the ARC to indicate to the slave machine that | |
| the I2C slave module is ready to receive data. This bit is cleared by | |
| the I2C module when it has received 4 bytes from the I2C master. | |
| This bit is also available in the status register that can be read by | |
| the I2C master. The I2C master can read the status register to see | |
| when the I2C slave module is ready to receive data.*/ | |
| unsigned int tx_rdy:1; /*[28] */ | |
| /*This bit is set to '1' by the ARC to indicate to the slave machine that | |
| the I2C slave module is ready to send data. This bit is cleared by | |
| the I2C module when it has sent 4 bytes to the I2C master. This bit | |
| is also available in the status register that can be read by the I2C | |
| master. The I2C master can read the status register to see when the | |
| I2C slave module has data to send.*/ | |
| unsigned int reg_ptr:3; /*[31:29] */ | |
| /*There are 5 internal registers inside the I2C slave module. The I2C | |
| Master sets this value using the byte that follows the address byte | |
| in the I2C data stream. Register 4 (numbered 0,1,¡4) is the | |
| status register.*/ | |
| }; | |
| struct aml_i2c_reg_slave{ | |
| unsigned int i2c_slave_ctrl; | |
| unsigned int i2c_slave_tx_data; | |
| unsigned int i2c_slave_rx_data; | |
| }; | |
| struct aml_i2c { | |
| unsigned int i2c_debug; | |
| unsigned int cur_slave_addr; | |
| unsigned int wait_count; | |
| unsigned int wait_ack_interval; | |
| unsigned int wait_read_interval; | |
| unsigned int wait_xfer_interval; | |
| unsigned int master_no;/*master a:0 master b:1*/ | |
| #define I2C_MASTER_AO 0 | |
| #define I2C_MASTER_A 1 | |
| #define I2C_MASTER_B 2 | |
| #define I2C_MASTER_C 3 | |
| #define I2C_MASTER_D 4 | |
| unsigned char token_tag[AML_I2C_MAX_TOKENS]; | |
| unsigned int msg_flags; | |
| struct aml_i2c_ops* ops; | |
| struct aml_i2c_reg_master __iomem* master_regs; | |
| //#ifdef CONFIG_I2C_AML_SLAVE | |
| struct aml_i2c_reg_slave __iomem* slave_regs; | |
| struct aml_pinmux_reg_bit slave_pinmux; | |
| unsigned int slave_dev_addr; | |
| //#endif | |
| void __iomem *reg_base; | |
| struct aml_pinmux_reg_bit master_pinmux; | |
| int irq; | |
| unsigned int use_pio;/*0: hardware i2c, 1: pio i2c*/ | |
| unsigned int master_i2c_speed; | |
| }; | |
| struct aml_i2c_ops { | |
| void (*xfer_prepare)(struct aml_i2c *i2c); | |
| int (*do_address)(struct aml_i2c *i2c, unsigned int addr); | |
| ssize_t (*read)(struct aml_i2c *i2c, unsigned char *buf, size_t len); | |
| ssize_t (*write)(struct aml_i2c *i2c, unsigned char *buf, size_t len); | |
| void (*stop)(struct aml_i2c *i2c); | |
| }; | |
| int aml_i2c_init(void); | |
| int aml_i2c_xfer(struct i2c_msg *msgs, int num); | |
| /*General i2c master transfer,it can Send to a specific master control*/ | |
| int aml_i2c_transfer(int adap_num , struct i2c_msg *msgs , int num); | |
| enum aml_i2c_id{ | |
| SOFT_I2C = 0, | |
| HARD_I2C, | |
| }; | |
| struct i2c_board_info { | |
| char type[64]; | |
| int i2c_id; | |
| unsigned short addr; | |
| void (*device_init)(void); | |
| void (*device_uninit)(void); | |
| }; | |
| #define I2C_BOARD_INFO(dev_type, dev_addr) \ | |
| .type = dev_type, .addr = (dev_addr) | |
| struct aml_i2c_device { | |
| struct i2c_borad_info *aml_i2c_boards; | |
| unsigned dev_num; | |
| }; | |
| #ifdef AML_MESON_BOARD_8726M_2010_11_18_V11 | |
| //Please refer board schematic for detail pin connection | |
| //@AML8726-M_ARM_DEV_BOARD_2DDR_V1R1.pdf | |
| //port27-> Red (0x7F) | |
| //port26-> Green (0xBF) | |
| //port25-> Blue (0xDF) | |
| #define I2C_LED_RED (0x7F) | |
| #define I2C_LED_GREEN (0xBF) | |
| #define I2C_LED_BLUE (0xDF) | |
| //To set onboard LEDs on/off | |
| void board_i2c_led_set(unsigned char byLED, unsigned char byOn); | |
| #endif //AML_MESON_BOARD_8726M_2010_11_18_V11 | |
| #endif //__AML_I2C_H__ |