1fdec2d21SMoritz Fischer /* 2fdec2d21SMoritz Fischer * Copyright (C) 2015 Moritz Fischer <moritz.fischer@ettus.com> 3fdec2d21SMoritz Fischer * IP from Cadence (ID T-CS-PE-0007-100, Version R1p10f2) 4fdec2d21SMoritz Fischer * 5fdec2d21SMoritz Fischer * This file is based on: drivers/i2c/zynq_i2c.c, 6fdec2d21SMoritz Fischer * with added driver-model support and code cleanup. 7fdec2d21SMoritz Fischer * 8fdec2d21SMoritz Fischer * SPDX-License-Identifier: GPL-2.0+ 9fdec2d21SMoritz Fischer */ 10fdec2d21SMoritz Fischer 11fdec2d21SMoritz Fischer #include <common.h> 12fdec2d21SMoritz Fischer #include <linux/types.h> 13fdec2d21SMoritz Fischer #include <linux/io.h> 14fdec2d21SMoritz Fischer #include <asm/errno.h> 15fdec2d21SMoritz Fischer #include <dm/device.h> 16fdec2d21SMoritz Fischer #include <dm/root.h> 17fdec2d21SMoritz Fischer #include <i2c.h> 18fdec2d21SMoritz Fischer #include <fdtdec.h> 19fdec2d21SMoritz Fischer #include <mapmem.h> 20fdec2d21SMoritz Fischer 21fdec2d21SMoritz Fischer DECLARE_GLOBAL_DATA_PTR; 22fdec2d21SMoritz Fischer 23fdec2d21SMoritz Fischer /* i2c register set */ 24fdec2d21SMoritz Fischer struct cdns_i2c_regs { 25fdec2d21SMoritz Fischer u32 control; 26fdec2d21SMoritz Fischer u32 status; 27fdec2d21SMoritz Fischer u32 address; 28fdec2d21SMoritz Fischer u32 data; 29fdec2d21SMoritz Fischer u32 interrupt_status; 30fdec2d21SMoritz Fischer u32 transfer_size; 31fdec2d21SMoritz Fischer u32 slave_mon_pause; 32fdec2d21SMoritz Fischer u32 time_out; 33fdec2d21SMoritz Fischer u32 interrupt_mask; 34fdec2d21SMoritz Fischer u32 interrupt_enable; 35fdec2d21SMoritz Fischer u32 interrupt_disable; 36fdec2d21SMoritz Fischer }; 37fdec2d21SMoritz Fischer 38fdec2d21SMoritz Fischer /* Control register fields */ 39fdec2d21SMoritz Fischer #define CDNS_I2C_CONTROL_RW 0x00000001 40fdec2d21SMoritz Fischer #define CDNS_I2C_CONTROL_MS 0x00000002 41fdec2d21SMoritz Fischer #define CDNS_I2C_CONTROL_NEA 0x00000004 42fdec2d21SMoritz Fischer #define CDNS_I2C_CONTROL_ACKEN 0x00000008 43fdec2d21SMoritz Fischer #define CDNS_I2C_CONTROL_HOLD 0x00000010 44fdec2d21SMoritz Fischer #define CDNS_I2C_CONTROL_SLVMON 0x00000020 45fdec2d21SMoritz Fischer #define CDNS_I2C_CONTROL_CLR_FIFO 0x00000040 46fdec2d21SMoritz Fischer #define CDNS_I2C_CONTROL_DIV_B_SHIFT 8 47fdec2d21SMoritz Fischer #define CDNS_I2C_CONTROL_DIV_B_MASK 0x00003F00 48fdec2d21SMoritz Fischer #define CDNS_I2C_CONTROL_DIV_A_SHIFT 14 49fdec2d21SMoritz Fischer #define CDNS_I2C_CONTROL_DIV_A_MASK 0x0000C000 50fdec2d21SMoritz Fischer 51fdec2d21SMoritz Fischer /* Status register values */ 52fdec2d21SMoritz Fischer #define CDNS_I2C_STATUS_RXDV 0x00000020 53fdec2d21SMoritz Fischer #define CDNS_I2C_STATUS_TXDV 0x00000040 54fdec2d21SMoritz Fischer #define CDNS_I2C_STATUS_RXOVF 0x00000080 55fdec2d21SMoritz Fischer #define CDNS_I2C_STATUS_BA 0x00000100 56fdec2d21SMoritz Fischer 57fdec2d21SMoritz Fischer /* Interrupt register fields */ 58fdec2d21SMoritz Fischer #define CDNS_I2C_INTERRUPT_COMP 0x00000001 59fdec2d21SMoritz Fischer #define CDNS_I2C_INTERRUPT_DATA 0x00000002 60fdec2d21SMoritz Fischer #define CDNS_I2C_INTERRUPT_NACK 0x00000004 61fdec2d21SMoritz Fischer #define CDNS_I2C_INTERRUPT_TO 0x00000008 62fdec2d21SMoritz Fischer #define CDNS_I2C_INTERRUPT_SLVRDY 0x00000010 63fdec2d21SMoritz Fischer #define CDNS_I2C_INTERRUPT_RXOVF 0x00000020 64fdec2d21SMoritz Fischer #define CDNS_I2C_INTERRUPT_TXOVF 0x00000040 65fdec2d21SMoritz Fischer #define CDNS_I2C_INTERRUPT_RXUNF 0x00000080 66fdec2d21SMoritz Fischer #define CDNS_I2C_INTERRUPT_ARBLOST 0x00000200 67fdec2d21SMoritz Fischer 68fdec2d21SMoritz Fischer #define CDNS_I2C_FIFO_DEPTH 16 69fdec2d21SMoritz Fischer #define CDNS_I2C_TRANSFER_SIZE_MAX 255 /* Controller transfer limit */ 70fdec2d21SMoritz Fischer 71fdec2d21SMoritz Fischer #ifdef DEBUG 72fdec2d21SMoritz Fischer static void cdns_i2c_debug_status(struct cdns_i2c_regs *cdns_i2c) 73fdec2d21SMoritz Fischer { 74fdec2d21SMoritz Fischer int int_status; 75fdec2d21SMoritz Fischer int status; 76fdec2d21SMoritz Fischer int_status = readl(&cdns_i2c->interrupt_status); 77fdec2d21SMoritz Fischer 78fdec2d21SMoritz Fischer status = readl(&cdns_i2c->status); 79fdec2d21SMoritz Fischer if (int_status || status) { 80fdec2d21SMoritz Fischer debug("Status: "); 81fdec2d21SMoritz Fischer if (int_status & CDNS_I2C_INTERRUPT_COMP) 82fdec2d21SMoritz Fischer debug("COMP "); 83fdec2d21SMoritz Fischer if (int_status & CDNS_I2C_INTERRUPT_DATA) 84fdec2d21SMoritz Fischer debug("DATA "); 85fdec2d21SMoritz Fischer if (int_status & CDNS_I2C_INTERRUPT_NACK) 86fdec2d21SMoritz Fischer debug("NACK "); 87fdec2d21SMoritz Fischer if (int_status & CDNS_I2C_INTERRUPT_TO) 88fdec2d21SMoritz Fischer debug("TO "); 89fdec2d21SMoritz Fischer if (int_status & CDNS_I2C_INTERRUPT_SLVRDY) 90fdec2d21SMoritz Fischer debug("SLVRDY "); 91fdec2d21SMoritz Fischer if (int_status & CDNS_I2C_INTERRUPT_RXOVF) 92fdec2d21SMoritz Fischer debug("RXOVF "); 93fdec2d21SMoritz Fischer if (int_status & CDNS_I2C_INTERRUPT_TXOVF) 94fdec2d21SMoritz Fischer debug("TXOVF "); 95fdec2d21SMoritz Fischer if (int_status & CDNS_I2C_INTERRUPT_RXUNF) 96fdec2d21SMoritz Fischer debug("RXUNF "); 97fdec2d21SMoritz Fischer if (int_status & CDNS_I2C_INTERRUPT_ARBLOST) 98fdec2d21SMoritz Fischer debug("ARBLOST "); 99fdec2d21SMoritz Fischer if (status & CDNS_I2C_STATUS_RXDV) 100fdec2d21SMoritz Fischer debug("RXDV "); 101fdec2d21SMoritz Fischer if (status & CDNS_I2C_STATUS_TXDV) 102fdec2d21SMoritz Fischer debug("TXDV "); 103fdec2d21SMoritz Fischer if (status & CDNS_I2C_STATUS_RXOVF) 104fdec2d21SMoritz Fischer debug("RXOVF "); 105fdec2d21SMoritz Fischer if (status & CDNS_I2C_STATUS_BA) 106fdec2d21SMoritz Fischer debug("BA "); 107fdec2d21SMoritz Fischer debug("TS%d ", readl(&cdns_i2c->transfer_size)); 108fdec2d21SMoritz Fischer debug("\n"); 109fdec2d21SMoritz Fischer } 110fdec2d21SMoritz Fischer } 111fdec2d21SMoritz Fischer #endif 112fdec2d21SMoritz Fischer 113fdec2d21SMoritz Fischer struct i2c_cdns_bus { 114fdec2d21SMoritz Fischer int id; 115*ad72e762SMichal Simek unsigned int input_freq; 116fdec2d21SMoritz Fischer struct cdns_i2c_regs __iomem *regs; /* register base */ 117fdec2d21SMoritz Fischer }; 118fdec2d21SMoritz Fischer 119fdec2d21SMoritz Fischer /* Wait for an interrupt */ 120fdec2d21SMoritz Fischer static u32 cdns_i2c_wait(struct cdns_i2c_regs *cdns_i2c, u32 mask) 121fdec2d21SMoritz Fischer { 122fdec2d21SMoritz Fischer int timeout, int_status; 123fdec2d21SMoritz Fischer 124fdec2d21SMoritz Fischer for (timeout = 0; timeout < 100; timeout++) { 125fdec2d21SMoritz Fischer udelay(100); 126fdec2d21SMoritz Fischer int_status = readl(&cdns_i2c->interrupt_status); 127fdec2d21SMoritz Fischer if (int_status & mask) 128fdec2d21SMoritz Fischer break; 129fdec2d21SMoritz Fischer } 130fdec2d21SMoritz Fischer 131fdec2d21SMoritz Fischer /* Clear interrupt status flags */ 132fdec2d21SMoritz Fischer writel(int_status & mask, &cdns_i2c->interrupt_status); 133fdec2d21SMoritz Fischer 134fdec2d21SMoritz Fischer return int_status & mask; 135fdec2d21SMoritz Fischer } 136fdec2d21SMoritz Fischer 137*ad72e762SMichal Simek #define CDNS_I2C_DIVA_MAX 4 138*ad72e762SMichal Simek #define CDNS_I2C_DIVB_MAX 64 139*ad72e762SMichal Simek 140*ad72e762SMichal Simek static int cdns_i2c_calc_divs(unsigned long *f, unsigned long input_clk, 141*ad72e762SMichal Simek unsigned int *a, unsigned int *b) 142*ad72e762SMichal Simek { 143*ad72e762SMichal Simek unsigned long fscl = *f, best_fscl = *f, actual_fscl, temp; 144*ad72e762SMichal Simek unsigned int div_a, div_b, calc_div_a = 0, calc_div_b = 0; 145*ad72e762SMichal Simek unsigned int last_error, current_error; 146*ad72e762SMichal Simek 147*ad72e762SMichal Simek /* calculate (divisor_a+1) x (divisor_b+1) */ 148*ad72e762SMichal Simek temp = input_clk / (22 * fscl); 149*ad72e762SMichal Simek 150*ad72e762SMichal Simek /* 151*ad72e762SMichal Simek * If the calculated value is negative or 0CDNS_I2C_DIVA_MAX, 152*ad72e762SMichal Simek * the fscl input is out of range. Return error. 153*ad72e762SMichal Simek */ 154*ad72e762SMichal Simek if (!temp || (temp > (CDNS_I2C_DIVA_MAX * CDNS_I2C_DIVB_MAX))) 155*ad72e762SMichal Simek return -EINVAL; 156*ad72e762SMichal Simek 157*ad72e762SMichal Simek last_error = -1; 158*ad72e762SMichal Simek for (div_a = 0; div_a < CDNS_I2C_DIVA_MAX; div_a++) { 159*ad72e762SMichal Simek div_b = DIV_ROUND_UP(input_clk, 22 * fscl * (div_a + 1)); 160*ad72e762SMichal Simek 161*ad72e762SMichal Simek if ((div_b < 1) || (div_b > CDNS_I2C_DIVB_MAX)) 162*ad72e762SMichal Simek continue; 163*ad72e762SMichal Simek div_b--; 164*ad72e762SMichal Simek 165*ad72e762SMichal Simek actual_fscl = input_clk / (22 * (div_a + 1) * (div_b + 1)); 166*ad72e762SMichal Simek 167*ad72e762SMichal Simek if (actual_fscl > fscl) 168*ad72e762SMichal Simek continue; 169*ad72e762SMichal Simek 170*ad72e762SMichal Simek current_error = ((actual_fscl > fscl) ? (actual_fscl - fscl) : 171*ad72e762SMichal Simek (fscl - actual_fscl)); 172*ad72e762SMichal Simek 173*ad72e762SMichal Simek if (last_error > current_error) { 174*ad72e762SMichal Simek calc_div_a = div_a; 175*ad72e762SMichal Simek calc_div_b = div_b; 176*ad72e762SMichal Simek best_fscl = actual_fscl; 177*ad72e762SMichal Simek last_error = current_error; 178*ad72e762SMichal Simek } 179*ad72e762SMichal Simek } 180*ad72e762SMichal Simek 181*ad72e762SMichal Simek *a = calc_div_a; 182*ad72e762SMichal Simek *b = calc_div_b; 183*ad72e762SMichal Simek *f = best_fscl; 184*ad72e762SMichal Simek 185*ad72e762SMichal Simek return 0; 186*ad72e762SMichal Simek } 187*ad72e762SMichal Simek 188fdec2d21SMoritz Fischer static int cdns_i2c_set_bus_speed(struct udevice *dev, unsigned int speed) 189fdec2d21SMoritz Fischer { 1906150be90SMichal Simek struct i2c_cdns_bus *bus = dev_get_priv(dev); 191*ad72e762SMichal Simek u32 div_a = 0, div_b = 0; 192*ad72e762SMichal Simek unsigned long speed_p = speed; 193*ad72e762SMichal Simek int ret = 0; 1946150be90SMichal Simek 195*ad72e762SMichal Simek if (speed > 400000) { 196*ad72e762SMichal Simek debug("%s, failed to set clock speed to %u\n", __func__, 197fdec2d21SMoritz Fischer speed); 198fdec2d21SMoritz Fischer return -EINVAL; 199fdec2d21SMoritz Fischer } 200fdec2d21SMoritz Fischer 201*ad72e762SMichal Simek ret = cdns_i2c_calc_divs(&speed_p, bus->input_freq, &div_a, &div_b); 202*ad72e762SMichal Simek if (ret) 203*ad72e762SMichal Simek return ret; 204*ad72e762SMichal Simek 205*ad72e762SMichal Simek debug("%s: div_a: %d, div_b: %d, input freq: %d, speed: %d/%ld\n", 206*ad72e762SMichal Simek __func__, div_a, div_b, bus->input_freq, speed, speed_p); 207*ad72e762SMichal Simek 208*ad72e762SMichal Simek writel((div_b << CDNS_I2C_CONTROL_DIV_B_SHIFT) | 209*ad72e762SMichal Simek (div_a << CDNS_I2C_CONTROL_DIV_A_SHIFT), &bus->regs->control); 2106150be90SMichal Simek 2116150be90SMichal Simek /* Enable master mode, ack, and 7-bit addressing */ 2126150be90SMichal Simek setbits_le32(&bus->regs->control, CDNS_I2C_CONTROL_MS | 2136150be90SMichal Simek CDNS_I2C_CONTROL_ACKEN | CDNS_I2C_CONTROL_NEA); 2146150be90SMichal Simek 215fdec2d21SMoritz Fischer return 0; 216fdec2d21SMoritz Fischer } 217fdec2d21SMoritz Fischer 218fdec2d21SMoritz Fischer /* Probe to see if a chip is present. */ 219fdec2d21SMoritz Fischer static int cdns_i2c_probe_chip(struct udevice *bus, uint chip_addr, 220fdec2d21SMoritz Fischer uint chip_flags) 221fdec2d21SMoritz Fischer { 222fdec2d21SMoritz Fischer struct i2c_cdns_bus *i2c_bus = dev_get_priv(bus); 223fdec2d21SMoritz Fischer struct cdns_i2c_regs *regs = i2c_bus->regs; 224fdec2d21SMoritz Fischer 225fdec2d21SMoritz Fischer /* Attempt to read a byte */ 226fdec2d21SMoritz Fischer setbits_le32(®s->control, CDNS_I2C_CONTROL_CLR_FIFO | 227fdec2d21SMoritz Fischer CDNS_I2C_CONTROL_RW); 228fdec2d21SMoritz Fischer clrbits_le32(®s->control, CDNS_I2C_CONTROL_HOLD); 229fdec2d21SMoritz Fischer writel(0xFF, ®s->interrupt_status); 230fdec2d21SMoritz Fischer writel(chip_addr, ®s->address); 231fdec2d21SMoritz Fischer writel(1, ®s->transfer_size); 232fdec2d21SMoritz Fischer 233fdec2d21SMoritz Fischer return (cdns_i2c_wait(regs, CDNS_I2C_INTERRUPT_COMP | 234fdec2d21SMoritz Fischer CDNS_I2C_INTERRUPT_NACK) & 235fdec2d21SMoritz Fischer CDNS_I2C_INTERRUPT_COMP) ? 0 : -ETIMEDOUT; 236fdec2d21SMoritz Fischer } 237fdec2d21SMoritz Fischer 238fdec2d21SMoritz Fischer static int cdns_i2c_write_data(struct i2c_cdns_bus *i2c_bus, u32 addr, u8 *data, 239fdec2d21SMoritz Fischer u32 len, bool next_is_read) 240fdec2d21SMoritz Fischer { 241fdec2d21SMoritz Fischer u8 *cur_data = data; 242fdec2d21SMoritz Fischer 243fdec2d21SMoritz Fischer struct cdns_i2c_regs *regs = i2c_bus->regs; 244fdec2d21SMoritz Fischer 245fdec2d21SMoritz Fischer setbits_le32(®s->control, CDNS_I2C_CONTROL_CLR_FIFO | 246fdec2d21SMoritz Fischer CDNS_I2C_CONTROL_HOLD); 247fdec2d21SMoritz Fischer 248fdec2d21SMoritz Fischer /* if next is a read, we need to clear HOLD, doesn't work */ 249fdec2d21SMoritz Fischer if (next_is_read) 250fdec2d21SMoritz Fischer clrbits_le32(®s->control, CDNS_I2C_CONTROL_HOLD); 251fdec2d21SMoritz Fischer 252fdec2d21SMoritz Fischer clrbits_le32(®s->control, CDNS_I2C_CONTROL_RW); 253fdec2d21SMoritz Fischer 254fdec2d21SMoritz Fischer writel(0xFF, ®s->interrupt_status); 255fdec2d21SMoritz Fischer writel(addr, ®s->address); 256fdec2d21SMoritz Fischer 257fdec2d21SMoritz Fischer while (len--) { 258fdec2d21SMoritz Fischer writel(*(cur_data++), ®s->data); 259fdec2d21SMoritz Fischer if (readl(®s->transfer_size) == CDNS_I2C_FIFO_DEPTH) { 260fdec2d21SMoritz Fischer if (!cdns_i2c_wait(regs, CDNS_I2C_INTERRUPT_COMP)) { 261fdec2d21SMoritz Fischer /* Release the bus */ 262fdec2d21SMoritz Fischer clrbits_le32(®s->control, 263fdec2d21SMoritz Fischer CDNS_I2C_CONTROL_HOLD); 264fdec2d21SMoritz Fischer return -ETIMEDOUT; 265fdec2d21SMoritz Fischer } 266fdec2d21SMoritz Fischer } 267fdec2d21SMoritz Fischer } 268fdec2d21SMoritz Fischer 269fdec2d21SMoritz Fischer /* All done... release the bus */ 270fdec2d21SMoritz Fischer clrbits_le32(®s->control, CDNS_I2C_CONTROL_HOLD); 271fdec2d21SMoritz Fischer /* Wait for the address and data to be sent */ 272fdec2d21SMoritz Fischer if (!cdns_i2c_wait(regs, CDNS_I2C_INTERRUPT_COMP)) 273fdec2d21SMoritz Fischer return -ETIMEDOUT; 274fdec2d21SMoritz Fischer return 0; 275fdec2d21SMoritz Fischer } 276fdec2d21SMoritz Fischer 277fdec2d21SMoritz Fischer static int cdns_i2c_read_data(struct i2c_cdns_bus *i2c_bus, u32 addr, u8 *data, 278fdec2d21SMoritz Fischer u32 len) 279fdec2d21SMoritz Fischer { 280fdec2d21SMoritz Fischer u32 status; 281fdec2d21SMoritz Fischer u32 i = 0; 282fdec2d21SMoritz Fischer u8 *cur_data = data; 283fdec2d21SMoritz Fischer 284fdec2d21SMoritz Fischer /* TODO: Fix this */ 285fdec2d21SMoritz Fischer struct cdns_i2c_regs *regs = i2c_bus->regs; 286fdec2d21SMoritz Fischer 287fdec2d21SMoritz Fischer /* Check the hardware can handle the requested bytes */ 288fdec2d21SMoritz Fischer if ((len < 0) || (len > CDNS_I2C_TRANSFER_SIZE_MAX)) 289fdec2d21SMoritz Fischer return -EINVAL; 290fdec2d21SMoritz Fischer 291fdec2d21SMoritz Fischer setbits_le32(®s->control, CDNS_I2C_CONTROL_CLR_FIFO | 292fdec2d21SMoritz Fischer CDNS_I2C_CONTROL_RW); 293fdec2d21SMoritz Fischer 294fdec2d21SMoritz Fischer /* Start reading data */ 295fdec2d21SMoritz Fischer writel(addr, ®s->address); 296fdec2d21SMoritz Fischer writel(len, ®s->transfer_size); 297fdec2d21SMoritz Fischer 298fdec2d21SMoritz Fischer /* Wait for data */ 299fdec2d21SMoritz Fischer do { 300fdec2d21SMoritz Fischer status = cdns_i2c_wait(regs, CDNS_I2C_INTERRUPT_COMP | 301fdec2d21SMoritz Fischer CDNS_I2C_INTERRUPT_DATA); 302fdec2d21SMoritz Fischer if (!status) { 303fdec2d21SMoritz Fischer /* Release the bus */ 304fdec2d21SMoritz Fischer clrbits_le32(®s->control, CDNS_I2C_CONTROL_HOLD); 305fdec2d21SMoritz Fischer return -ETIMEDOUT; 306fdec2d21SMoritz Fischer } 307fdec2d21SMoritz Fischer debug("Read %d bytes\n", 308fdec2d21SMoritz Fischer len - readl(®s->transfer_size)); 309fdec2d21SMoritz Fischer for (; i < len - readl(®s->transfer_size); i++) 310fdec2d21SMoritz Fischer *(cur_data++) = readl(®s->data); 311fdec2d21SMoritz Fischer } while (readl(®s->transfer_size) != 0); 312fdec2d21SMoritz Fischer /* All done... release the bus */ 313fdec2d21SMoritz Fischer clrbits_le32(®s->control, CDNS_I2C_CONTROL_HOLD); 314fdec2d21SMoritz Fischer 315fdec2d21SMoritz Fischer #ifdef DEBUG 316fdec2d21SMoritz Fischer cdns_i2c_debug_status(regs); 317fdec2d21SMoritz Fischer #endif 318fdec2d21SMoritz Fischer return 0; 319fdec2d21SMoritz Fischer } 320fdec2d21SMoritz Fischer 321fdec2d21SMoritz Fischer static int cdns_i2c_xfer(struct udevice *dev, struct i2c_msg *msg, 322fdec2d21SMoritz Fischer int nmsgs) 323fdec2d21SMoritz Fischer { 324fdec2d21SMoritz Fischer struct i2c_cdns_bus *i2c_bus = dev_get_priv(dev); 325fdec2d21SMoritz Fischer int ret; 326fdec2d21SMoritz Fischer 327fdec2d21SMoritz Fischer debug("i2c_xfer: %d messages\n", nmsgs); 328fdec2d21SMoritz Fischer for (; nmsgs > 0; nmsgs--, msg++) { 329fdec2d21SMoritz Fischer bool next_is_read = nmsgs > 1 && (msg[1].flags & I2C_M_RD); 330fdec2d21SMoritz Fischer 331fdec2d21SMoritz Fischer debug("i2c_xfer: chip=0x%x, len=0x%x\n", msg->addr, msg->len); 332fdec2d21SMoritz Fischer if (msg->flags & I2C_M_RD) { 333fdec2d21SMoritz Fischer ret = cdns_i2c_read_data(i2c_bus, msg->addr, msg->buf, 334fdec2d21SMoritz Fischer msg->len); 335fdec2d21SMoritz Fischer } else { 336fdec2d21SMoritz Fischer ret = cdns_i2c_write_data(i2c_bus, msg->addr, msg->buf, 337fdec2d21SMoritz Fischer msg->len, next_is_read); 338fdec2d21SMoritz Fischer } 339fdec2d21SMoritz Fischer if (ret) { 340fdec2d21SMoritz Fischer debug("i2c_write: error sending\n"); 341fdec2d21SMoritz Fischer return -EREMOTEIO; 342fdec2d21SMoritz Fischer } 343fdec2d21SMoritz Fischer } 344fdec2d21SMoritz Fischer 345fdec2d21SMoritz Fischer return 0; 346fdec2d21SMoritz Fischer } 347fdec2d21SMoritz Fischer 348a13767bcSMichal Simek static int cdns_i2c_ofdata_to_platdata(struct udevice *dev) 349a13767bcSMichal Simek { 350a13767bcSMichal Simek struct i2c_cdns_bus *i2c_bus = dev_get_priv(dev); 351a13767bcSMichal Simek 352a13767bcSMichal Simek i2c_bus->regs = (struct cdns_i2c_regs *)dev_get_addr(dev); 353a13767bcSMichal Simek if (!i2c_bus->regs) 354a13767bcSMichal Simek return -ENOMEM; 355a13767bcSMichal Simek 356*ad72e762SMichal Simek i2c_bus->input_freq = 100000000; /* TODO hardcode input freq for now */ 357*ad72e762SMichal Simek 358a13767bcSMichal Simek return 0; 359a13767bcSMichal Simek } 360a13767bcSMichal Simek 361fdec2d21SMoritz Fischer static const struct dm_i2c_ops cdns_i2c_ops = { 362fdec2d21SMoritz Fischer .xfer = cdns_i2c_xfer, 363fdec2d21SMoritz Fischer .probe_chip = cdns_i2c_probe_chip, 364fdec2d21SMoritz Fischer .set_bus_speed = cdns_i2c_set_bus_speed, 365fdec2d21SMoritz Fischer }; 366fdec2d21SMoritz Fischer 367fdec2d21SMoritz Fischer static const struct udevice_id cdns_i2c_of_match[] = { 368fdec2d21SMoritz Fischer { .compatible = "cdns,i2c-r1p10" }, 369fdec2d21SMoritz Fischer { /* end of table */ } 370fdec2d21SMoritz Fischer }; 371fdec2d21SMoritz Fischer 372fdec2d21SMoritz Fischer U_BOOT_DRIVER(cdns_i2c) = { 373fdec2d21SMoritz Fischer .name = "i2c-cdns", 374fdec2d21SMoritz Fischer .id = UCLASS_I2C, 375fdec2d21SMoritz Fischer .of_match = cdns_i2c_of_match, 376a13767bcSMichal Simek .ofdata_to_platdata = cdns_i2c_ofdata_to_platdata, 377fdec2d21SMoritz Fischer .priv_auto_alloc_size = sizeof(struct i2c_cdns_bus), 378fdec2d21SMoritz Fischer .ops = &cdns_i2c_ops, 379fdec2d21SMoritz Fischer }; 380