162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright (C) 2011 NXP Semiconductors 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Code portions referenced from the i2x-pxa and i2c-pnx drivers 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * Make SMBus byte and word transactions work on LPC178x/7x 862306a36Sopenharmony_ci * Copyright (c) 2012 962306a36Sopenharmony_ci * Alexander Potashev, Emcraft Systems, aspotashev@emcraft.com 1062306a36Sopenharmony_ci * Anton Protopopov, Emcraft Systems, antonp@emcraft.com 1162306a36Sopenharmony_ci * 1262306a36Sopenharmony_ci * Copyright (C) 2015 Joachim Eastwood <manabian@gmail.com> 1362306a36Sopenharmony_ci */ 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_ci#include <linux/clk.h> 1662306a36Sopenharmony_ci#include <linux/errno.h> 1762306a36Sopenharmony_ci#include <linux/i2c.h> 1862306a36Sopenharmony_ci#include <linux/interrupt.h> 1962306a36Sopenharmony_ci#include <linux/io.h> 2062306a36Sopenharmony_ci#include <linux/kernel.h> 2162306a36Sopenharmony_ci#include <linux/module.h> 2262306a36Sopenharmony_ci#include <linux/of.h> 2362306a36Sopenharmony_ci#include <linux/platform_device.h> 2462306a36Sopenharmony_ci#include <linux/sched.h> 2562306a36Sopenharmony_ci#include <linux/time.h> 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_ci/* LPC24xx register offsets and bits */ 2862306a36Sopenharmony_ci#define LPC24XX_I2CONSET 0x00 2962306a36Sopenharmony_ci#define LPC24XX_I2STAT 0x04 3062306a36Sopenharmony_ci#define LPC24XX_I2DAT 0x08 3162306a36Sopenharmony_ci#define LPC24XX_I2ADDR 0x0c 3262306a36Sopenharmony_ci#define LPC24XX_I2SCLH 0x10 3362306a36Sopenharmony_ci#define LPC24XX_I2SCLL 0x14 3462306a36Sopenharmony_ci#define LPC24XX_I2CONCLR 0x18 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_ci#define LPC24XX_AA BIT(2) 3762306a36Sopenharmony_ci#define LPC24XX_SI BIT(3) 3862306a36Sopenharmony_ci#define LPC24XX_STO BIT(4) 3962306a36Sopenharmony_ci#define LPC24XX_STA BIT(5) 4062306a36Sopenharmony_ci#define LPC24XX_I2EN BIT(6) 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_ci#define LPC24XX_STO_AA (LPC24XX_STO | LPC24XX_AA) 4362306a36Sopenharmony_ci#define LPC24XX_CLEAR_ALL (LPC24XX_AA | LPC24XX_SI | LPC24XX_STO | \ 4462306a36Sopenharmony_ci LPC24XX_STA | LPC24XX_I2EN) 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_ci/* I2C SCL clock has different duty cycle depending on mode */ 4762306a36Sopenharmony_ci#define I2C_STD_MODE_DUTY 46 4862306a36Sopenharmony_ci#define I2C_FAST_MODE_DUTY 36 4962306a36Sopenharmony_ci#define I2C_FAST_MODE_PLUS_DUTY 38 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_ci/* 5262306a36Sopenharmony_ci * 26 possible I2C status codes, but codes applicable only 5362306a36Sopenharmony_ci * to master are listed here and used in this driver 5462306a36Sopenharmony_ci */ 5562306a36Sopenharmony_cienum { 5662306a36Sopenharmony_ci M_BUS_ERROR = 0x00, 5762306a36Sopenharmony_ci M_START = 0x08, 5862306a36Sopenharmony_ci M_REPSTART = 0x10, 5962306a36Sopenharmony_ci MX_ADDR_W_ACK = 0x18, 6062306a36Sopenharmony_ci MX_ADDR_W_NACK = 0x20, 6162306a36Sopenharmony_ci MX_DATA_W_ACK = 0x28, 6262306a36Sopenharmony_ci MX_DATA_W_NACK = 0x30, 6362306a36Sopenharmony_ci M_DATA_ARB_LOST = 0x38, 6462306a36Sopenharmony_ci MR_ADDR_R_ACK = 0x40, 6562306a36Sopenharmony_ci MR_ADDR_R_NACK = 0x48, 6662306a36Sopenharmony_ci MR_DATA_R_ACK = 0x50, 6762306a36Sopenharmony_ci MR_DATA_R_NACK = 0x58, 6862306a36Sopenharmony_ci M_I2C_IDLE = 0xf8, 6962306a36Sopenharmony_ci}; 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_cistruct lpc2k_i2c { 7262306a36Sopenharmony_ci void __iomem *base; 7362306a36Sopenharmony_ci struct clk *clk; 7462306a36Sopenharmony_ci int irq; 7562306a36Sopenharmony_ci wait_queue_head_t wait; 7662306a36Sopenharmony_ci struct i2c_adapter adap; 7762306a36Sopenharmony_ci struct i2c_msg *msg; 7862306a36Sopenharmony_ci int msg_idx; 7962306a36Sopenharmony_ci int msg_status; 8062306a36Sopenharmony_ci int is_last; 8162306a36Sopenharmony_ci}; 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_cistatic void i2c_lpc2k_reset(struct lpc2k_i2c *i2c) 8462306a36Sopenharmony_ci{ 8562306a36Sopenharmony_ci /* Will force clear all statuses */ 8662306a36Sopenharmony_ci writel(LPC24XX_CLEAR_ALL, i2c->base + LPC24XX_I2CONCLR); 8762306a36Sopenharmony_ci writel(0, i2c->base + LPC24XX_I2ADDR); 8862306a36Sopenharmony_ci writel(LPC24XX_I2EN, i2c->base + LPC24XX_I2CONSET); 8962306a36Sopenharmony_ci} 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_cistatic int i2c_lpc2k_clear_arb(struct lpc2k_i2c *i2c) 9262306a36Sopenharmony_ci{ 9362306a36Sopenharmony_ci unsigned long timeout = jiffies + msecs_to_jiffies(1000); 9462306a36Sopenharmony_ci 9562306a36Sopenharmony_ci /* 9662306a36Sopenharmony_ci * If the transfer needs to abort for some reason, we'll try to 9762306a36Sopenharmony_ci * force a stop condition to clear any pending bus conditions 9862306a36Sopenharmony_ci */ 9962306a36Sopenharmony_ci writel(LPC24XX_STO, i2c->base + LPC24XX_I2CONSET); 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_ci /* Wait for status change */ 10262306a36Sopenharmony_ci while (readl(i2c->base + LPC24XX_I2STAT) != M_I2C_IDLE) { 10362306a36Sopenharmony_ci if (time_after(jiffies, timeout)) { 10462306a36Sopenharmony_ci /* Bus was not idle, try to reset adapter */ 10562306a36Sopenharmony_ci i2c_lpc2k_reset(i2c); 10662306a36Sopenharmony_ci return -EBUSY; 10762306a36Sopenharmony_ci } 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_ci cpu_relax(); 11062306a36Sopenharmony_ci } 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_ci return 0; 11362306a36Sopenharmony_ci} 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_cistatic void i2c_lpc2k_pump_msg(struct lpc2k_i2c *i2c) 11662306a36Sopenharmony_ci{ 11762306a36Sopenharmony_ci unsigned char data; 11862306a36Sopenharmony_ci u32 status; 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_ci /* 12162306a36Sopenharmony_ci * I2C in the LPC2xxx series is basically a state machine. 12262306a36Sopenharmony_ci * Just run through the steps based on the current status. 12362306a36Sopenharmony_ci */ 12462306a36Sopenharmony_ci status = readl(i2c->base + LPC24XX_I2STAT); 12562306a36Sopenharmony_ci 12662306a36Sopenharmony_ci switch (status) { 12762306a36Sopenharmony_ci case M_START: 12862306a36Sopenharmony_ci case M_REPSTART: 12962306a36Sopenharmony_ci /* Start bit was just sent out, send out addr and dir */ 13062306a36Sopenharmony_ci data = i2c_8bit_addr_from_msg(i2c->msg); 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_ci writel(data, i2c->base + LPC24XX_I2DAT); 13362306a36Sopenharmony_ci writel(LPC24XX_STA, i2c->base + LPC24XX_I2CONCLR); 13462306a36Sopenharmony_ci break; 13562306a36Sopenharmony_ci 13662306a36Sopenharmony_ci case MX_ADDR_W_ACK: 13762306a36Sopenharmony_ci case MX_DATA_W_ACK: 13862306a36Sopenharmony_ci /* 13962306a36Sopenharmony_ci * Address or data was sent out with an ACK. If there is more 14062306a36Sopenharmony_ci * data to send, send it now 14162306a36Sopenharmony_ci */ 14262306a36Sopenharmony_ci if (i2c->msg_idx < i2c->msg->len) { 14362306a36Sopenharmony_ci writel(i2c->msg->buf[i2c->msg_idx], 14462306a36Sopenharmony_ci i2c->base + LPC24XX_I2DAT); 14562306a36Sopenharmony_ci } else if (i2c->is_last) { 14662306a36Sopenharmony_ci /* Last message, send stop */ 14762306a36Sopenharmony_ci writel(LPC24XX_STO_AA, i2c->base + LPC24XX_I2CONSET); 14862306a36Sopenharmony_ci writel(LPC24XX_SI, i2c->base + LPC24XX_I2CONCLR); 14962306a36Sopenharmony_ci i2c->msg_status = 0; 15062306a36Sopenharmony_ci disable_irq_nosync(i2c->irq); 15162306a36Sopenharmony_ci } else { 15262306a36Sopenharmony_ci i2c->msg_status = 0; 15362306a36Sopenharmony_ci disable_irq_nosync(i2c->irq); 15462306a36Sopenharmony_ci } 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_ci i2c->msg_idx++; 15762306a36Sopenharmony_ci break; 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_ci case MR_ADDR_R_ACK: 16062306a36Sopenharmony_ci /* Receive first byte from slave */ 16162306a36Sopenharmony_ci if (i2c->msg->len == 1) { 16262306a36Sopenharmony_ci /* Last byte, return NACK */ 16362306a36Sopenharmony_ci writel(LPC24XX_AA, i2c->base + LPC24XX_I2CONCLR); 16462306a36Sopenharmony_ci } else { 16562306a36Sopenharmony_ci /* Not last byte, return ACK */ 16662306a36Sopenharmony_ci writel(LPC24XX_AA, i2c->base + LPC24XX_I2CONSET); 16762306a36Sopenharmony_ci } 16862306a36Sopenharmony_ci 16962306a36Sopenharmony_ci writel(LPC24XX_STA, i2c->base + LPC24XX_I2CONCLR); 17062306a36Sopenharmony_ci break; 17162306a36Sopenharmony_ci 17262306a36Sopenharmony_ci case MR_DATA_R_NACK: 17362306a36Sopenharmony_ci /* 17462306a36Sopenharmony_ci * The I2C shows NACK status on reads, so we need to accept 17562306a36Sopenharmony_ci * the NACK as an ACK here. This should be ok, as the real 17662306a36Sopenharmony_ci * BACK would of been caught on the address write. 17762306a36Sopenharmony_ci */ 17862306a36Sopenharmony_ci case MR_DATA_R_ACK: 17962306a36Sopenharmony_ci /* Data was received */ 18062306a36Sopenharmony_ci if (i2c->msg_idx < i2c->msg->len) { 18162306a36Sopenharmony_ci i2c->msg->buf[i2c->msg_idx] = 18262306a36Sopenharmony_ci readl(i2c->base + LPC24XX_I2DAT); 18362306a36Sopenharmony_ci } 18462306a36Sopenharmony_ci 18562306a36Sopenharmony_ci /* If transfer is done, send STOP */ 18662306a36Sopenharmony_ci if (i2c->msg_idx >= i2c->msg->len - 1 && i2c->is_last) { 18762306a36Sopenharmony_ci writel(LPC24XX_STO_AA, i2c->base + LPC24XX_I2CONSET); 18862306a36Sopenharmony_ci writel(LPC24XX_SI, i2c->base + LPC24XX_I2CONCLR); 18962306a36Sopenharmony_ci i2c->msg_status = 0; 19062306a36Sopenharmony_ci } 19162306a36Sopenharmony_ci 19262306a36Sopenharmony_ci /* Message is done */ 19362306a36Sopenharmony_ci if (i2c->msg_idx >= i2c->msg->len - 1) { 19462306a36Sopenharmony_ci i2c->msg_status = 0; 19562306a36Sopenharmony_ci disable_irq_nosync(i2c->irq); 19662306a36Sopenharmony_ci } 19762306a36Sopenharmony_ci 19862306a36Sopenharmony_ci /* 19962306a36Sopenharmony_ci * One pre-last data input, send NACK to tell the slave that 20062306a36Sopenharmony_ci * this is going to be the last data byte to be transferred. 20162306a36Sopenharmony_ci */ 20262306a36Sopenharmony_ci if (i2c->msg_idx >= i2c->msg->len - 2) { 20362306a36Sopenharmony_ci /* One byte left to receive - NACK */ 20462306a36Sopenharmony_ci writel(LPC24XX_AA, i2c->base + LPC24XX_I2CONCLR); 20562306a36Sopenharmony_ci } else { 20662306a36Sopenharmony_ci /* More than one byte left to receive - ACK */ 20762306a36Sopenharmony_ci writel(LPC24XX_AA, i2c->base + LPC24XX_I2CONSET); 20862306a36Sopenharmony_ci } 20962306a36Sopenharmony_ci 21062306a36Sopenharmony_ci writel(LPC24XX_STA, i2c->base + LPC24XX_I2CONCLR); 21162306a36Sopenharmony_ci i2c->msg_idx++; 21262306a36Sopenharmony_ci break; 21362306a36Sopenharmony_ci 21462306a36Sopenharmony_ci case MX_ADDR_W_NACK: 21562306a36Sopenharmony_ci case MX_DATA_W_NACK: 21662306a36Sopenharmony_ci case MR_ADDR_R_NACK: 21762306a36Sopenharmony_ci /* NACK processing is done */ 21862306a36Sopenharmony_ci writel(LPC24XX_STO_AA, i2c->base + LPC24XX_I2CONSET); 21962306a36Sopenharmony_ci i2c->msg_status = -ENXIO; 22062306a36Sopenharmony_ci disable_irq_nosync(i2c->irq); 22162306a36Sopenharmony_ci break; 22262306a36Sopenharmony_ci 22362306a36Sopenharmony_ci case M_DATA_ARB_LOST: 22462306a36Sopenharmony_ci /* Arbitration lost */ 22562306a36Sopenharmony_ci i2c->msg_status = -EAGAIN; 22662306a36Sopenharmony_ci 22762306a36Sopenharmony_ci /* Release the I2C bus */ 22862306a36Sopenharmony_ci writel(LPC24XX_STA | LPC24XX_STO, i2c->base + LPC24XX_I2CONCLR); 22962306a36Sopenharmony_ci disable_irq_nosync(i2c->irq); 23062306a36Sopenharmony_ci break; 23162306a36Sopenharmony_ci 23262306a36Sopenharmony_ci default: 23362306a36Sopenharmony_ci /* Unexpected statuses */ 23462306a36Sopenharmony_ci i2c->msg_status = -EIO; 23562306a36Sopenharmony_ci disable_irq_nosync(i2c->irq); 23662306a36Sopenharmony_ci break; 23762306a36Sopenharmony_ci } 23862306a36Sopenharmony_ci 23962306a36Sopenharmony_ci /* Exit on failure or all bytes transferred */ 24062306a36Sopenharmony_ci if (i2c->msg_status != -EBUSY) 24162306a36Sopenharmony_ci wake_up(&i2c->wait); 24262306a36Sopenharmony_ci 24362306a36Sopenharmony_ci /* 24462306a36Sopenharmony_ci * If `msg_status` is zero, then `lpc2k_process_msg()` 24562306a36Sopenharmony_ci * is responsible for clearing the SI flag. 24662306a36Sopenharmony_ci */ 24762306a36Sopenharmony_ci if (i2c->msg_status != 0) 24862306a36Sopenharmony_ci writel(LPC24XX_SI, i2c->base + LPC24XX_I2CONCLR); 24962306a36Sopenharmony_ci} 25062306a36Sopenharmony_ci 25162306a36Sopenharmony_cistatic int lpc2k_process_msg(struct lpc2k_i2c *i2c, int msgidx) 25262306a36Sopenharmony_ci{ 25362306a36Sopenharmony_ci /* A new transfer is kicked off by initiating a start condition */ 25462306a36Sopenharmony_ci if (!msgidx) { 25562306a36Sopenharmony_ci writel(LPC24XX_STA, i2c->base + LPC24XX_I2CONSET); 25662306a36Sopenharmony_ci } else { 25762306a36Sopenharmony_ci /* 25862306a36Sopenharmony_ci * A multi-message I2C transfer continues where the 25962306a36Sopenharmony_ci * previous I2C transfer left off and uses the 26062306a36Sopenharmony_ci * current condition of the I2C adapter. 26162306a36Sopenharmony_ci */ 26262306a36Sopenharmony_ci if (unlikely(i2c->msg->flags & I2C_M_NOSTART)) { 26362306a36Sopenharmony_ci WARN_ON(i2c->msg->len == 0); 26462306a36Sopenharmony_ci 26562306a36Sopenharmony_ci if (!(i2c->msg->flags & I2C_M_RD)) { 26662306a36Sopenharmony_ci /* Start transmit of data */ 26762306a36Sopenharmony_ci writel(i2c->msg->buf[0], 26862306a36Sopenharmony_ci i2c->base + LPC24XX_I2DAT); 26962306a36Sopenharmony_ci i2c->msg_idx++; 27062306a36Sopenharmony_ci } 27162306a36Sopenharmony_ci } else { 27262306a36Sopenharmony_ci /* Start or repeated start */ 27362306a36Sopenharmony_ci writel(LPC24XX_STA, i2c->base + LPC24XX_I2CONSET); 27462306a36Sopenharmony_ci } 27562306a36Sopenharmony_ci 27662306a36Sopenharmony_ci writel(LPC24XX_SI, i2c->base + LPC24XX_I2CONCLR); 27762306a36Sopenharmony_ci } 27862306a36Sopenharmony_ci 27962306a36Sopenharmony_ci enable_irq(i2c->irq); 28062306a36Sopenharmony_ci 28162306a36Sopenharmony_ci /* Wait for transfer completion */ 28262306a36Sopenharmony_ci if (wait_event_timeout(i2c->wait, i2c->msg_status != -EBUSY, 28362306a36Sopenharmony_ci msecs_to_jiffies(1000)) == 0) { 28462306a36Sopenharmony_ci disable_irq_nosync(i2c->irq); 28562306a36Sopenharmony_ci 28662306a36Sopenharmony_ci return -ETIMEDOUT; 28762306a36Sopenharmony_ci } 28862306a36Sopenharmony_ci 28962306a36Sopenharmony_ci return i2c->msg_status; 29062306a36Sopenharmony_ci} 29162306a36Sopenharmony_ci 29262306a36Sopenharmony_cistatic int i2c_lpc2k_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, 29362306a36Sopenharmony_ci int msg_num) 29462306a36Sopenharmony_ci{ 29562306a36Sopenharmony_ci struct lpc2k_i2c *i2c = i2c_get_adapdata(adap); 29662306a36Sopenharmony_ci int ret, i; 29762306a36Sopenharmony_ci u32 stat; 29862306a36Sopenharmony_ci 29962306a36Sopenharmony_ci /* Check for bus idle condition */ 30062306a36Sopenharmony_ci stat = readl(i2c->base + LPC24XX_I2STAT); 30162306a36Sopenharmony_ci if (stat != M_I2C_IDLE) { 30262306a36Sopenharmony_ci /* Something is holding the bus, try to clear it */ 30362306a36Sopenharmony_ci return i2c_lpc2k_clear_arb(i2c); 30462306a36Sopenharmony_ci } 30562306a36Sopenharmony_ci 30662306a36Sopenharmony_ci /* Process a single message at a time */ 30762306a36Sopenharmony_ci for (i = 0; i < msg_num; i++) { 30862306a36Sopenharmony_ci /* Save message pointer and current message data index */ 30962306a36Sopenharmony_ci i2c->msg = &msgs[i]; 31062306a36Sopenharmony_ci i2c->msg_idx = 0; 31162306a36Sopenharmony_ci i2c->msg_status = -EBUSY; 31262306a36Sopenharmony_ci i2c->is_last = (i == (msg_num - 1)); 31362306a36Sopenharmony_ci 31462306a36Sopenharmony_ci ret = lpc2k_process_msg(i2c, i); 31562306a36Sopenharmony_ci if (ret) 31662306a36Sopenharmony_ci return ret; 31762306a36Sopenharmony_ci } 31862306a36Sopenharmony_ci 31962306a36Sopenharmony_ci return msg_num; 32062306a36Sopenharmony_ci} 32162306a36Sopenharmony_ci 32262306a36Sopenharmony_cistatic irqreturn_t i2c_lpc2k_handler(int irq, void *dev_id) 32362306a36Sopenharmony_ci{ 32462306a36Sopenharmony_ci struct lpc2k_i2c *i2c = dev_id; 32562306a36Sopenharmony_ci 32662306a36Sopenharmony_ci if (readl(i2c->base + LPC24XX_I2CONSET) & LPC24XX_SI) { 32762306a36Sopenharmony_ci i2c_lpc2k_pump_msg(i2c); 32862306a36Sopenharmony_ci return IRQ_HANDLED; 32962306a36Sopenharmony_ci } 33062306a36Sopenharmony_ci 33162306a36Sopenharmony_ci return IRQ_NONE; 33262306a36Sopenharmony_ci} 33362306a36Sopenharmony_ci 33462306a36Sopenharmony_cistatic u32 i2c_lpc2k_functionality(struct i2c_adapter *adap) 33562306a36Sopenharmony_ci{ 33662306a36Sopenharmony_ci /* Only emulated SMBus for now */ 33762306a36Sopenharmony_ci return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; 33862306a36Sopenharmony_ci} 33962306a36Sopenharmony_ci 34062306a36Sopenharmony_cistatic const struct i2c_algorithm i2c_lpc2k_algorithm = { 34162306a36Sopenharmony_ci .master_xfer = i2c_lpc2k_xfer, 34262306a36Sopenharmony_ci .functionality = i2c_lpc2k_functionality, 34362306a36Sopenharmony_ci}; 34462306a36Sopenharmony_ci 34562306a36Sopenharmony_cistatic int i2c_lpc2k_probe(struct platform_device *pdev) 34662306a36Sopenharmony_ci{ 34762306a36Sopenharmony_ci struct lpc2k_i2c *i2c; 34862306a36Sopenharmony_ci u32 bus_clk_rate; 34962306a36Sopenharmony_ci u32 scl_high; 35062306a36Sopenharmony_ci u32 clkrate; 35162306a36Sopenharmony_ci int ret; 35262306a36Sopenharmony_ci 35362306a36Sopenharmony_ci i2c = devm_kzalloc(&pdev->dev, sizeof(*i2c), GFP_KERNEL); 35462306a36Sopenharmony_ci if (!i2c) 35562306a36Sopenharmony_ci return -ENOMEM; 35662306a36Sopenharmony_ci 35762306a36Sopenharmony_ci i2c->base = devm_platform_ioremap_resource(pdev, 0); 35862306a36Sopenharmony_ci if (IS_ERR(i2c->base)) 35962306a36Sopenharmony_ci return PTR_ERR(i2c->base); 36062306a36Sopenharmony_ci 36162306a36Sopenharmony_ci i2c->irq = platform_get_irq(pdev, 0); 36262306a36Sopenharmony_ci if (i2c->irq < 0) 36362306a36Sopenharmony_ci return i2c->irq; 36462306a36Sopenharmony_ci 36562306a36Sopenharmony_ci init_waitqueue_head(&i2c->wait); 36662306a36Sopenharmony_ci 36762306a36Sopenharmony_ci i2c->clk = devm_clk_get_enabled(&pdev->dev, NULL); 36862306a36Sopenharmony_ci if (IS_ERR(i2c->clk)) { 36962306a36Sopenharmony_ci dev_err(&pdev->dev, "failed to enable clock.\n"); 37062306a36Sopenharmony_ci return PTR_ERR(i2c->clk); 37162306a36Sopenharmony_ci } 37262306a36Sopenharmony_ci 37362306a36Sopenharmony_ci ret = devm_request_irq(&pdev->dev, i2c->irq, i2c_lpc2k_handler, 0, 37462306a36Sopenharmony_ci dev_name(&pdev->dev), i2c); 37562306a36Sopenharmony_ci if (ret < 0) { 37662306a36Sopenharmony_ci dev_err(&pdev->dev, "can't request interrupt.\n"); 37762306a36Sopenharmony_ci return ret; 37862306a36Sopenharmony_ci } 37962306a36Sopenharmony_ci 38062306a36Sopenharmony_ci disable_irq_nosync(i2c->irq); 38162306a36Sopenharmony_ci 38262306a36Sopenharmony_ci /* Place controller is a known state */ 38362306a36Sopenharmony_ci i2c_lpc2k_reset(i2c); 38462306a36Sopenharmony_ci 38562306a36Sopenharmony_ci ret = of_property_read_u32(pdev->dev.of_node, "clock-frequency", 38662306a36Sopenharmony_ci &bus_clk_rate); 38762306a36Sopenharmony_ci if (ret) 38862306a36Sopenharmony_ci bus_clk_rate = I2C_MAX_STANDARD_MODE_FREQ; 38962306a36Sopenharmony_ci 39062306a36Sopenharmony_ci clkrate = clk_get_rate(i2c->clk); 39162306a36Sopenharmony_ci if (clkrate == 0) { 39262306a36Sopenharmony_ci dev_err(&pdev->dev, "can't get I2C base clock\n"); 39362306a36Sopenharmony_ci return -EINVAL; 39462306a36Sopenharmony_ci } 39562306a36Sopenharmony_ci 39662306a36Sopenharmony_ci /* Setup I2C dividers to generate clock with proper duty cycle */ 39762306a36Sopenharmony_ci clkrate = clkrate / bus_clk_rate; 39862306a36Sopenharmony_ci if (bus_clk_rate <= I2C_MAX_STANDARD_MODE_FREQ) 39962306a36Sopenharmony_ci scl_high = (clkrate * I2C_STD_MODE_DUTY) / 100; 40062306a36Sopenharmony_ci else if (bus_clk_rate <= I2C_MAX_FAST_MODE_FREQ) 40162306a36Sopenharmony_ci scl_high = (clkrate * I2C_FAST_MODE_DUTY) / 100; 40262306a36Sopenharmony_ci else 40362306a36Sopenharmony_ci scl_high = (clkrate * I2C_FAST_MODE_PLUS_DUTY) / 100; 40462306a36Sopenharmony_ci 40562306a36Sopenharmony_ci writel(scl_high, i2c->base + LPC24XX_I2SCLH); 40662306a36Sopenharmony_ci writel(clkrate - scl_high, i2c->base + LPC24XX_I2SCLL); 40762306a36Sopenharmony_ci 40862306a36Sopenharmony_ci platform_set_drvdata(pdev, i2c); 40962306a36Sopenharmony_ci 41062306a36Sopenharmony_ci i2c_set_adapdata(&i2c->adap, i2c); 41162306a36Sopenharmony_ci i2c->adap.owner = THIS_MODULE; 41262306a36Sopenharmony_ci strscpy(i2c->adap.name, "LPC2K I2C adapter", sizeof(i2c->adap.name)); 41362306a36Sopenharmony_ci i2c->adap.algo = &i2c_lpc2k_algorithm; 41462306a36Sopenharmony_ci i2c->adap.dev.parent = &pdev->dev; 41562306a36Sopenharmony_ci i2c->adap.dev.of_node = pdev->dev.of_node; 41662306a36Sopenharmony_ci 41762306a36Sopenharmony_ci ret = i2c_add_adapter(&i2c->adap); 41862306a36Sopenharmony_ci if (ret < 0) 41962306a36Sopenharmony_ci return ret; 42062306a36Sopenharmony_ci 42162306a36Sopenharmony_ci dev_info(&pdev->dev, "LPC2K I2C adapter\n"); 42262306a36Sopenharmony_ci 42362306a36Sopenharmony_ci return 0; 42462306a36Sopenharmony_ci} 42562306a36Sopenharmony_ci 42662306a36Sopenharmony_cistatic void i2c_lpc2k_remove(struct platform_device *dev) 42762306a36Sopenharmony_ci{ 42862306a36Sopenharmony_ci struct lpc2k_i2c *i2c = platform_get_drvdata(dev); 42962306a36Sopenharmony_ci 43062306a36Sopenharmony_ci i2c_del_adapter(&i2c->adap); 43162306a36Sopenharmony_ci} 43262306a36Sopenharmony_ci 43362306a36Sopenharmony_cistatic int i2c_lpc2k_suspend(struct device *dev) 43462306a36Sopenharmony_ci{ 43562306a36Sopenharmony_ci struct lpc2k_i2c *i2c = dev_get_drvdata(dev); 43662306a36Sopenharmony_ci 43762306a36Sopenharmony_ci clk_disable(i2c->clk); 43862306a36Sopenharmony_ci 43962306a36Sopenharmony_ci return 0; 44062306a36Sopenharmony_ci} 44162306a36Sopenharmony_ci 44262306a36Sopenharmony_cistatic int i2c_lpc2k_resume(struct device *dev) 44362306a36Sopenharmony_ci{ 44462306a36Sopenharmony_ci struct lpc2k_i2c *i2c = dev_get_drvdata(dev); 44562306a36Sopenharmony_ci 44662306a36Sopenharmony_ci clk_enable(i2c->clk); 44762306a36Sopenharmony_ci i2c_lpc2k_reset(i2c); 44862306a36Sopenharmony_ci 44962306a36Sopenharmony_ci return 0; 45062306a36Sopenharmony_ci} 45162306a36Sopenharmony_ci 45262306a36Sopenharmony_cistatic const struct dev_pm_ops i2c_lpc2k_dev_pm_ops = { 45362306a36Sopenharmony_ci .suspend_noirq = i2c_lpc2k_suspend, 45462306a36Sopenharmony_ci .resume_noirq = i2c_lpc2k_resume, 45562306a36Sopenharmony_ci}; 45662306a36Sopenharmony_ci 45762306a36Sopenharmony_cistatic const struct of_device_id lpc2k_i2c_match[] = { 45862306a36Sopenharmony_ci { .compatible = "nxp,lpc1788-i2c" }, 45962306a36Sopenharmony_ci {}, 46062306a36Sopenharmony_ci}; 46162306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, lpc2k_i2c_match); 46262306a36Sopenharmony_ci 46362306a36Sopenharmony_cistatic struct platform_driver i2c_lpc2k_driver = { 46462306a36Sopenharmony_ci .probe = i2c_lpc2k_probe, 46562306a36Sopenharmony_ci .remove_new = i2c_lpc2k_remove, 46662306a36Sopenharmony_ci .driver = { 46762306a36Sopenharmony_ci .name = "lpc2k-i2c", 46862306a36Sopenharmony_ci .pm = pm_sleep_ptr(&i2c_lpc2k_dev_pm_ops), 46962306a36Sopenharmony_ci .of_match_table = lpc2k_i2c_match, 47062306a36Sopenharmony_ci }, 47162306a36Sopenharmony_ci}; 47262306a36Sopenharmony_cimodule_platform_driver(i2c_lpc2k_driver); 47362306a36Sopenharmony_ci 47462306a36Sopenharmony_ciMODULE_AUTHOR("Kevin Wells <kevin.wells@nxp.com>"); 47562306a36Sopenharmony_ciMODULE_DESCRIPTION("I2C driver for LPC2xxx devices"); 47662306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 47762306a36Sopenharmony_ciMODULE_ALIAS("platform:lpc2k-i2c"); 478