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 678934f784SMichal Simek #if defined(CONFIG_ZYNQ_I2C0) 688934f784SMichal Simek # define ZYNQ_I2C_BASE ZYNQ_I2C_BASEADDR0 698934f784SMichal Simek #else 708934f784SMichal Simek # define ZYNQ_I2C_BASE ZYNQ_I2C_BASEADDR1 718934f784SMichal Simek #endif 728934f784SMichal Simek 738934f784SMichal Simek static struct zynq_i2c_registers *zynq_i2c = 748934f784SMichal Simek (struct zynq_i2c_registers *)ZYNQ_I2C_BASE; 758934f784SMichal Simek 768934f784SMichal Simek /* I2C init called by cmd_i2c when doing 'i2c reset'. */ 77*0bdffe71SHeiko Schocher static void zynq_i2c_init(struct i2c_adapter *adap, int requested_speed, 78*0bdffe71SHeiko Schocher int slaveadd) 798934f784SMichal Simek { 808934f784SMichal Simek /* 111MHz / ( (3 * 17) * 22 ) = ~100KHz */ 818934f784SMichal Simek writel((16 << ZYNQ_I2C_CONTROL_DIV_B_SHIFT) | 828934f784SMichal Simek (2 << ZYNQ_I2C_CONTROL_DIV_A_SHIFT), &zynq_i2c->control); 838934f784SMichal Simek 848934f784SMichal Simek /* Enable master mode, ack, and 7-bit addressing */ 858934f784SMichal Simek setbits_le32(&zynq_i2c->control, ZYNQ_I2C_CONTROL_MS | 868934f784SMichal Simek ZYNQ_I2C_CONTROL_ACKEN | ZYNQ_I2C_CONTROL_NEA); 878934f784SMichal Simek } 888934f784SMichal Simek 898934f784SMichal Simek #ifdef DEBUG 908934f784SMichal Simek static void zynq_i2c_debug_status(void) 918934f784SMichal Simek { 928934f784SMichal Simek int int_status; 938934f784SMichal Simek int status; 948934f784SMichal Simek int_status = readl(&zynq_i2c->interrupt_status); 958934f784SMichal Simek 968934f784SMichal Simek status = readl(&zynq_i2c->status); 978934f784SMichal Simek if (int_status || status) { 988934f784SMichal Simek debug("Status: "); 998934f784SMichal Simek if (int_status & ZYNQ_I2C_INTERRUPT_COMP) 1008934f784SMichal Simek debug("COMP "); 1018934f784SMichal Simek if (int_status & ZYNQ_I2C_INTERRUPT_DATA) 1028934f784SMichal Simek debug("DATA "); 1038934f784SMichal Simek if (int_status & ZYNQ_I2C_INTERRUPT_NACK) 1048934f784SMichal Simek debug("NACK "); 1058934f784SMichal Simek if (int_status & ZYNQ_I2C_INTERRUPT_TO) 1068934f784SMichal Simek debug("TO "); 1078934f784SMichal Simek if (int_status & ZYNQ_I2C_INTERRUPT_SLVRDY) 1088934f784SMichal Simek debug("SLVRDY "); 1098934f784SMichal Simek if (int_status & ZYNQ_I2C_INTERRUPT_RXOVF) 1108934f784SMichal Simek debug("RXOVF "); 1118934f784SMichal Simek if (int_status & ZYNQ_I2C_INTERRUPT_TXOVF) 1128934f784SMichal Simek debug("TXOVF "); 1138934f784SMichal Simek if (int_status & ZYNQ_I2C_INTERRUPT_RXUNF) 1148934f784SMichal Simek debug("RXUNF "); 1158934f784SMichal Simek if (int_status & ZYNQ_I2C_INTERRUPT_ARBLOST) 1168934f784SMichal Simek debug("ARBLOST "); 1178934f784SMichal Simek if (status & ZYNQ_I2C_STATUS_RXDV) 1188934f784SMichal Simek debug("RXDV "); 1198934f784SMichal Simek if (status & ZYNQ_I2C_STATUS_TXDV) 1208934f784SMichal Simek debug("TXDV "); 1218934f784SMichal Simek if (status & ZYNQ_I2C_STATUS_RXOVF) 1228934f784SMichal Simek debug("RXOVF "); 1238934f784SMichal Simek if (status & ZYNQ_I2C_STATUS_BA) 1248934f784SMichal Simek debug("BA "); 1258934f784SMichal Simek debug("TS%d ", readl(&zynq_i2c->transfer_size)); 1268934f784SMichal Simek debug("\n"); 1278934f784SMichal Simek } 1288934f784SMichal Simek } 1298934f784SMichal Simek #endif 1308934f784SMichal Simek 1318934f784SMichal Simek /* Wait for an interrupt */ 1328934f784SMichal Simek static u32 zynq_i2c_wait(u32 mask) 1338934f784SMichal Simek { 1348934f784SMichal Simek int timeout, int_status; 1358934f784SMichal Simek 1368934f784SMichal Simek for (timeout = 0; timeout < 100; timeout++) { 1378934f784SMichal Simek udelay(100); 1388934f784SMichal Simek int_status = readl(&zynq_i2c->interrupt_status); 1398934f784SMichal Simek if (int_status & mask) 1408934f784SMichal Simek break; 1418934f784SMichal Simek } 1428934f784SMichal Simek #ifdef DEBUG 1438934f784SMichal Simek zynq_i2c_debug_status(); 1448934f784SMichal Simek #endif 1458934f784SMichal Simek /* Clear interrupt status flags */ 1468934f784SMichal Simek writel(int_status & mask, &zynq_i2c->interrupt_status); 1478934f784SMichal Simek 1488934f784SMichal Simek return int_status & mask; 1498934f784SMichal Simek } 1508934f784SMichal Simek 1518934f784SMichal Simek /* 1528934f784SMichal Simek * I2C probe called by cmd_i2c when doing 'i2c probe'. 1538934f784SMichal Simek * Begin read, nak data byte, end. 1548934f784SMichal Simek */ 155*0bdffe71SHeiko Schocher static int zynq_i2c_probe(struct i2c_adapter *adap, u8 dev) 1568934f784SMichal Simek { 1578934f784SMichal Simek /* Attempt to read a byte */ 1588934f784SMichal Simek setbits_le32(&zynq_i2c->control, ZYNQ_I2C_CONTROL_CLR_FIFO | 1598934f784SMichal Simek ZYNQ_I2C_CONTROL_RW); 1608934f784SMichal Simek clrbits_le32(&zynq_i2c->control, ZYNQ_I2C_CONTROL_HOLD); 1618934f784SMichal Simek writel(0xFF, &zynq_i2c->interrupt_status); 1628934f784SMichal Simek writel(dev, &zynq_i2c->address); 1638934f784SMichal Simek writel(1, &zynq_i2c->transfer_size); 1648934f784SMichal Simek 1658934f784SMichal Simek return (zynq_i2c_wait(ZYNQ_I2C_INTERRUPT_COMP | 1668934f784SMichal Simek ZYNQ_I2C_INTERRUPT_NACK) & 1678934f784SMichal Simek ZYNQ_I2C_INTERRUPT_COMP) ? 0 : -ETIMEDOUT; 1688934f784SMichal Simek } 1698934f784SMichal Simek 1708934f784SMichal Simek /* 1718934f784SMichal Simek * I2C read called by cmd_i2c when doing 'i2c read' and by cmd_eeprom.c 1728934f784SMichal Simek * Begin write, send address byte(s), begin read, receive data bytes, end. 1738934f784SMichal Simek */ 174*0bdffe71SHeiko Schocher static int zynq_i2c_read(struct i2c_adapter *adap, u8 dev, uint addr, 175*0bdffe71SHeiko Schocher int alen, u8 *data, int length) 1768934f784SMichal Simek { 1778934f784SMichal Simek u32 status; 1788934f784SMichal Simek u32 i = 0; 1798934f784SMichal Simek u8 *cur_data = data; 1808934f784SMichal Simek 1818934f784SMichal Simek /* Check the hardware can handle the requested bytes */ 1828934f784SMichal Simek if ((length < 0) || (length > ZYNQ_I2C_TRANSFERT_SIZE_MAX)) 1838934f784SMichal Simek return -EINVAL; 1848934f784SMichal Simek 1858934f784SMichal Simek /* Write the register address */ 1868934f784SMichal Simek setbits_le32(&zynq_i2c->control, ZYNQ_I2C_CONTROL_CLR_FIFO | 1878934f784SMichal Simek ZYNQ_I2C_CONTROL_HOLD); 1888934f784SMichal Simek /* 1898934f784SMichal Simek * Temporarily disable restart (by clearing hold) 1908934f784SMichal Simek * It doesn't seem to work. 1918934f784SMichal Simek */ 1928934f784SMichal Simek clrbits_le32(&zynq_i2c->control, ZYNQ_I2C_CONTROL_RW | 1938934f784SMichal Simek ZYNQ_I2C_CONTROL_HOLD); 1948934f784SMichal Simek writel(0xFF, &zynq_i2c->interrupt_status); 1958934f784SMichal Simek while (alen--) 1968934f784SMichal Simek writel(addr >> (8*alen), &zynq_i2c->data); 1978934f784SMichal Simek writel(dev, &zynq_i2c->address); 1988934f784SMichal Simek 1998934f784SMichal Simek /* Wait for the address to be sent */ 2008934f784SMichal Simek if (!zynq_i2c_wait(ZYNQ_I2C_INTERRUPT_COMP)) { 2018934f784SMichal Simek /* Release the bus */ 2028934f784SMichal Simek clrbits_le32(&zynq_i2c->control, ZYNQ_I2C_CONTROL_HOLD); 2038934f784SMichal Simek return -ETIMEDOUT; 2048934f784SMichal Simek } 2058934f784SMichal Simek debug("Device acked address\n"); 2068934f784SMichal Simek 2078934f784SMichal Simek setbits_le32(&zynq_i2c->control, ZYNQ_I2C_CONTROL_CLR_FIFO | 2088934f784SMichal Simek ZYNQ_I2C_CONTROL_RW); 2098934f784SMichal Simek /* Start reading data */ 2108934f784SMichal Simek writel(dev, &zynq_i2c->address); 2118934f784SMichal Simek writel(length, &zynq_i2c->transfer_size); 2128934f784SMichal Simek 2138934f784SMichal Simek /* Wait for data */ 2148934f784SMichal Simek do { 2158934f784SMichal Simek status = zynq_i2c_wait(ZYNQ_I2C_INTERRUPT_COMP | 2168934f784SMichal Simek ZYNQ_I2C_INTERRUPT_DATA); 2178934f784SMichal Simek if (!status) { 2188934f784SMichal Simek /* Release the bus */ 2198934f784SMichal Simek clrbits_le32(&zynq_i2c->control, ZYNQ_I2C_CONTROL_HOLD); 2208934f784SMichal Simek return -ETIMEDOUT; 2218934f784SMichal Simek } 2228934f784SMichal Simek debug("Read %d bytes\n", 2238934f784SMichal Simek length - readl(&zynq_i2c->transfer_size)); 2248934f784SMichal Simek for (; i < length - readl(&zynq_i2c->transfer_size); i++) 2258934f784SMichal Simek *(cur_data++) = readl(&zynq_i2c->data); 2268934f784SMichal Simek } while (readl(&zynq_i2c->transfer_size) != 0); 2278934f784SMichal Simek /* All done... release the bus */ 2288934f784SMichal Simek clrbits_le32(&zynq_i2c->control, ZYNQ_I2C_CONTROL_HOLD); 2298934f784SMichal Simek 2308934f784SMichal Simek #ifdef DEBUG 2318934f784SMichal Simek zynq_i2c_debug_status(); 2328934f784SMichal Simek #endif 2338934f784SMichal Simek return 0; 2348934f784SMichal Simek } 2358934f784SMichal Simek 2368934f784SMichal Simek /* 2378934f784SMichal Simek * I2C write called by cmd_i2c when doing 'i2c write' and by cmd_eeprom.c 2388934f784SMichal Simek * Begin write, send address byte(s), send data bytes, end. 2398934f784SMichal Simek */ 240*0bdffe71SHeiko Schocher static int zynq_i2c_write(struct i2c_adapter *adap, u8 dev, uint addr, 241*0bdffe71SHeiko Schocher int alen, u8 *data, int length) 2428934f784SMichal Simek { 2438934f784SMichal Simek u8 *cur_data = data; 2448934f784SMichal Simek 2458934f784SMichal Simek /* Write the register address */ 2468934f784SMichal Simek setbits_le32(&zynq_i2c->control, ZYNQ_I2C_CONTROL_CLR_FIFO | 2478934f784SMichal Simek ZYNQ_I2C_CONTROL_HOLD); 2488934f784SMichal Simek clrbits_le32(&zynq_i2c->control, ZYNQ_I2C_CONTROL_RW); 2498934f784SMichal Simek writel(0xFF, &zynq_i2c->interrupt_status); 2508934f784SMichal Simek while (alen--) 2518934f784SMichal Simek writel(addr >> (8*alen), &zynq_i2c->data); 2528934f784SMichal Simek /* Start the tranfer */ 2538934f784SMichal Simek writel(dev, &zynq_i2c->address); 2548934f784SMichal Simek if (!zynq_i2c_wait(ZYNQ_I2C_INTERRUPT_COMP)) { 2558934f784SMichal Simek /* Release the bus */ 2568934f784SMichal Simek clrbits_le32(&zynq_i2c->control, ZYNQ_I2C_CONTROL_HOLD); 2578934f784SMichal Simek return -ETIMEDOUT; 2588934f784SMichal Simek } 2598934f784SMichal Simek 2608934f784SMichal Simek debug("Device acked address\n"); 2618934f784SMichal Simek while (length--) { 2628934f784SMichal Simek writel(*(cur_data++), &zynq_i2c->data); 2638934f784SMichal Simek if (readl(&zynq_i2c->transfer_size) == ZYNQ_I2C_FIFO_DEPTH) { 2648934f784SMichal Simek if (!zynq_i2c_wait(ZYNQ_I2C_INTERRUPT_COMP)) { 2658934f784SMichal Simek /* Release the bus */ 2668934f784SMichal Simek clrbits_le32(&zynq_i2c->control, 2678934f784SMichal Simek ZYNQ_I2C_CONTROL_HOLD); 2688934f784SMichal Simek return -ETIMEDOUT; 2698934f784SMichal Simek } 2708934f784SMichal Simek } 2718934f784SMichal Simek } 2728934f784SMichal Simek 2738934f784SMichal Simek /* All done... release the bus */ 2748934f784SMichal Simek clrbits_le32(&zynq_i2c->control, ZYNQ_I2C_CONTROL_HOLD); 2758934f784SMichal Simek /* Wait for the address and data to be sent */ 2768934f784SMichal Simek if (!zynq_i2c_wait(ZYNQ_I2C_INTERRUPT_COMP)) 2778934f784SMichal Simek return -ETIMEDOUT; 2788934f784SMichal Simek return 0; 2798934f784SMichal Simek } 2808934f784SMichal Simek 281*0bdffe71SHeiko Schocher static unsigned int zynq_i2c_set_bus_speed(struct i2c_adapter *adap, 282*0bdffe71SHeiko Schocher unsigned int speed) 2838934f784SMichal Simek { 284*0bdffe71SHeiko Schocher if (speed != 1000000) 285*0bdffe71SHeiko Schocher return -EINVAL; 286*0bdffe71SHeiko Schocher 2878934f784SMichal Simek return 0; 2888934f784SMichal Simek } 2898934f784SMichal Simek 290*0bdffe71SHeiko Schocher U_BOOT_I2C_ADAP_COMPLETE(zynq_0, zynq_i2c_init, zynq_i2c_probe, zynq_i2c_read, 291*0bdffe71SHeiko Schocher zynq_i2c_write, zynq_i2c_set_bus_speed, 292*0bdffe71SHeiko Schocher CONFIG_SYS_I2C_ZYNQ_SPEED, CONFIG_SYS_I2C_ZYNQ_SLAVE, 293*0bdffe71SHeiko Schocher 0) 294