162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Driver for the Renesas RZ/V2M I2C unit 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 2016-2022 Renesas Electronics Corporation 662306a36Sopenharmony_ci */ 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci#include <linux/bits.h> 962306a36Sopenharmony_ci#include <linux/clk.h> 1062306a36Sopenharmony_ci#include <linux/device.h> 1162306a36Sopenharmony_ci#include <linux/err.h> 1262306a36Sopenharmony_ci#include <linux/interrupt.h> 1362306a36Sopenharmony_ci#include <linux/io.h> 1462306a36Sopenharmony_ci#include <linux/iopoll.h> 1562306a36Sopenharmony_ci#include <linux/i2c.h> 1662306a36Sopenharmony_ci#include <linux/jiffies.h> 1762306a36Sopenharmony_ci#include <linux/kernel.h> 1862306a36Sopenharmony_ci#include <linux/math64.h> 1962306a36Sopenharmony_ci#include <linux/module.h> 2062306a36Sopenharmony_ci#include <linux/mod_devicetable.h> 2162306a36Sopenharmony_ci#include <linux/platform_device.h> 2262306a36Sopenharmony_ci#include <linux/pm_runtime.h> 2362306a36Sopenharmony_ci#include <linux/reset.h> 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_ci/* Register offsets */ 2662306a36Sopenharmony_ci#define IICB0DAT 0x00 /* Data Register */ 2762306a36Sopenharmony_ci#define IICB0CTL0 0x08 /* Control Register 0 */ 2862306a36Sopenharmony_ci#define IICB0TRG 0x0C /* Trigger Register */ 2962306a36Sopenharmony_ci#define IICB0STR0 0x10 /* Status Register 0 */ 3062306a36Sopenharmony_ci#define IICB0CTL1 0x20 /* Control Register 1 */ 3162306a36Sopenharmony_ci#define IICB0WL 0x24 /* Low Level Width Setting Reg */ 3262306a36Sopenharmony_ci#define IICB0WH 0x28 /* How Level Width Setting Reg */ 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_ci/* IICB0CTL0 */ 3562306a36Sopenharmony_ci#define IICB0IICE BIT(7) /* I2C Enable */ 3662306a36Sopenharmony_ci#define IICB0SLWT BIT(1) /* Interrupt Request Timing */ 3762306a36Sopenharmony_ci#define IICB0SLAC BIT(0) /* Acknowledge */ 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_ci/* IICB0TRG */ 4062306a36Sopenharmony_ci#define IICB0WRET BIT(2) /* Quit Wait Trigger */ 4162306a36Sopenharmony_ci#define IICB0STT BIT(1) /* Create Start Condition Trigger */ 4262306a36Sopenharmony_ci#define IICB0SPT BIT(0) /* Create Stop Condition Trigger */ 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ci/* IICB0STR0 */ 4562306a36Sopenharmony_ci#define IICB0SSAC BIT(8) /* Ack Flag */ 4662306a36Sopenharmony_ci#define IICB0SSBS BIT(6) /* Bus Flag */ 4762306a36Sopenharmony_ci#define IICB0SSSP BIT(4) /* Stop Condition Flag */ 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_ci/* IICB0CTL1 */ 5062306a36Sopenharmony_ci#define IICB0MDSC BIT(7) /* Bus Mode */ 5162306a36Sopenharmony_ci#define IICB0SLSE BIT(1) /* Start condition output */ 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_cistruct rzv2m_i2c_priv { 5462306a36Sopenharmony_ci void __iomem *base; 5562306a36Sopenharmony_ci struct i2c_adapter adap; 5662306a36Sopenharmony_ci struct clk *clk; 5762306a36Sopenharmony_ci int bus_mode; 5862306a36Sopenharmony_ci struct completion msg_tia_done; 5962306a36Sopenharmony_ci u32 iicb0wl; 6062306a36Sopenharmony_ci u32 iicb0wh; 6162306a36Sopenharmony_ci}; 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_cienum bcr_index { 6462306a36Sopenharmony_ci RZV2M_I2C_100K = 0, 6562306a36Sopenharmony_ci RZV2M_I2C_400K, 6662306a36Sopenharmony_ci}; 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_cistruct bitrate_config { 6962306a36Sopenharmony_ci unsigned int percent_low; 7062306a36Sopenharmony_ci unsigned int min_hold_time_ns; 7162306a36Sopenharmony_ci}; 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_cistatic const struct bitrate_config bitrate_configs[] = { 7462306a36Sopenharmony_ci [RZV2M_I2C_100K] = { 47, 3450 }, 7562306a36Sopenharmony_ci [RZV2M_I2C_400K] = { 52, 900 }, 7662306a36Sopenharmony_ci}; 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_cistatic inline void bit_setl(void __iomem *addr, u32 val) 7962306a36Sopenharmony_ci{ 8062306a36Sopenharmony_ci writel(readl(addr) | val, addr); 8162306a36Sopenharmony_ci} 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_cistatic inline void bit_clrl(void __iomem *addr, u32 val) 8462306a36Sopenharmony_ci{ 8562306a36Sopenharmony_ci writel(readl(addr) & ~val, addr); 8662306a36Sopenharmony_ci} 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_cistatic irqreturn_t rzv2m_i2c_tia_irq_handler(int this_irq, void *dev_id) 8962306a36Sopenharmony_ci{ 9062306a36Sopenharmony_ci struct rzv2m_i2c_priv *priv = dev_id; 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_ci complete(&priv->msg_tia_done); 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_ci return IRQ_HANDLED; 9562306a36Sopenharmony_ci} 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_ci/* Calculate IICB0WL and IICB0WH */ 9862306a36Sopenharmony_cistatic int rzv2m_i2c_clock_calculate(struct device *dev, 9962306a36Sopenharmony_ci struct rzv2m_i2c_priv *priv) 10062306a36Sopenharmony_ci{ 10162306a36Sopenharmony_ci const struct bitrate_config *config; 10262306a36Sopenharmony_ci unsigned int hold_time_ns; 10362306a36Sopenharmony_ci unsigned int total_pclks; 10462306a36Sopenharmony_ci unsigned int trf_pclks; 10562306a36Sopenharmony_ci unsigned long pclk_hz; 10662306a36Sopenharmony_ci struct i2c_timings t; 10762306a36Sopenharmony_ci u32 trf_ns; 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_ci i2c_parse_fw_timings(dev, &t, true); 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_ci pclk_hz = clk_get_rate(priv->clk); 11262306a36Sopenharmony_ci total_pclks = pclk_hz / t.bus_freq_hz; 11362306a36Sopenharmony_ci 11462306a36Sopenharmony_ci trf_ns = t.scl_rise_ns + t.scl_fall_ns; 11562306a36Sopenharmony_ci trf_pclks = mul_u64_u32_div(pclk_hz, trf_ns, NSEC_PER_SEC); 11662306a36Sopenharmony_ci 11762306a36Sopenharmony_ci /* Config setting */ 11862306a36Sopenharmony_ci switch (t.bus_freq_hz) { 11962306a36Sopenharmony_ci case I2C_MAX_FAST_MODE_FREQ: 12062306a36Sopenharmony_ci priv->bus_mode = RZV2M_I2C_400K; 12162306a36Sopenharmony_ci break; 12262306a36Sopenharmony_ci case I2C_MAX_STANDARD_MODE_FREQ: 12362306a36Sopenharmony_ci priv->bus_mode = RZV2M_I2C_100K; 12462306a36Sopenharmony_ci break; 12562306a36Sopenharmony_ci default: 12662306a36Sopenharmony_ci dev_err(dev, "transfer speed is invalid\n"); 12762306a36Sopenharmony_ci return -EINVAL; 12862306a36Sopenharmony_ci } 12962306a36Sopenharmony_ci config = &bitrate_configs[priv->bus_mode]; 13062306a36Sopenharmony_ci 13162306a36Sopenharmony_ci /* IICB0WL = (percent_low / Transfer clock) x PCLK */ 13262306a36Sopenharmony_ci priv->iicb0wl = total_pclks * config->percent_low / 100; 13362306a36Sopenharmony_ci if (priv->iicb0wl > (BIT(10) - 1)) 13462306a36Sopenharmony_ci return -EINVAL; 13562306a36Sopenharmony_ci 13662306a36Sopenharmony_ci /* IICB0WH = ((percent_high / Transfer clock) x PCLK) - (tR + tF) */ 13762306a36Sopenharmony_ci priv->iicb0wh = total_pclks - priv->iicb0wl - trf_pclks; 13862306a36Sopenharmony_ci if (priv->iicb0wh > (BIT(10) - 1)) 13962306a36Sopenharmony_ci return -EINVAL; 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_ci /* 14262306a36Sopenharmony_ci * Data hold time must be less than 0.9us in fast mode and 14362306a36Sopenharmony_ci * 3.45us in standard mode. 14462306a36Sopenharmony_ci * Data hold time = IICB0WL[9:2] / PCLK 14562306a36Sopenharmony_ci */ 14662306a36Sopenharmony_ci hold_time_ns = div64_ul((u64)(priv->iicb0wl >> 2) * NSEC_PER_SEC, pclk_hz); 14762306a36Sopenharmony_ci if (hold_time_ns > config->min_hold_time_ns) { 14862306a36Sopenharmony_ci dev_err(dev, "data hold time %dns is over %dns\n", 14962306a36Sopenharmony_ci hold_time_ns, config->min_hold_time_ns); 15062306a36Sopenharmony_ci return -EINVAL; 15162306a36Sopenharmony_ci } 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_ci return 0; 15462306a36Sopenharmony_ci} 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_cistatic void rzv2m_i2c_init(struct rzv2m_i2c_priv *priv) 15762306a36Sopenharmony_ci{ 15862306a36Sopenharmony_ci u32 i2c_ctl0; 15962306a36Sopenharmony_ci u32 i2c_ctl1; 16062306a36Sopenharmony_ci 16162306a36Sopenharmony_ci /* i2c disable */ 16262306a36Sopenharmony_ci writel(0, priv->base + IICB0CTL0); 16362306a36Sopenharmony_ci 16462306a36Sopenharmony_ci /* IICB0CTL1 setting */ 16562306a36Sopenharmony_ci i2c_ctl1 = IICB0SLSE; 16662306a36Sopenharmony_ci if (priv->bus_mode == RZV2M_I2C_400K) 16762306a36Sopenharmony_ci i2c_ctl1 |= IICB0MDSC; 16862306a36Sopenharmony_ci writel(i2c_ctl1, priv->base + IICB0CTL1); 16962306a36Sopenharmony_ci 17062306a36Sopenharmony_ci /* IICB0WL IICB0WH setting */ 17162306a36Sopenharmony_ci writel(priv->iicb0wl, priv->base + IICB0WL); 17262306a36Sopenharmony_ci writel(priv->iicb0wh, priv->base + IICB0WH); 17362306a36Sopenharmony_ci 17462306a36Sopenharmony_ci /* i2c enable after setting */ 17562306a36Sopenharmony_ci i2c_ctl0 = IICB0SLWT | IICB0SLAC | IICB0IICE; 17662306a36Sopenharmony_ci writel(i2c_ctl0, priv->base + IICB0CTL0); 17762306a36Sopenharmony_ci} 17862306a36Sopenharmony_ci 17962306a36Sopenharmony_cistatic int rzv2m_i2c_write_with_ack(struct rzv2m_i2c_priv *priv, u32 data) 18062306a36Sopenharmony_ci{ 18162306a36Sopenharmony_ci unsigned long time_left; 18262306a36Sopenharmony_ci 18362306a36Sopenharmony_ci reinit_completion(&priv->msg_tia_done); 18462306a36Sopenharmony_ci 18562306a36Sopenharmony_ci writel(data, priv->base + IICB0DAT); 18662306a36Sopenharmony_ci 18762306a36Sopenharmony_ci time_left = wait_for_completion_timeout(&priv->msg_tia_done, 18862306a36Sopenharmony_ci priv->adap.timeout); 18962306a36Sopenharmony_ci if (!time_left) 19062306a36Sopenharmony_ci return -ETIMEDOUT; 19162306a36Sopenharmony_ci 19262306a36Sopenharmony_ci /* Confirm ACK */ 19362306a36Sopenharmony_ci if ((readl(priv->base + IICB0STR0) & IICB0SSAC) != IICB0SSAC) 19462306a36Sopenharmony_ci return -ENXIO; 19562306a36Sopenharmony_ci 19662306a36Sopenharmony_ci return 0; 19762306a36Sopenharmony_ci} 19862306a36Sopenharmony_ci 19962306a36Sopenharmony_cistatic int rzv2m_i2c_read_with_ack(struct rzv2m_i2c_priv *priv, u8 *data, 20062306a36Sopenharmony_ci bool last) 20162306a36Sopenharmony_ci{ 20262306a36Sopenharmony_ci unsigned long time_left; 20362306a36Sopenharmony_ci u32 data_tmp; 20462306a36Sopenharmony_ci 20562306a36Sopenharmony_ci reinit_completion(&priv->msg_tia_done); 20662306a36Sopenharmony_ci 20762306a36Sopenharmony_ci /* Interrupt request timing : 8th clock */ 20862306a36Sopenharmony_ci bit_clrl(priv->base + IICB0CTL0, IICB0SLWT); 20962306a36Sopenharmony_ci 21062306a36Sopenharmony_ci /* Exit the wait state */ 21162306a36Sopenharmony_ci writel(IICB0WRET, priv->base + IICB0TRG); 21262306a36Sopenharmony_ci 21362306a36Sopenharmony_ci /* Wait for transaction */ 21462306a36Sopenharmony_ci time_left = wait_for_completion_timeout(&priv->msg_tia_done, 21562306a36Sopenharmony_ci priv->adap.timeout); 21662306a36Sopenharmony_ci if (!time_left) 21762306a36Sopenharmony_ci return -ETIMEDOUT; 21862306a36Sopenharmony_ci 21962306a36Sopenharmony_ci if (last) { 22062306a36Sopenharmony_ci /* Disable ACK */ 22162306a36Sopenharmony_ci bit_clrl(priv->base + IICB0CTL0, IICB0SLAC); 22262306a36Sopenharmony_ci 22362306a36Sopenharmony_ci /* Read data*/ 22462306a36Sopenharmony_ci data_tmp = readl(priv->base + IICB0DAT); 22562306a36Sopenharmony_ci 22662306a36Sopenharmony_ci /* Interrupt request timing : 9th clock */ 22762306a36Sopenharmony_ci bit_setl(priv->base + IICB0CTL0, IICB0SLWT); 22862306a36Sopenharmony_ci 22962306a36Sopenharmony_ci /* Exit the wait state */ 23062306a36Sopenharmony_ci writel(IICB0WRET, priv->base + IICB0TRG); 23162306a36Sopenharmony_ci 23262306a36Sopenharmony_ci /* Wait for transaction */ 23362306a36Sopenharmony_ci time_left = wait_for_completion_timeout(&priv->msg_tia_done, 23462306a36Sopenharmony_ci priv->adap.timeout); 23562306a36Sopenharmony_ci if (!time_left) 23662306a36Sopenharmony_ci return -ETIMEDOUT; 23762306a36Sopenharmony_ci 23862306a36Sopenharmony_ci /* Enable ACK */ 23962306a36Sopenharmony_ci bit_setl(priv->base + IICB0CTL0, IICB0SLAC); 24062306a36Sopenharmony_ci } else { 24162306a36Sopenharmony_ci /* Read data */ 24262306a36Sopenharmony_ci data_tmp = readl(priv->base + IICB0DAT); 24362306a36Sopenharmony_ci } 24462306a36Sopenharmony_ci 24562306a36Sopenharmony_ci *data = data_tmp; 24662306a36Sopenharmony_ci 24762306a36Sopenharmony_ci return 0; 24862306a36Sopenharmony_ci} 24962306a36Sopenharmony_ci 25062306a36Sopenharmony_cistatic int rzv2m_i2c_send(struct rzv2m_i2c_priv *priv, struct i2c_msg *msg, 25162306a36Sopenharmony_ci unsigned int *count) 25262306a36Sopenharmony_ci{ 25362306a36Sopenharmony_ci unsigned int i; 25462306a36Sopenharmony_ci int ret; 25562306a36Sopenharmony_ci 25662306a36Sopenharmony_ci for (i = 0; i < msg->len; i++) { 25762306a36Sopenharmony_ci ret = rzv2m_i2c_write_with_ack(priv, msg->buf[i]); 25862306a36Sopenharmony_ci if (ret < 0) 25962306a36Sopenharmony_ci return ret; 26062306a36Sopenharmony_ci } 26162306a36Sopenharmony_ci *count = i; 26262306a36Sopenharmony_ci 26362306a36Sopenharmony_ci return 0; 26462306a36Sopenharmony_ci} 26562306a36Sopenharmony_ci 26662306a36Sopenharmony_cistatic int rzv2m_i2c_receive(struct rzv2m_i2c_priv *priv, struct i2c_msg *msg, 26762306a36Sopenharmony_ci unsigned int *count) 26862306a36Sopenharmony_ci{ 26962306a36Sopenharmony_ci unsigned int i; 27062306a36Sopenharmony_ci int ret; 27162306a36Sopenharmony_ci 27262306a36Sopenharmony_ci for (i = 0; i < msg->len; i++) { 27362306a36Sopenharmony_ci ret = rzv2m_i2c_read_with_ack(priv, &msg->buf[i], 27462306a36Sopenharmony_ci (msg->len - 1) == i); 27562306a36Sopenharmony_ci if (ret < 0) 27662306a36Sopenharmony_ci return ret; 27762306a36Sopenharmony_ci } 27862306a36Sopenharmony_ci *count = i; 27962306a36Sopenharmony_ci 28062306a36Sopenharmony_ci return 0; 28162306a36Sopenharmony_ci} 28262306a36Sopenharmony_ci 28362306a36Sopenharmony_cistatic int rzv2m_i2c_send_address(struct rzv2m_i2c_priv *priv, 28462306a36Sopenharmony_ci struct i2c_msg *msg) 28562306a36Sopenharmony_ci{ 28662306a36Sopenharmony_ci u32 addr; 28762306a36Sopenharmony_ci int ret; 28862306a36Sopenharmony_ci 28962306a36Sopenharmony_ci if (msg->flags & I2C_M_TEN) { 29062306a36Sopenharmony_ci /* 29162306a36Sopenharmony_ci * 10-bit address 29262306a36Sopenharmony_ci * addr_1: 5'b11110 | addr[9:8] | (R/nW) 29362306a36Sopenharmony_ci * addr_2: addr[7:0] 29462306a36Sopenharmony_ci */ 29562306a36Sopenharmony_ci addr = 0xf0 | ((msg->addr & GENMASK(9, 8)) >> 7); 29662306a36Sopenharmony_ci addr |= !!(msg->flags & I2C_M_RD); 29762306a36Sopenharmony_ci /* Send 1st address(extend code) */ 29862306a36Sopenharmony_ci ret = rzv2m_i2c_write_with_ack(priv, addr); 29962306a36Sopenharmony_ci if (ret) 30062306a36Sopenharmony_ci return ret; 30162306a36Sopenharmony_ci 30262306a36Sopenharmony_ci /* Send 2nd address */ 30362306a36Sopenharmony_ci ret = rzv2m_i2c_write_with_ack(priv, msg->addr & 0xff); 30462306a36Sopenharmony_ci } else { 30562306a36Sopenharmony_ci /* 7-bit address */ 30662306a36Sopenharmony_ci addr = i2c_8bit_addr_from_msg(msg); 30762306a36Sopenharmony_ci ret = rzv2m_i2c_write_with_ack(priv, addr); 30862306a36Sopenharmony_ci } 30962306a36Sopenharmony_ci 31062306a36Sopenharmony_ci return ret; 31162306a36Sopenharmony_ci} 31262306a36Sopenharmony_ci 31362306a36Sopenharmony_cistatic int rzv2m_i2c_stop_condition(struct rzv2m_i2c_priv *priv) 31462306a36Sopenharmony_ci{ 31562306a36Sopenharmony_ci u32 value; 31662306a36Sopenharmony_ci 31762306a36Sopenharmony_ci /* Send stop condition */ 31862306a36Sopenharmony_ci writel(IICB0SPT, priv->base + IICB0TRG); 31962306a36Sopenharmony_ci return readl_poll_timeout(priv->base + IICB0STR0, 32062306a36Sopenharmony_ci value, value & IICB0SSSP, 32162306a36Sopenharmony_ci 100, jiffies_to_usecs(priv->adap.timeout)); 32262306a36Sopenharmony_ci} 32362306a36Sopenharmony_ci 32462306a36Sopenharmony_cistatic int rzv2m_i2c_master_xfer_msg(struct rzv2m_i2c_priv *priv, 32562306a36Sopenharmony_ci struct i2c_msg *msg, int stop) 32662306a36Sopenharmony_ci{ 32762306a36Sopenharmony_ci unsigned int count = 0; 32862306a36Sopenharmony_ci int ret, read = !!(msg->flags & I2C_M_RD); 32962306a36Sopenharmony_ci 33062306a36Sopenharmony_ci /* Send start condition */ 33162306a36Sopenharmony_ci writel(IICB0STT, priv->base + IICB0TRG); 33262306a36Sopenharmony_ci 33362306a36Sopenharmony_ci ret = rzv2m_i2c_send_address(priv, msg); 33462306a36Sopenharmony_ci if (!ret) { 33562306a36Sopenharmony_ci if (read) 33662306a36Sopenharmony_ci ret = rzv2m_i2c_receive(priv, msg, &count); 33762306a36Sopenharmony_ci else 33862306a36Sopenharmony_ci ret = rzv2m_i2c_send(priv, msg, &count); 33962306a36Sopenharmony_ci 34062306a36Sopenharmony_ci if (!ret && stop) 34162306a36Sopenharmony_ci ret = rzv2m_i2c_stop_condition(priv); 34262306a36Sopenharmony_ci } 34362306a36Sopenharmony_ci 34462306a36Sopenharmony_ci if (ret == -ENXIO) 34562306a36Sopenharmony_ci rzv2m_i2c_stop_condition(priv); 34662306a36Sopenharmony_ci else if (ret < 0) 34762306a36Sopenharmony_ci rzv2m_i2c_init(priv); 34862306a36Sopenharmony_ci else 34962306a36Sopenharmony_ci ret = count; 35062306a36Sopenharmony_ci 35162306a36Sopenharmony_ci return ret; 35262306a36Sopenharmony_ci} 35362306a36Sopenharmony_ci 35462306a36Sopenharmony_cistatic int rzv2m_i2c_master_xfer(struct i2c_adapter *adap, 35562306a36Sopenharmony_ci struct i2c_msg *msgs, int num) 35662306a36Sopenharmony_ci{ 35762306a36Sopenharmony_ci struct rzv2m_i2c_priv *priv = i2c_get_adapdata(adap); 35862306a36Sopenharmony_ci struct device *dev = priv->adap.dev.parent; 35962306a36Sopenharmony_ci unsigned int i; 36062306a36Sopenharmony_ci int ret; 36162306a36Sopenharmony_ci 36262306a36Sopenharmony_ci ret = pm_runtime_resume_and_get(dev); 36362306a36Sopenharmony_ci if (ret < 0) 36462306a36Sopenharmony_ci return ret; 36562306a36Sopenharmony_ci 36662306a36Sopenharmony_ci if (readl(priv->base + IICB0STR0) & IICB0SSBS) { 36762306a36Sopenharmony_ci ret = -EAGAIN; 36862306a36Sopenharmony_ci goto out; 36962306a36Sopenharmony_ci } 37062306a36Sopenharmony_ci 37162306a36Sopenharmony_ci /* I2C main transfer */ 37262306a36Sopenharmony_ci for (i = 0; i < num; i++) { 37362306a36Sopenharmony_ci ret = rzv2m_i2c_master_xfer_msg(priv, &msgs[i], i == (num - 1)); 37462306a36Sopenharmony_ci if (ret < 0) 37562306a36Sopenharmony_ci goto out; 37662306a36Sopenharmony_ci } 37762306a36Sopenharmony_ci ret = num; 37862306a36Sopenharmony_ci 37962306a36Sopenharmony_ciout: 38062306a36Sopenharmony_ci pm_runtime_mark_last_busy(dev); 38162306a36Sopenharmony_ci pm_runtime_put_autosuspend(dev); 38262306a36Sopenharmony_ci 38362306a36Sopenharmony_ci return ret; 38462306a36Sopenharmony_ci} 38562306a36Sopenharmony_ci 38662306a36Sopenharmony_cistatic u32 rzv2m_i2c_func(struct i2c_adapter *adap) 38762306a36Sopenharmony_ci{ 38862306a36Sopenharmony_ci return I2C_FUNC_I2C | (I2C_FUNC_SMBUS_EMUL & ~I2C_FUNC_SMBUS_QUICK) | 38962306a36Sopenharmony_ci I2C_FUNC_10BIT_ADDR; 39062306a36Sopenharmony_ci} 39162306a36Sopenharmony_ci 39262306a36Sopenharmony_cistatic int rzv2m_i2c_disable(struct device *dev, struct rzv2m_i2c_priv *priv) 39362306a36Sopenharmony_ci{ 39462306a36Sopenharmony_ci int ret; 39562306a36Sopenharmony_ci 39662306a36Sopenharmony_ci ret = pm_runtime_resume_and_get(dev); 39762306a36Sopenharmony_ci if (ret < 0) 39862306a36Sopenharmony_ci return ret; 39962306a36Sopenharmony_ci 40062306a36Sopenharmony_ci bit_clrl(priv->base + IICB0CTL0, IICB0IICE); 40162306a36Sopenharmony_ci pm_runtime_put(dev); 40262306a36Sopenharmony_ci 40362306a36Sopenharmony_ci return 0; 40462306a36Sopenharmony_ci} 40562306a36Sopenharmony_ci 40662306a36Sopenharmony_cistatic const struct i2c_adapter_quirks rzv2m_i2c_quirks = { 40762306a36Sopenharmony_ci .flags = I2C_AQ_NO_ZERO_LEN, 40862306a36Sopenharmony_ci}; 40962306a36Sopenharmony_ci 41062306a36Sopenharmony_cistatic struct i2c_algorithm rzv2m_i2c_algo = { 41162306a36Sopenharmony_ci .master_xfer = rzv2m_i2c_master_xfer, 41262306a36Sopenharmony_ci .functionality = rzv2m_i2c_func, 41362306a36Sopenharmony_ci}; 41462306a36Sopenharmony_ci 41562306a36Sopenharmony_cistatic int rzv2m_i2c_probe(struct platform_device *pdev) 41662306a36Sopenharmony_ci{ 41762306a36Sopenharmony_ci struct device *dev = &pdev->dev; 41862306a36Sopenharmony_ci struct rzv2m_i2c_priv *priv; 41962306a36Sopenharmony_ci struct reset_control *rstc; 42062306a36Sopenharmony_ci struct i2c_adapter *adap; 42162306a36Sopenharmony_ci struct resource *res; 42262306a36Sopenharmony_ci int irq, ret; 42362306a36Sopenharmony_ci 42462306a36Sopenharmony_ci priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); 42562306a36Sopenharmony_ci if (!priv) 42662306a36Sopenharmony_ci return -ENOMEM; 42762306a36Sopenharmony_ci 42862306a36Sopenharmony_ci priv->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); 42962306a36Sopenharmony_ci if (IS_ERR(priv->base)) 43062306a36Sopenharmony_ci return PTR_ERR(priv->base); 43162306a36Sopenharmony_ci 43262306a36Sopenharmony_ci priv->clk = devm_clk_get(dev, NULL); 43362306a36Sopenharmony_ci if (IS_ERR(priv->clk)) 43462306a36Sopenharmony_ci return dev_err_probe(dev, PTR_ERR(priv->clk), "Can't get clock\n"); 43562306a36Sopenharmony_ci 43662306a36Sopenharmony_ci rstc = devm_reset_control_get_shared(dev, NULL); 43762306a36Sopenharmony_ci if (IS_ERR(rstc)) 43862306a36Sopenharmony_ci return dev_err_probe(dev, PTR_ERR(rstc), "Missing reset ctrl\n"); 43962306a36Sopenharmony_ci /* 44062306a36Sopenharmony_ci * The reset also affects other HW that is not under the control 44162306a36Sopenharmony_ci * of Linux. Therefore, all we can do is deassert the reset. 44262306a36Sopenharmony_ci */ 44362306a36Sopenharmony_ci reset_control_deassert(rstc); 44462306a36Sopenharmony_ci 44562306a36Sopenharmony_ci irq = platform_get_irq(pdev, 0); 44662306a36Sopenharmony_ci if (irq < 0) 44762306a36Sopenharmony_ci return irq; 44862306a36Sopenharmony_ci 44962306a36Sopenharmony_ci ret = devm_request_irq(dev, irq, rzv2m_i2c_tia_irq_handler, 0, 45062306a36Sopenharmony_ci dev_name(dev), priv); 45162306a36Sopenharmony_ci if (ret < 0) 45262306a36Sopenharmony_ci return dev_err_probe(dev, ret, "Unable to request irq %d\n", irq); 45362306a36Sopenharmony_ci 45462306a36Sopenharmony_ci adap = &priv->adap; 45562306a36Sopenharmony_ci adap->nr = pdev->id; 45662306a36Sopenharmony_ci adap->algo = &rzv2m_i2c_algo; 45762306a36Sopenharmony_ci adap->quirks = &rzv2m_i2c_quirks; 45862306a36Sopenharmony_ci adap->dev.parent = dev; 45962306a36Sopenharmony_ci adap->owner = THIS_MODULE; 46062306a36Sopenharmony_ci device_set_node(&adap->dev, dev_fwnode(dev)); 46162306a36Sopenharmony_ci i2c_set_adapdata(adap, priv); 46262306a36Sopenharmony_ci strscpy(adap->name, pdev->name, sizeof(adap->name)); 46362306a36Sopenharmony_ci init_completion(&priv->msg_tia_done); 46462306a36Sopenharmony_ci 46562306a36Sopenharmony_ci ret = rzv2m_i2c_clock_calculate(dev, priv); 46662306a36Sopenharmony_ci if (ret < 0) 46762306a36Sopenharmony_ci return ret; 46862306a36Sopenharmony_ci 46962306a36Sopenharmony_ci pm_runtime_enable(dev); 47062306a36Sopenharmony_ci 47162306a36Sopenharmony_ci pm_runtime_get_sync(dev); 47262306a36Sopenharmony_ci rzv2m_i2c_init(priv); 47362306a36Sopenharmony_ci pm_runtime_put(dev); 47462306a36Sopenharmony_ci 47562306a36Sopenharmony_ci platform_set_drvdata(pdev, priv); 47662306a36Sopenharmony_ci 47762306a36Sopenharmony_ci ret = i2c_add_numbered_adapter(adap); 47862306a36Sopenharmony_ci if (ret < 0) { 47962306a36Sopenharmony_ci rzv2m_i2c_disable(dev, priv); 48062306a36Sopenharmony_ci pm_runtime_disable(dev); 48162306a36Sopenharmony_ci } 48262306a36Sopenharmony_ci 48362306a36Sopenharmony_ci return ret; 48462306a36Sopenharmony_ci} 48562306a36Sopenharmony_ci 48662306a36Sopenharmony_cistatic void rzv2m_i2c_remove(struct platform_device *pdev) 48762306a36Sopenharmony_ci{ 48862306a36Sopenharmony_ci struct rzv2m_i2c_priv *priv = platform_get_drvdata(pdev); 48962306a36Sopenharmony_ci struct device *dev = priv->adap.dev.parent; 49062306a36Sopenharmony_ci 49162306a36Sopenharmony_ci i2c_del_adapter(&priv->adap); 49262306a36Sopenharmony_ci rzv2m_i2c_disable(dev, priv); 49362306a36Sopenharmony_ci pm_runtime_disable(dev); 49462306a36Sopenharmony_ci} 49562306a36Sopenharmony_ci 49662306a36Sopenharmony_cistatic int rzv2m_i2c_suspend(struct device *dev) 49762306a36Sopenharmony_ci{ 49862306a36Sopenharmony_ci struct rzv2m_i2c_priv *priv = dev_get_drvdata(dev); 49962306a36Sopenharmony_ci 50062306a36Sopenharmony_ci return rzv2m_i2c_disable(dev, priv); 50162306a36Sopenharmony_ci} 50262306a36Sopenharmony_ci 50362306a36Sopenharmony_cistatic int rzv2m_i2c_resume(struct device *dev) 50462306a36Sopenharmony_ci{ 50562306a36Sopenharmony_ci struct rzv2m_i2c_priv *priv = dev_get_drvdata(dev); 50662306a36Sopenharmony_ci int ret; 50762306a36Sopenharmony_ci 50862306a36Sopenharmony_ci ret = rzv2m_i2c_clock_calculate(dev, priv); 50962306a36Sopenharmony_ci if (ret < 0) 51062306a36Sopenharmony_ci return ret; 51162306a36Sopenharmony_ci 51262306a36Sopenharmony_ci ret = pm_runtime_resume_and_get(dev); 51362306a36Sopenharmony_ci if (ret < 0) 51462306a36Sopenharmony_ci return ret; 51562306a36Sopenharmony_ci 51662306a36Sopenharmony_ci rzv2m_i2c_init(priv); 51762306a36Sopenharmony_ci pm_runtime_put(dev); 51862306a36Sopenharmony_ci 51962306a36Sopenharmony_ci return 0; 52062306a36Sopenharmony_ci} 52162306a36Sopenharmony_ci 52262306a36Sopenharmony_cistatic const struct of_device_id rzv2m_i2c_ids[] = { 52362306a36Sopenharmony_ci { .compatible = "renesas,rzv2m-i2c" }, 52462306a36Sopenharmony_ci { } 52562306a36Sopenharmony_ci}; 52662306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, rzv2m_i2c_ids); 52762306a36Sopenharmony_ci 52862306a36Sopenharmony_cistatic const struct dev_pm_ops rzv2m_i2c_pm_ops = { 52962306a36Sopenharmony_ci SYSTEM_SLEEP_PM_OPS(rzv2m_i2c_suspend, rzv2m_i2c_resume) 53062306a36Sopenharmony_ci}; 53162306a36Sopenharmony_ci 53262306a36Sopenharmony_cistatic struct platform_driver rzv2m_i2c_driver = { 53362306a36Sopenharmony_ci .driver = { 53462306a36Sopenharmony_ci .name = "rzv2m-i2c", 53562306a36Sopenharmony_ci .of_match_table = rzv2m_i2c_ids, 53662306a36Sopenharmony_ci .pm = pm_sleep_ptr(&rzv2m_i2c_pm_ops), 53762306a36Sopenharmony_ci }, 53862306a36Sopenharmony_ci .probe = rzv2m_i2c_probe, 53962306a36Sopenharmony_ci .remove_new = rzv2m_i2c_remove, 54062306a36Sopenharmony_ci}; 54162306a36Sopenharmony_cimodule_platform_driver(rzv2m_i2c_driver); 54262306a36Sopenharmony_ci 54362306a36Sopenharmony_ciMODULE_DESCRIPTION("RZ/V2M I2C bus driver"); 54462306a36Sopenharmony_ciMODULE_AUTHOR("Renesas Electronics Corporation"); 54562306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 546