18934f784SMichal Simek /*
28934f784SMichal Simek * Driver for the Zynq-7000 PS I2C controller
38934f784SMichal Simek * IP from Cadence (ID T-CS-PE-0007-100, Version R1p10f2)
48934f784SMichal Simek *
58934f784SMichal Simek * Author: Joe Hershberger <joe.hershberger@ni.com>
68934f784SMichal Simek * Copyright (c) 2012 Joe Hershberger.
78934f784SMichal Simek *
88934f784SMichal Simek * Copyright (c) 2012-2013 Xilinx, Michal Simek
98934f784SMichal Simek *
101a459660SWolfgang Denk * SPDX-License-Identifier: GPL-2.0+
11*28527096SSimon Glass *
12*28527096SSimon Glass * NOTE: This driver should be converted to driver model before June 2017.
13*28527096SSimon Glass * Please see doc/driver-model/i2c-howto.txt for instructions.
148934f784SMichal Simek */
158934f784SMichal Simek
168934f784SMichal Simek #include <common.h>
178934f784SMichal Simek #include <asm/io.h>
188934f784SMichal Simek #include <i2c.h>
191221ce45SMasahiro Yamada #include <linux/errno.h>
208934f784SMichal Simek #include <asm/arch/hardware.h>
218934f784SMichal Simek
228934f784SMichal Simek /* i2c register set */
238934f784SMichal Simek struct zynq_i2c_registers {
248934f784SMichal Simek u32 control;
258934f784SMichal Simek u32 status;
268934f784SMichal Simek u32 address;
278934f784SMichal Simek u32 data;
288934f784SMichal Simek u32 interrupt_status;
298934f784SMichal Simek u32 transfer_size;
308934f784SMichal Simek u32 slave_mon_pause;
318934f784SMichal Simek u32 time_out;
328934f784SMichal Simek u32 interrupt_mask;
338934f784SMichal Simek u32 interrupt_enable;
348934f784SMichal Simek u32 interrupt_disable;
358934f784SMichal Simek };
368934f784SMichal Simek
378934f784SMichal Simek /* Control register fields */
388934f784SMichal Simek #define ZYNQ_I2C_CONTROL_RW 0x00000001
398934f784SMichal Simek #define ZYNQ_I2C_CONTROL_MS 0x00000002
408934f784SMichal Simek #define ZYNQ_I2C_CONTROL_NEA 0x00000004
418934f784SMichal Simek #define ZYNQ_I2C_CONTROL_ACKEN 0x00000008
428934f784SMichal Simek #define ZYNQ_I2C_CONTROL_HOLD 0x00000010
438934f784SMichal Simek #define ZYNQ_I2C_CONTROL_SLVMON 0x00000020
448934f784SMichal Simek #define ZYNQ_I2C_CONTROL_CLR_FIFO 0x00000040
458934f784SMichal Simek #define ZYNQ_I2C_CONTROL_DIV_B_SHIFT 8
468934f784SMichal Simek #define ZYNQ_I2C_CONTROL_DIV_B_MASK 0x00003F00
478934f784SMichal Simek #define ZYNQ_I2C_CONTROL_DIV_A_SHIFT 14
488934f784SMichal Simek #define ZYNQ_I2C_CONTROL_DIV_A_MASK 0x0000C000
498934f784SMichal Simek
508934f784SMichal Simek /* Status register values */
518934f784SMichal Simek #define ZYNQ_I2C_STATUS_RXDV 0x00000020
528934f784SMichal Simek #define ZYNQ_I2C_STATUS_TXDV 0x00000040
538934f784SMichal Simek #define ZYNQ_I2C_STATUS_RXOVF 0x00000080
548934f784SMichal Simek #define ZYNQ_I2C_STATUS_BA 0x00000100
558934f784SMichal Simek
568934f784SMichal Simek /* Interrupt register fields */
578934f784SMichal Simek #define ZYNQ_I2C_INTERRUPT_COMP 0x00000001
588934f784SMichal Simek #define ZYNQ_I2C_INTERRUPT_DATA 0x00000002
598934f784SMichal Simek #define ZYNQ_I2C_INTERRUPT_NACK 0x00000004
608934f784SMichal Simek #define ZYNQ_I2C_INTERRUPT_TO 0x00000008
618934f784SMichal Simek #define ZYNQ_I2C_INTERRUPT_SLVRDY 0x00000010
628934f784SMichal Simek #define ZYNQ_I2C_INTERRUPT_RXOVF 0x00000020
638934f784SMichal Simek #define ZYNQ_I2C_INTERRUPT_TXOVF 0x00000040
648934f784SMichal Simek #define ZYNQ_I2C_INTERRUPT_RXUNF 0x00000080
658934f784SMichal Simek #define ZYNQ_I2C_INTERRUPT_ARBLOST 0x00000200
668934f784SMichal Simek
678934f784SMichal Simek #define ZYNQ_I2C_FIFO_DEPTH 16
688934f784SMichal Simek #define ZYNQ_I2C_TRANSFERT_SIZE_MAX 255 /* Controller transfer limit */
698934f784SMichal Simek
i2c_select(struct i2c_adapter * adap)7018948632SMichael Burr static struct zynq_i2c_registers *i2c_select(struct i2c_adapter *adap)
7118948632SMichael Burr {
7218948632SMichael Burr return adap->hwadapnr ?
7318948632SMichael Burr /* Zynq PS I2C1 */
7418948632SMichael Burr (struct zynq_i2c_registers *)ZYNQ_I2C_BASEADDR1 :
7518948632SMichael Burr /* Zynq PS I2C0 */
7618948632SMichael Burr (struct zynq_i2c_registers *)ZYNQ_I2C_BASEADDR0;
7718948632SMichael Burr }
788934f784SMichal Simek
798934f784SMichal Simek /* I2C init called by cmd_i2c when doing 'i2c reset'. */
zynq_i2c_init(struct i2c_adapter * adap,int requested_speed,int slaveadd)800bdffe71SHeiko Schocher static void zynq_i2c_init(struct i2c_adapter *adap, int requested_speed,
810bdffe71SHeiko Schocher int slaveadd)
828934f784SMichal Simek {
8318948632SMichael Burr struct zynq_i2c_registers *zynq_i2c = i2c_select(adap);
8418948632SMichael Burr
858934f784SMichal Simek /* 111MHz / ( (3 * 17) * 22 ) = ~100KHz */
868934f784SMichal Simek writel((16 << ZYNQ_I2C_CONTROL_DIV_B_SHIFT) |
878934f784SMichal Simek (2 << ZYNQ_I2C_CONTROL_DIV_A_SHIFT), &zynq_i2c->control);
888934f784SMichal Simek
898934f784SMichal Simek /* Enable master mode, ack, and 7-bit addressing */
908934f784SMichal Simek setbits_le32(&zynq_i2c->control, ZYNQ_I2C_CONTROL_MS |
918934f784SMichal Simek ZYNQ_I2C_CONTROL_ACKEN | ZYNQ_I2C_CONTROL_NEA);
928934f784SMichal Simek }
938934f784SMichal Simek
948934f784SMichal Simek #ifdef DEBUG
zynq_i2c_debug_status(struct zynq_i2c_registers * zynq_i2c)9518948632SMichael Burr static void zynq_i2c_debug_status(struct zynq_i2c_registers *zynq_i2c)
968934f784SMichal Simek {
978934f784SMichal Simek int int_status;
988934f784SMichal Simek int status;
998934f784SMichal Simek int_status = readl(&zynq_i2c->interrupt_status);
1008934f784SMichal Simek
1018934f784SMichal Simek status = readl(&zynq_i2c->status);
1028934f784SMichal Simek if (int_status || status) {
1038934f784SMichal Simek debug("Status: ");
1048934f784SMichal Simek if (int_status & ZYNQ_I2C_INTERRUPT_COMP)
1058934f784SMichal Simek debug("COMP ");
1068934f784SMichal Simek if (int_status & ZYNQ_I2C_INTERRUPT_DATA)
1078934f784SMichal Simek debug("DATA ");
1088934f784SMichal Simek if (int_status & ZYNQ_I2C_INTERRUPT_NACK)
1098934f784SMichal Simek debug("NACK ");
1108934f784SMichal Simek if (int_status & ZYNQ_I2C_INTERRUPT_TO)
1118934f784SMichal Simek debug("TO ");
1128934f784SMichal Simek if (int_status & ZYNQ_I2C_INTERRUPT_SLVRDY)
1138934f784SMichal Simek debug("SLVRDY ");
1148934f784SMichal Simek if (int_status & ZYNQ_I2C_INTERRUPT_RXOVF)
1158934f784SMichal Simek debug("RXOVF ");
1168934f784SMichal Simek if (int_status & ZYNQ_I2C_INTERRUPT_TXOVF)
1178934f784SMichal Simek debug("TXOVF ");
1188934f784SMichal Simek if (int_status & ZYNQ_I2C_INTERRUPT_RXUNF)
1198934f784SMichal Simek debug("RXUNF ");
1208934f784SMichal Simek if (int_status & ZYNQ_I2C_INTERRUPT_ARBLOST)
1218934f784SMichal Simek debug("ARBLOST ");
1228934f784SMichal Simek if (status & ZYNQ_I2C_STATUS_RXDV)
1238934f784SMichal Simek debug("RXDV ");
1248934f784SMichal Simek if (status & ZYNQ_I2C_STATUS_TXDV)
1258934f784SMichal Simek debug("TXDV ");
1268934f784SMichal Simek if (status & ZYNQ_I2C_STATUS_RXOVF)
1278934f784SMichal Simek debug("RXOVF ");
1288934f784SMichal Simek if (status & ZYNQ_I2C_STATUS_BA)
1298934f784SMichal Simek debug("BA ");
1308934f784SMichal Simek debug("TS%d ", readl(&zynq_i2c->transfer_size));
1318934f784SMichal Simek debug("\n");
1328934f784SMichal Simek }
1338934f784SMichal Simek }
1348934f784SMichal Simek #endif
1358934f784SMichal Simek
1368934f784SMichal Simek /* Wait for an interrupt */
zynq_i2c_wait(struct zynq_i2c_registers * zynq_i2c,u32 mask)13718948632SMichael Burr static u32 zynq_i2c_wait(struct zynq_i2c_registers *zynq_i2c, u32 mask)
1388934f784SMichal Simek {
1398934f784SMichal Simek int timeout, int_status;
1408934f784SMichal Simek
1418934f784SMichal Simek for (timeout = 0; timeout < 100; timeout++) {
1428934f784SMichal Simek udelay(100);
1438934f784SMichal Simek int_status = readl(&zynq_i2c->interrupt_status);
1448934f784SMichal Simek if (int_status & mask)
1458934f784SMichal Simek break;
1468934f784SMichal Simek }
1478934f784SMichal Simek #ifdef DEBUG
1485146fc2bSJesper B. Christensen zynq_i2c_debug_status(zynq_i2c);
1498934f784SMichal Simek #endif
1508934f784SMichal Simek /* Clear interrupt status flags */
1518934f784SMichal Simek writel(int_status & mask, &zynq_i2c->interrupt_status);
1528934f784SMichal Simek
1538934f784SMichal Simek return int_status & mask;
1548934f784SMichal Simek }
1558934f784SMichal Simek
1568934f784SMichal Simek /*
1578934f784SMichal Simek * I2C probe called by cmd_i2c when doing 'i2c probe'.
1588934f784SMichal Simek * Begin read, nak data byte, end.
1598934f784SMichal Simek */
zynq_i2c_probe(struct i2c_adapter * adap,u8 dev)1600bdffe71SHeiko Schocher static int zynq_i2c_probe(struct i2c_adapter *adap, u8 dev)
1618934f784SMichal Simek {
16218948632SMichael Burr struct zynq_i2c_registers *zynq_i2c = i2c_select(adap);
16318948632SMichael Burr
1648934f784SMichal Simek /* Attempt to read a byte */
1658934f784SMichal Simek setbits_le32(&zynq_i2c->control, ZYNQ_I2C_CONTROL_CLR_FIFO |
1668934f784SMichal Simek ZYNQ_I2C_CONTROL_RW);
1678934f784SMichal Simek clrbits_le32(&zynq_i2c->control, ZYNQ_I2C_CONTROL_HOLD);
1688934f784SMichal Simek writel(0xFF, &zynq_i2c->interrupt_status);
1698934f784SMichal Simek writel(dev, &zynq_i2c->address);
1708934f784SMichal Simek writel(1, &zynq_i2c->transfer_size);
1718934f784SMichal Simek
17218948632SMichael Burr return (zynq_i2c_wait(zynq_i2c, ZYNQ_I2C_INTERRUPT_COMP |
1738934f784SMichal Simek ZYNQ_I2C_INTERRUPT_NACK) &
1748934f784SMichal Simek ZYNQ_I2C_INTERRUPT_COMP) ? 0 : -ETIMEDOUT;
1758934f784SMichal Simek }
1768934f784SMichal Simek
1778934f784SMichal Simek /*
1788934f784SMichal Simek * I2C read called by cmd_i2c when doing 'i2c read' and by cmd_eeprom.c
1798934f784SMichal Simek * Begin write, send address byte(s), begin read, receive data bytes, end.
1808934f784SMichal Simek */
zynq_i2c_read(struct i2c_adapter * adap,u8 dev,uint addr,int alen,u8 * data,int length)1810bdffe71SHeiko Schocher static int zynq_i2c_read(struct i2c_adapter *adap, u8 dev, uint addr,
1820bdffe71SHeiko Schocher int alen, u8 *data, int length)
1838934f784SMichal Simek {
1848934f784SMichal Simek u32 status;
1858934f784SMichal Simek u32 i = 0;
1868934f784SMichal Simek u8 *cur_data = data;
18718948632SMichael Burr struct zynq_i2c_registers *zynq_i2c = i2c_select(adap);
1888934f784SMichal Simek
1898934f784SMichal Simek /* Check the hardware can handle the requested bytes */
1908934f784SMichal Simek if ((length < 0) || (length > ZYNQ_I2C_TRANSFERT_SIZE_MAX))
1918934f784SMichal Simek return -EINVAL;
1928934f784SMichal Simek
1938934f784SMichal Simek /* Write the register address */
1948934f784SMichal Simek setbits_le32(&zynq_i2c->control, ZYNQ_I2C_CONTROL_CLR_FIFO |
1958934f784SMichal Simek ZYNQ_I2C_CONTROL_HOLD);
1968934f784SMichal Simek /*
1978934f784SMichal Simek * Temporarily disable restart (by clearing hold)
1988934f784SMichal Simek * It doesn't seem to work.
1998934f784SMichal Simek */
2009e901071SMichael Burr clrbits_le32(&zynq_i2c->control, ZYNQ_I2C_CONTROL_HOLD);
2018934f784SMichal Simek writel(0xFF, &zynq_i2c->interrupt_status);
2029e901071SMichael Burr if (alen) {
2039e901071SMichael Burr clrbits_le32(&zynq_i2c->control, ZYNQ_I2C_CONTROL_RW);
2049e901071SMichael Burr writel(dev, &zynq_i2c->address);
2058934f784SMichal Simek while (alen--)
2068934f784SMichal Simek writel(addr >> (8 * alen), &zynq_i2c->data);
2078934f784SMichal Simek
2088934f784SMichal Simek /* Wait for the address to be sent */
20918948632SMichael Burr if (!zynq_i2c_wait(zynq_i2c, ZYNQ_I2C_INTERRUPT_COMP)) {
2108934f784SMichal Simek /* Release the bus */
2118934f784SMichal Simek clrbits_le32(&zynq_i2c->control, ZYNQ_I2C_CONTROL_HOLD);
2128934f784SMichal Simek return -ETIMEDOUT;
2138934f784SMichal Simek }
2148934f784SMichal Simek debug("Device acked address\n");
2159e901071SMichael Burr }
2168934f784SMichal Simek
2178934f784SMichal Simek setbits_le32(&zynq_i2c->control, ZYNQ_I2C_CONTROL_CLR_FIFO |
2188934f784SMichal Simek ZYNQ_I2C_CONTROL_RW);
2198934f784SMichal Simek /* Start reading data */
2208934f784SMichal Simek writel(dev, &zynq_i2c->address);
2218934f784SMichal Simek writel(length, &zynq_i2c->transfer_size);
2228934f784SMichal Simek
2238934f784SMichal Simek /* Wait for data */
2248934f784SMichal Simek do {
22518948632SMichael Burr status = zynq_i2c_wait(zynq_i2c, ZYNQ_I2C_INTERRUPT_COMP |
2268934f784SMichal Simek ZYNQ_I2C_INTERRUPT_DATA);
2278934f784SMichal Simek if (!status) {
2288934f784SMichal Simek /* Release the bus */
2298934f784SMichal Simek clrbits_le32(&zynq_i2c->control, ZYNQ_I2C_CONTROL_HOLD);
2308934f784SMichal Simek return -ETIMEDOUT;
2318934f784SMichal Simek }
2328934f784SMichal Simek debug("Read %d bytes\n",
2338934f784SMichal Simek length - readl(&zynq_i2c->transfer_size));
2348934f784SMichal Simek for (; i < length - readl(&zynq_i2c->transfer_size); i++)
2358934f784SMichal Simek *(cur_data++) = readl(&zynq_i2c->data);
2368934f784SMichal Simek } while (readl(&zynq_i2c->transfer_size) != 0);
2378934f784SMichal Simek /* All done... release the bus */
2388934f784SMichal Simek clrbits_le32(&zynq_i2c->control, ZYNQ_I2C_CONTROL_HOLD);
2398934f784SMichal Simek
2408934f784SMichal Simek #ifdef DEBUG
2415146fc2bSJesper B. Christensen zynq_i2c_debug_status(zynq_i2c);
2428934f784SMichal Simek #endif
2438934f784SMichal Simek return 0;
2448934f784SMichal Simek }
2458934f784SMichal Simek
2468934f784SMichal Simek /*
2478934f784SMichal Simek * I2C write called by cmd_i2c when doing 'i2c write' and by cmd_eeprom.c
2488934f784SMichal Simek * Begin write, send address byte(s), send data bytes, end.
2498934f784SMichal Simek */
zynq_i2c_write(struct i2c_adapter * adap,u8 dev,uint addr,int alen,u8 * data,int length)2500bdffe71SHeiko Schocher static int zynq_i2c_write(struct i2c_adapter *adap, u8 dev, uint addr,
2510bdffe71SHeiko Schocher int alen, u8 *data, int length)
2528934f784SMichal Simek {
2538934f784SMichal Simek u8 *cur_data = data;
25418948632SMichael Burr struct zynq_i2c_registers *zynq_i2c = i2c_select(adap);
2558934f784SMichal Simek
2568934f784SMichal Simek /* Write the register address */
2578934f784SMichal Simek setbits_le32(&zynq_i2c->control, ZYNQ_I2C_CONTROL_CLR_FIFO |
2588934f784SMichal Simek ZYNQ_I2C_CONTROL_HOLD);
2598934f784SMichal Simek clrbits_le32(&zynq_i2c->control, ZYNQ_I2C_CONTROL_RW);
2608934f784SMichal Simek writel(0xFF, &zynq_i2c->interrupt_status);
2619e901071SMichael Burr writel(dev, &zynq_i2c->address);
2629e901071SMichael Burr if (alen) {
2638934f784SMichal Simek while (alen--)
2648934f784SMichal Simek writel(addr >> (8 * alen), &zynq_i2c->data);
2658934f784SMichal Simek /* Start the tranfer */
26618948632SMichael Burr if (!zynq_i2c_wait(zynq_i2c, ZYNQ_I2C_INTERRUPT_COMP)) {
2678934f784SMichal Simek /* Release the bus */
2688934f784SMichal Simek clrbits_le32(&zynq_i2c->control, ZYNQ_I2C_CONTROL_HOLD);
2698934f784SMichal Simek return -ETIMEDOUT;
2708934f784SMichal Simek }
2718934f784SMichal Simek debug("Device acked address\n");
2729e901071SMichael Burr }
2739e901071SMichael Burr
2748934f784SMichal Simek while (length--) {
2758934f784SMichal Simek writel(*(cur_data++), &zynq_i2c->data);
2768934f784SMichal Simek if (readl(&zynq_i2c->transfer_size) == ZYNQ_I2C_FIFO_DEPTH) {
27718948632SMichael Burr if (!zynq_i2c_wait(zynq_i2c, ZYNQ_I2C_INTERRUPT_COMP)) {
2788934f784SMichal Simek /* Release the bus */
2798934f784SMichal Simek clrbits_le32(&zynq_i2c->control,
2808934f784SMichal Simek ZYNQ_I2C_CONTROL_HOLD);
2818934f784SMichal Simek return -ETIMEDOUT;
2828934f784SMichal Simek }
2838934f784SMichal Simek }
2848934f784SMichal Simek }
2858934f784SMichal Simek
2868934f784SMichal Simek /* All done... release the bus */
2878934f784SMichal Simek clrbits_le32(&zynq_i2c->control, ZYNQ_I2C_CONTROL_HOLD);
2888934f784SMichal Simek /* Wait for the address and data to be sent */
28918948632SMichael Burr if (!zynq_i2c_wait(zynq_i2c, ZYNQ_I2C_INTERRUPT_COMP))
2908934f784SMichal Simek return -ETIMEDOUT;
2918934f784SMichal Simek return 0;
2928934f784SMichal Simek }
2938934f784SMichal Simek
zynq_i2c_set_bus_speed(struct i2c_adapter * adap,unsigned int speed)2940bdffe71SHeiko Schocher static unsigned int zynq_i2c_set_bus_speed(struct i2c_adapter *adap,
2950bdffe71SHeiko Schocher unsigned int speed)
2968934f784SMichal Simek {
2970bdffe71SHeiko Schocher if (speed != 1000000)
2980bdffe71SHeiko Schocher return -EINVAL;
2990bdffe71SHeiko Schocher
3008934f784SMichal Simek return 0;
3018934f784SMichal Simek }
3028934f784SMichal Simek
303009902a8SMichal Simek #ifdef CONFIG_ZYNQ_I2C0
3040bdffe71SHeiko Schocher U_BOOT_I2C_ADAP_COMPLETE(zynq_0, zynq_i2c_init, zynq_i2c_probe, zynq_i2c_read,
3050bdffe71SHeiko Schocher zynq_i2c_write, zynq_i2c_set_bus_speed,
3060bdffe71SHeiko Schocher CONFIG_SYS_I2C_ZYNQ_SPEED, CONFIG_SYS_I2C_ZYNQ_SLAVE,
3070bdffe71SHeiko Schocher 0)
308009902a8SMichal Simek #endif
309009902a8SMichal Simek #ifdef CONFIG_ZYNQ_I2C1
31018948632SMichael Burr U_BOOT_I2C_ADAP_COMPLETE(zynq_1, zynq_i2c_init, zynq_i2c_probe, zynq_i2c_read,
31118948632SMichael Burr zynq_i2c_write, zynq_i2c_set_bus_speed,
31218948632SMichael Burr CONFIG_SYS_I2C_ZYNQ_SPEED, CONFIG_SYS_I2C_ZYNQ_SLAVE,
31318948632SMichael Burr 1)
314009902a8SMichal Simek #endif
315