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+ 118934f784SMichal Simek */ 128934f784SMichal Simek 138934f784SMichal Simek #include <common.h> 148934f784SMichal Simek #include <asm/io.h> 158934f784SMichal Simek #include <i2c.h> 168934f784SMichal Simek #include <asm/errno.h> 178934f784SMichal Simek #include <asm/arch/hardware.h> 188934f784SMichal Simek 198934f784SMichal Simek /* i2c register set */ 208934f784SMichal Simek struct zynq_i2c_registers { 218934f784SMichal Simek u32 control; 228934f784SMichal Simek u32 status; 238934f784SMichal Simek u32 address; 248934f784SMichal Simek u32 data; 258934f784SMichal Simek u32 interrupt_status; 268934f784SMichal Simek u32 transfer_size; 278934f784SMichal Simek u32 slave_mon_pause; 288934f784SMichal Simek u32 time_out; 298934f784SMichal Simek u32 interrupt_mask; 308934f784SMichal Simek u32 interrupt_enable; 318934f784SMichal Simek u32 interrupt_disable; 328934f784SMichal Simek }; 338934f784SMichal Simek 348934f784SMichal Simek /* Control register fields */ 358934f784SMichal Simek #define ZYNQ_I2C_CONTROL_RW 0x00000001 368934f784SMichal Simek #define ZYNQ_I2C_CONTROL_MS 0x00000002 378934f784SMichal Simek #define ZYNQ_I2C_CONTROL_NEA 0x00000004 388934f784SMichal Simek #define ZYNQ_I2C_CONTROL_ACKEN 0x00000008 398934f784SMichal Simek #define ZYNQ_I2C_CONTROL_HOLD 0x00000010 408934f784SMichal Simek #define ZYNQ_I2C_CONTROL_SLVMON 0x00000020 418934f784SMichal Simek #define ZYNQ_I2C_CONTROL_CLR_FIFO 0x00000040 428934f784SMichal Simek #define ZYNQ_I2C_CONTROL_DIV_B_SHIFT 8 438934f784SMichal Simek #define ZYNQ_I2C_CONTROL_DIV_B_MASK 0x00003F00 448934f784SMichal Simek #define ZYNQ_I2C_CONTROL_DIV_A_SHIFT 14 458934f784SMichal Simek #define ZYNQ_I2C_CONTROL_DIV_A_MASK 0x0000C000 468934f784SMichal Simek 478934f784SMichal Simek /* Status register values */ 488934f784SMichal Simek #define ZYNQ_I2C_STATUS_RXDV 0x00000020 498934f784SMichal Simek #define ZYNQ_I2C_STATUS_TXDV 0x00000040 508934f784SMichal Simek #define ZYNQ_I2C_STATUS_RXOVF 0x00000080 518934f784SMichal Simek #define ZYNQ_I2C_STATUS_BA 0x00000100 528934f784SMichal Simek 538934f784SMichal Simek /* Interrupt register fields */ 548934f784SMichal Simek #define ZYNQ_I2C_INTERRUPT_COMP 0x00000001 558934f784SMichal Simek #define ZYNQ_I2C_INTERRUPT_DATA 0x00000002 568934f784SMichal Simek #define ZYNQ_I2C_INTERRUPT_NACK 0x00000004 578934f784SMichal Simek #define ZYNQ_I2C_INTERRUPT_TO 0x00000008 588934f784SMichal Simek #define ZYNQ_I2C_INTERRUPT_SLVRDY 0x00000010 598934f784SMichal Simek #define ZYNQ_I2C_INTERRUPT_RXOVF 0x00000020 608934f784SMichal Simek #define ZYNQ_I2C_INTERRUPT_TXOVF 0x00000040 618934f784SMichal Simek #define ZYNQ_I2C_INTERRUPT_RXUNF 0x00000080 628934f784SMichal Simek #define ZYNQ_I2C_INTERRUPT_ARBLOST 0x00000200 638934f784SMichal Simek 648934f784SMichal Simek #define ZYNQ_I2C_FIFO_DEPTH 16 658934f784SMichal Simek #define ZYNQ_I2C_TRANSFERT_SIZE_MAX 255 /* Controller transfer limit */ 668934f784SMichal Simek 6718948632SMichael Burr static struct zynq_i2c_registers *i2c_select(struct i2c_adapter *adap) 6818948632SMichael Burr { 6918948632SMichael Burr return adap->hwadapnr ? 7018948632SMichael Burr /* Zynq PS I2C1 */ 7118948632SMichael Burr (struct zynq_i2c_registers *)ZYNQ_I2C_BASEADDR1 : 7218948632SMichael Burr /* Zynq PS I2C0 */ 7318948632SMichael Burr (struct zynq_i2c_registers *)ZYNQ_I2C_BASEADDR0; 7418948632SMichael Burr } 758934f784SMichal Simek 768934f784SMichal Simek /* I2C init called by cmd_i2c when doing 'i2c reset'. */ 770bdffe71SHeiko Schocher static void zynq_i2c_init(struct i2c_adapter *adap, int requested_speed, 780bdffe71SHeiko Schocher int slaveadd) 798934f784SMichal Simek { 8018948632SMichael Burr struct zynq_i2c_registers *zynq_i2c = i2c_select(adap); 8118948632SMichael Burr 828934f784SMichal Simek /* 111MHz / ( (3 * 17) * 22 ) = ~100KHz */ 838934f784SMichal Simek writel((16 << ZYNQ_I2C_CONTROL_DIV_B_SHIFT) | 848934f784SMichal Simek (2 << ZYNQ_I2C_CONTROL_DIV_A_SHIFT), &zynq_i2c->control); 858934f784SMichal Simek 868934f784SMichal Simek /* Enable master mode, ack, and 7-bit addressing */ 878934f784SMichal Simek setbits_le32(&zynq_i2c->control, ZYNQ_I2C_CONTROL_MS | 888934f784SMichal Simek ZYNQ_I2C_CONTROL_ACKEN | ZYNQ_I2C_CONTROL_NEA); 898934f784SMichal Simek } 908934f784SMichal Simek 918934f784SMichal Simek #ifdef DEBUG 9218948632SMichael Burr static void zynq_i2c_debug_status(struct zynq_i2c_registers *zynq_i2c) 938934f784SMichal Simek { 948934f784SMichal Simek int int_status; 958934f784SMichal Simek int status; 968934f784SMichal Simek int_status = readl(&zynq_i2c->interrupt_status); 978934f784SMichal Simek 988934f784SMichal Simek status = readl(&zynq_i2c->status); 998934f784SMichal Simek if (int_status || status) { 1008934f784SMichal Simek debug("Status: "); 1018934f784SMichal Simek if (int_status & ZYNQ_I2C_INTERRUPT_COMP) 1028934f784SMichal Simek debug("COMP "); 1038934f784SMichal Simek if (int_status & ZYNQ_I2C_INTERRUPT_DATA) 1048934f784SMichal Simek debug("DATA "); 1058934f784SMichal Simek if (int_status & ZYNQ_I2C_INTERRUPT_NACK) 1068934f784SMichal Simek debug("NACK "); 1078934f784SMichal Simek if (int_status & ZYNQ_I2C_INTERRUPT_TO) 1088934f784SMichal Simek debug("TO "); 1098934f784SMichal Simek if (int_status & ZYNQ_I2C_INTERRUPT_SLVRDY) 1108934f784SMichal Simek debug("SLVRDY "); 1118934f784SMichal Simek if (int_status & ZYNQ_I2C_INTERRUPT_RXOVF) 1128934f784SMichal Simek debug("RXOVF "); 1138934f784SMichal Simek if (int_status & ZYNQ_I2C_INTERRUPT_TXOVF) 1148934f784SMichal Simek debug("TXOVF "); 1158934f784SMichal Simek if (int_status & ZYNQ_I2C_INTERRUPT_RXUNF) 1168934f784SMichal Simek debug("RXUNF "); 1178934f784SMichal Simek if (int_status & ZYNQ_I2C_INTERRUPT_ARBLOST) 1188934f784SMichal Simek debug("ARBLOST "); 1198934f784SMichal Simek if (status & ZYNQ_I2C_STATUS_RXDV) 1208934f784SMichal Simek debug("RXDV "); 1218934f784SMichal Simek if (status & ZYNQ_I2C_STATUS_TXDV) 1228934f784SMichal Simek debug("TXDV "); 1238934f784SMichal Simek if (status & ZYNQ_I2C_STATUS_RXOVF) 1248934f784SMichal Simek debug("RXOVF "); 1258934f784SMichal Simek if (status & ZYNQ_I2C_STATUS_BA) 1268934f784SMichal Simek debug("BA "); 1278934f784SMichal Simek debug("TS%d ", readl(&zynq_i2c->transfer_size)); 1288934f784SMichal Simek debug("\n"); 1298934f784SMichal Simek } 1308934f784SMichal Simek } 1318934f784SMichal Simek #endif 1328934f784SMichal Simek 1338934f784SMichal Simek /* Wait for an interrupt */ 13418948632SMichael Burr static u32 zynq_i2c_wait(struct zynq_i2c_registers *zynq_i2c, u32 mask) 1358934f784SMichal Simek { 1368934f784SMichal Simek int timeout, int_status; 1378934f784SMichal Simek 1388934f784SMichal Simek for (timeout = 0; timeout < 100; timeout++) { 1398934f784SMichal Simek udelay(100); 1408934f784SMichal Simek int_status = readl(&zynq_i2c->interrupt_status); 1418934f784SMichal Simek if (int_status & mask) 1428934f784SMichal Simek break; 1438934f784SMichal Simek } 1448934f784SMichal Simek #ifdef DEBUG 145*5146fc2bSJesper B. Christensen zynq_i2c_debug_status(zynq_i2c); 1468934f784SMichal Simek #endif 1478934f784SMichal Simek /* Clear interrupt status flags */ 1488934f784SMichal Simek writel(int_status & mask, &zynq_i2c->interrupt_status); 1498934f784SMichal Simek 1508934f784SMichal Simek return int_status & mask; 1518934f784SMichal Simek } 1528934f784SMichal Simek 1538934f784SMichal Simek /* 1548934f784SMichal Simek * I2C probe called by cmd_i2c when doing 'i2c probe'. 1558934f784SMichal Simek * Begin read, nak data byte, end. 1568934f784SMichal Simek */ 1570bdffe71SHeiko Schocher static int zynq_i2c_probe(struct i2c_adapter *adap, u8 dev) 1588934f784SMichal Simek { 15918948632SMichael Burr struct zynq_i2c_registers *zynq_i2c = i2c_select(adap); 16018948632SMichael Burr 1618934f784SMichal Simek /* Attempt to read a byte */ 1628934f784SMichal Simek setbits_le32(&zynq_i2c->control, ZYNQ_I2C_CONTROL_CLR_FIFO | 1638934f784SMichal Simek ZYNQ_I2C_CONTROL_RW); 1648934f784SMichal Simek clrbits_le32(&zynq_i2c->control, ZYNQ_I2C_CONTROL_HOLD); 1658934f784SMichal Simek writel(0xFF, &zynq_i2c->interrupt_status); 1668934f784SMichal Simek writel(dev, &zynq_i2c->address); 1678934f784SMichal Simek writel(1, &zynq_i2c->transfer_size); 1688934f784SMichal Simek 16918948632SMichael Burr return (zynq_i2c_wait(zynq_i2c, ZYNQ_I2C_INTERRUPT_COMP | 1708934f784SMichal Simek ZYNQ_I2C_INTERRUPT_NACK) & 1718934f784SMichal Simek ZYNQ_I2C_INTERRUPT_COMP) ? 0 : -ETIMEDOUT; 1728934f784SMichal Simek } 1738934f784SMichal Simek 1748934f784SMichal Simek /* 1758934f784SMichal Simek * I2C read called by cmd_i2c when doing 'i2c read' and by cmd_eeprom.c 1768934f784SMichal Simek * Begin write, send address byte(s), begin read, receive data bytes, end. 1778934f784SMichal Simek */ 1780bdffe71SHeiko Schocher static int zynq_i2c_read(struct i2c_adapter *adap, u8 dev, uint addr, 1790bdffe71SHeiko Schocher int alen, u8 *data, int length) 1808934f784SMichal Simek { 1818934f784SMichal Simek u32 status; 1828934f784SMichal Simek u32 i = 0; 1838934f784SMichal Simek u8 *cur_data = data; 18418948632SMichael Burr struct zynq_i2c_registers *zynq_i2c = i2c_select(adap); 1858934f784SMichal Simek 1868934f784SMichal Simek /* Check the hardware can handle the requested bytes */ 1878934f784SMichal Simek if ((length < 0) || (length > ZYNQ_I2C_TRANSFERT_SIZE_MAX)) 1888934f784SMichal Simek return -EINVAL; 1898934f784SMichal Simek 1908934f784SMichal Simek /* Write the register address */ 1918934f784SMichal Simek setbits_le32(&zynq_i2c->control, ZYNQ_I2C_CONTROL_CLR_FIFO | 1928934f784SMichal Simek ZYNQ_I2C_CONTROL_HOLD); 1938934f784SMichal Simek /* 1948934f784SMichal Simek * Temporarily disable restart (by clearing hold) 1958934f784SMichal Simek * It doesn't seem to work. 1968934f784SMichal Simek */ 1979e901071SMichael Burr clrbits_le32(&zynq_i2c->control, ZYNQ_I2C_CONTROL_HOLD); 1988934f784SMichal Simek writel(0xFF, &zynq_i2c->interrupt_status); 1999e901071SMichael Burr if (alen) { 2009e901071SMichael Burr clrbits_le32(&zynq_i2c->control, ZYNQ_I2C_CONTROL_RW); 2019e901071SMichael Burr writel(dev, &zynq_i2c->address); 2028934f784SMichal Simek while (alen--) 2038934f784SMichal Simek writel(addr >> (8 * alen), &zynq_i2c->data); 2048934f784SMichal Simek 2058934f784SMichal Simek /* Wait for the address to be sent */ 20618948632SMichael Burr if (!zynq_i2c_wait(zynq_i2c, ZYNQ_I2C_INTERRUPT_COMP)) { 2078934f784SMichal Simek /* Release the bus */ 2088934f784SMichal Simek clrbits_le32(&zynq_i2c->control, ZYNQ_I2C_CONTROL_HOLD); 2098934f784SMichal Simek return -ETIMEDOUT; 2108934f784SMichal Simek } 2118934f784SMichal Simek debug("Device acked address\n"); 2129e901071SMichael Burr } 2138934f784SMichal Simek 2148934f784SMichal Simek setbits_le32(&zynq_i2c->control, ZYNQ_I2C_CONTROL_CLR_FIFO | 2158934f784SMichal Simek ZYNQ_I2C_CONTROL_RW); 2168934f784SMichal Simek /* Start reading data */ 2178934f784SMichal Simek writel(dev, &zynq_i2c->address); 2188934f784SMichal Simek writel(length, &zynq_i2c->transfer_size); 2198934f784SMichal Simek 2208934f784SMichal Simek /* Wait for data */ 2218934f784SMichal Simek do { 22218948632SMichael Burr status = zynq_i2c_wait(zynq_i2c, ZYNQ_I2C_INTERRUPT_COMP | 2238934f784SMichal Simek ZYNQ_I2C_INTERRUPT_DATA); 2248934f784SMichal Simek if (!status) { 2258934f784SMichal Simek /* Release the bus */ 2268934f784SMichal Simek clrbits_le32(&zynq_i2c->control, ZYNQ_I2C_CONTROL_HOLD); 2278934f784SMichal Simek return -ETIMEDOUT; 2288934f784SMichal Simek } 2298934f784SMichal Simek debug("Read %d bytes\n", 2308934f784SMichal Simek length - readl(&zynq_i2c->transfer_size)); 2318934f784SMichal Simek for (; i < length - readl(&zynq_i2c->transfer_size); i++) 2328934f784SMichal Simek *(cur_data++) = readl(&zynq_i2c->data); 2338934f784SMichal Simek } while (readl(&zynq_i2c->transfer_size) != 0); 2348934f784SMichal Simek /* All done... release the bus */ 2358934f784SMichal Simek clrbits_le32(&zynq_i2c->control, ZYNQ_I2C_CONTROL_HOLD); 2368934f784SMichal Simek 2378934f784SMichal Simek #ifdef DEBUG 238*5146fc2bSJesper B. Christensen zynq_i2c_debug_status(zynq_i2c); 2398934f784SMichal Simek #endif 2408934f784SMichal Simek return 0; 2418934f784SMichal Simek } 2428934f784SMichal Simek 2438934f784SMichal Simek /* 2448934f784SMichal Simek * I2C write called by cmd_i2c when doing 'i2c write' and by cmd_eeprom.c 2458934f784SMichal Simek * Begin write, send address byte(s), send data bytes, end. 2468934f784SMichal Simek */ 2470bdffe71SHeiko Schocher static int zynq_i2c_write(struct i2c_adapter *adap, u8 dev, uint addr, 2480bdffe71SHeiko Schocher int alen, u8 *data, int length) 2498934f784SMichal Simek { 2508934f784SMichal Simek u8 *cur_data = data; 25118948632SMichael Burr struct zynq_i2c_registers *zynq_i2c = i2c_select(adap); 2528934f784SMichal Simek 2538934f784SMichal Simek /* Write the register address */ 2548934f784SMichal Simek setbits_le32(&zynq_i2c->control, ZYNQ_I2C_CONTROL_CLR_FIFO | 2558934f784SMichal Simek ZYNQ_I2C_CONTROL_HOLD); 2568934f784SMichal Simek clrbits_le32(&zynq_i2c->control, ZYNQ_I2C_CONTROL_RW); 2578934f784SMichal Simek writel(0xFF, &zynq_i2c->interrupt_status); 2589e901071SMichael Burr writel(dev, &zynq_i2c->address); 2599e901071SMichael Burr if (alen) { 2608934f784SMichal Simek while (alen--) 2618934f784SMichal Simek writel(addr >> (8 * alen), &zynq_i2c->data); 2628934f784SMichal Simek /* Start the tranfer */ 26318948632SMichael Burr if (!zynq_i2c_wait(zynq_i2c, ZYNQ_I2C_INTERRUPT_COMP)) { 2648934f784SMichal Simek /* Release the bus */ 2658934f784SMichal Simek clrbits_le32(&zynq_i2c->control, ZYNQ_I2C_CONTROL_HOLD); 2668934f784SMichal Simek return -ETIMEDOUT; 2678934f784SMichal Simek } 2688934f784SMichal Simek debug("Device acked address\n"); 2699e901071SMichael Burr } 2709e901071SMichael Burr 2718934f784SMichal Simek while (length--) { 2728934f784SMichal Simek writel(*(cur_data++), &zynq_i2c->data); 2738934f784SMichal Simek if (readl(&zynq_i2c->transfer_size) == ZYNQ_I2C_FIFO_DEPTH) { 27418948632SMichael Burr if (!zynq_i2c_wait(zynq_i2c, ZYNQ_I2C_INTERRUPT_COMP)) { 2758934f784SMichal Simek /* Release the bus */ 2768934f784SMichal Simek clrbits_le32(&zynq_i2c->control, 2778934f784SMichal Simek ZYNQ_I2C_CONTROL_HOLD); 2788934f784SMichal Simek return -ETIMEDOUT; 2798934f784SMichal Simek } 2808934f784SMichal Simek } 2818934f784SMichal Simek } 2828934f784SMichal Simek 2838934f784SMichal Simek /* All done... release the bus */ 2848934f784SMichal Simek clrbits_le32(&zynq_i2c->control, ZYNQ_I2C_CONTROL_HOLD); 2858934f784SMichal Simek /* Wait for the address and data to be sent */ 28618948632SMichael Burr if (!zynq_i2c_wait(zynq_i2c, ZYNQ_I2C_INTERRUPT_COMP)) 2878934f784SMichal Simek return -ETIMEDOUT; 2888934f784SMichal Simek return 0; 2898934f784SMichal Simek } 2908934f784SMichal Simek 2910bdffe71SHeiko Schocher static unsigned int zynq_i2c_set_bus_speed(struct i2c_adapter *adap, 2920bdffe71SHeiko Schocher unsigned int speed) 2938934f784SMichal Simek { 2940bdffe71SHeiko Schocher if (speed != 1000000) 2950bdffe71SHeiko Schocher return -EINVAL; 2960bdffe71SHeiko Schocher 2978934f784SMichal Simek return 0; 2988934f784SMichal Simek } 2998934f784SMichal Simek 3000bdffe71SHeiko Schocher U_BOOT_I2C_ADAP_COMPLETE(zynq_0, zynq_i2c_init, zynq_i2c_probe, zynq_i2c_read, 3010bdffe71SHeiko Schocher zynq_i2c_write, zynq_i2c_set_bus_speed, 3020bdffe71SHeiko Schocher CONFIG_SYS_I2C_ZYNQ_SPEED, CONFIG_SYS_I2C_ZYNQ_SLAVE, 3030bdffe71SHeiko Schocher 0) 30418948632SMichael Burr U_BOOT_I2C_ADAP_COMPLETE(zynq_1, zynq_i2c_init, zynq_i2c_probe, zynq_i2c_read, 30518948632SMichael Burr zynq_i2c_write, zynq_i2c_set_bus_speed, 30618948632SMichael Burr CONFIG_SYS_I2C_ZYNQ_SPEED, CONFIG_SYS_I2C_ZYNQ_SLAVE, 30718948632SMichael Burr 1) 308