18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * I2C driver for the Renesas EMEV2 SoC 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (C) 2015 Wolfram Sang <wsa@sang-engineering.com> 68c2ecf20Sopenharmony_ci * Copyright 2013 Codethink Ltd. 78c2ecf20Sopenharmony_ci * Copyright 2010-2015 Renesas Electronics Corporation 88c2ecf20Sopenharmony_ci */ 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_ci#include <linux/clk.h> 118c2ecf20Sopenharmony_ci#include <linux/completion.h> 128c2ecf20Sopenharmony_ci#include <linux/device.h> 138c2ecf20Sopenharmony_ci#include <linux/i2c.h> 148c2ecf20Sopenharmony_ci#include <linux/init.h> 158c2ecf20Sopenharmony_ci#include <linux/interrupt.h> 168c2ecf20Sopenharmony_ci#include <linux/io.h> 178c2ecf20Sopenharmony_ci#include <linux/kernel.h> 188c2ecf20Sopenharmony_ci#include <linux/module.h> 198c2ecf20Sopenharmony_ci#include <linux/of_device.h> 208c2ecf20Sopenharmony_ci#include <linux/platform_device.h> 218c2ecf20Sopenharmony_ci#include <linux/sched.h> 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_ci/* I2C Registers */ 248c2ecf20Sopenharmony_ci#define I2C_OFS_IICACT0 0x00 /* start */ 258c2ecf20Sopenharmony_ci#define I2C_OFS_IIC0 0x04 /* shift */ 268c2ecf20Sopenharmony_ci#define I2C_OFS_IICC0 0x08 /* control */ 278c2ecf20Sopenharmony_ci#define I2C_OFS_SVA0 0x0c /* slave address */ 288c2ecf20Sopenharmony_ci#define I2C_OFS_IICCL0 0x10 /* clock select */ 298c2ecf20Sopenharmony_ci#define I2C_OFS_IICX0 0x14 /* extension */ 308c2ecf20Sopenharmony_ci#define I2C_OFS_IICS0 0x18 /* status */ 318c2ecf20Sopenharmony_ci#define I2C_OFS_IICSE0 0x1c /* status For emulation */ 328c2ecf20Sopenharmony_ci#define I2C_OFS_IICF0 0x20 /* IIC flag */ 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_ci/* I2C IICACT0 Masks */ 358c2ecf20Sopenharmony_ci#define I2C_BIT_IICE0 0x0001 368c2ecf20Sopenharmony_ci 378c2ecf20Sopenharmony_ci/* I2C IICC0 Masks */ 388c2ecf20Sopenharmony_ci#define I2C_BIT_LREL0 0x0040 398c2ecf20Sopenharmony_ci#define I2C_BIT_WREL0 0x0020 408c2ecf20Sopenharmony_ci#define I2C_BIT_SPIE0 0x0010 418c2ecf20Sopenharmony_ci#define I2C_BIT_WTIM0 0x0008 428c2ecf20Sopenharmony_ci#define I2C_BIT_ACKE0 0x0004 438c2ecf20Sopenharmony_ci#define I2C_BIT_STT0 0x0002 448c2ecf20Sopenharmony_ci#define I2C_BIT_SPT0 0x0001 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_ci/* I2C IICCL0 Masks */ 478c2ecf20Sopenharmony_ci#define I2C_BIT_SMC0 0x0008 488c2ecf20Sopenharmony_ci#define I2C_BIT_DFC0 0x0004 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_ci/* I2C IICSE0 Masks */ 518c2ecf20Sopenharmony_ci#define I2C_BIT_MSTS0 0x0080 528c2ecf20Sopenharmony_ci#define I2C_BIT_ALD0 0x0040 538c2ecf20Sopenharmony_ci#define I2C_BIT_EXC0 0x0020 548c2ecf20Sopenharmony_ci#define I2C_BIT_COI0 0x0010 558c2ecf20Sopenharmony_ci#define I2C_BIT_TRC0 0x0008 568c2ecf20Sopenharmony_ci#define I2C_BIT_ACKD0 0x0004 578c2ecf20Sopenharmony_ci#define I2C_BIT_STD0 0x0002 588c2ecf20Sopenharmony_ci#define I2C_BIT_SPD0 0x0001 598c2ecf20Sopenharmony_ci 608c2ecf20Sopenharmony_ci/* I2C IICF0 Masks */ 618c2ecf20Sopenharmony_ci#define I2C_BIT_STCF 0x0080 628c2ecf20Sopenharmony_ci#define I2C_BIT_IICBSY 0x0040 638c2ecf20Sopenharmony_ci#define I2C_BIT_STCEN 0x0002 648c2ecf20Sopenharmony_ci#define I2C_BIT_IICRSV 0x0001 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_cistruct em_i2c_device { 678c2ecf20Sopenharmony_ci void __iomem *base; 688c2ecf20Sopenharmony_ci struct i2c_adapter adap; 698c2ecf20Sopenharmony_ci struct completion msg_done; 708c2ecf20Sopenharmony_ci struct clk *sclk; 718c2ecf20Sopenharmony_ci struct i2c_client *slave; 728c2ecf20Sopenharmony_ci int irq; 738c2ecf20Sopenharmony_ci}; 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_cistatic inline void em_clear_set_bit(struct em_i2c_device *priv, u8 clear, u8 set, u8 reg) 768c2ecf20Sopenharmony_ci{ 778c2ecf20Sopenharmony_ci writeb((readb(priv->base + reg) & ~clear) | set, priv->base + reg); 788c2ecf20Sopenharmony_ci} 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_cistatic int em_i2c_wait_for_event(struct em_i2c_device *priv) 818c2ecf20Sopenharmony_ci{ 828c2ecf20Sopenharmony_ci unsigned long time_left; 838c2ecf20Sopenharmony_ci int status; 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_ci reinit_completion(&priv->msg_done); 868c2ecf20Sopenharmony_ci 878c2ecf20Sopenharmony_ci time_left = wait_for_completion_timeout(&priv->msg_done, priv->adap.timeout); 888c2ecf20Sopenharmony_ci 898c2ecf20Sopenharmony_ci if (!time_left) 908c2ecf20Sopenharmony_ci return -ETIMEDOUT; 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_ci status = readb(priv->base + I2C_OFS_IICSE0); 938c2ecf20Sopenharmony_ci return status & I2C_BIT_ALD0 ? -EAGAIN : status; 948c2ecf20Sopenharmony_ci} 958c2ecf20Sopenharmony_ci 968c2ecf20Sopenharmony_cistatic void em_i2c_stop(struct em_i2c_device *priv) 978c2ecf20Sopenharmony_ci{ 988c2ecf20Sopenharmony_ci /* Send Stop condition */ 998c2ecf20Sopenharmony_ci em_clear_set_bit(priv, 0, I2C_BIT_SPT0 | I2C_BIT_SPIE0, I2C_OFS_IICC0); 1008c2ecf20Sopenharmony_ci 1018c2ecf20Sopenharmony_ci /* Wait for stop condition */ 1028c2ecf20Sopenharmony_ci em_i2c_wait_for_event(priv); 1038c2ecf20Sopenharmony_ci} 1048c2ecf20Sopenharmony_ci 1058c2ecf20Sopenharmony_cistatic void em_i2c_reset(struct i2c_adapter *adap) 1068c2ecf20Sopenharmony_ci{ 1078c2ecf20Sopenharmony_ci struct em_i2c_device *priv = i2c_get_adapdata(adap); 1088c2ecf20Sopenharmony_ci int retr; 1098c2ecf20Sopenharmony_ci 1108c2ecf20Sopenharmony_ci /* If I2C active */ 1118c2ecf20Sopenharmony_ci if (readb(priv->base + I2C_OFS_IICACT0) & I2C_BIT_IICE0) { 1128c2ecf20Sopenharmony_ci /* Disable I2C operation */ 1138c2ecf20Sopenharmony_ci writeb(0, priv->base + I2C_OFS_IICACT0); 1148c2ecf20Sopenharmony_ci 1158c2ecf20Sopenharmony_ci retr = 1000; 1168c2ecf20Sopenharmony_ci while (readb(priv->base + I2C_OFS_IICACT0) == 1 && retr) 1178c2ecf20Sopenharmony_ci retr--; 1188c2ecf20Sopenharmony_ci WARN_ON(retr == 0); 1198c2ecf20Sopenharmony_ci } 1208c2ecf20Sopenharmony_ci 1218c2ecf20Sopenharmony_ci /* Transfer mode set */ 1228c2ecf20Sopenharmony_ci writeb(I2C_BIT_DFC0, priv->base + I2C_OFS_IICCL0); 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_ci /* Can Issue start without detecting a stop, Reservation disabled. */ 1258c2ecf20Sopenharmony_ci writeb(I2C_BIT_STCEN | I2C_BIT_IICRSV, priv->base + I2C_OFS_IICF0); 1268c2ecf20Sopenharmony_ci 1278c2ecf20Sopenharmony_ci /* I2C enable, 9 bit interrupt mode */ 1288c2ecf20Sopenharmony_ci writeb(I2C_BIT_WTIM0, priv->base + I2C_OFS_IICC0); 1298c2ecf20Sopenharmony_ci 1308c2ecf20Sopenharmony_ci /* Enable I2C operation */ 1318c2ecf20Sopenharmony_ci writeb(I2C_BIT_IICE0, priv->base + I2C_OFS_IICACT0); 1328c2ecf20Sopenharmony_ci 1338c2ecf20Sopenharmony_ci retr = 1000; 1348c2ecf20Sopenharmony_ci while (readb(priv->base + I2C_OFS_IICACT0) == 0 && retr) 1358c2ecf20Sopenharmony_ci retr--; 1368c2ecf20Sopenharmony_ci WARN_ON(retr == 0); 1378c2ecf20Sopenharmony_ci} 1388c2ecf20Sopenharmony_ci 1398c2ecf20Sopenharmony_cistatic int __em_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msg, 1408c2ecf20Sopenharmony_ci int stop) 1418c2ecf20Sopenharmony_ci{ 1428c2ecf20Sopenharmony_ci struct em_i2c_device *priv = i2c_get_adapdata(adap); 1438c2ecf20Sopenharmony_ci int count, status, read = !!(msg->flags & I2C_M_RD); 1448c2ecf20Sopenharmony_ci 1458c2ecf20Sopenharmony_ci /* Send start condition */ 1468c2ecf20Sopenharmony_ci em_clear_set_bit(priv, 0, I2C_BIT_ACKE0 | I2C_BIT_WTIM0, I2C_OFS_IICC0); 1478c2ecf20Sopenharmony_ci em_clear_set_bit(priv, 0, I2C_BIT_STT0, I2C_OFS_IICC0); 1488c2ecf20Sopenharmony_ci 1498c2ecf20Sopenharmony_ci /* Send slave address and R/W type */ 1508c2ecf20Sopenharmony_ci writeb(i2c_8bit_addr_from_msg(msg), priv->base + I2C_OFS_IIC0); 1518c2ecf20Sopenharmony_ci 1528c2ecf20Sopenharmony_ci /* Wait for transaction */ 1538c2ecf20Sopenharmony_ci status = em_i2c_wait_for_event(priv); 1548c2ecf20Sopenharmony_ci if (status < 0) 1558c2ecf20Sopenharmony_ci goto out_reset; 1568c2ecf20Sopenharmony_ci 1578c2ecf20Sopenharmony_ci /* Received NACK (result of setting slave address and R/W) */ 1588c2ecf20Sopenharmony_ci if (!(status & I2C_BIT_ACKD0)) { 1598c2ecf20Sopenharmony_ci em_i2c_stop(priv); 1608c2ecf20Sopenharmony_ci goto out; 1618c2ecf20Sopenharmony_ci } 1628c2ecf20Sopenharmony_ci 1638c2ecf20Sopenharmony_ci /* Extra setup for read transactions */ 1648c2ecf20Sopenharmony_ci if (read) { 1658c2ecf20Sopenharmony_ci /* 8 bit interrupt mode */ 1668c2ecf20Sopenharmony_ci em_clear_set_bit(priv, I2C_BIT_WTIM0, I2C_BIT_ACKE0, I2C_OFS_IICC0); 1678c2ecf20Sopenharmony_ci em_clear_set_bit(priv, I2C_BIT_WTIM0, I2C_BIT_WREL0, I2C_OFS_IICC0); 1688c2ecf20Sopenharmony_ci 1698c2ecf20Sopenharmony_ci /* Wait for transaction */ 1708c2ecf20Sopenharmony_ci status = em_i2c_wait_for_event(priv); 1718c2ecf20Sopenharmony_ci if (status < 0) 1728c2ecf20Sopenharmony_ci goto out_reset; 1738c2ecf20Sopenharmony_ci } 1748c2ecf20Sopenharmony_ci 1758c2ecf20Sopenharmony_ci /* Send / receive data */ 1768c2ecf20Sopenharmony_ci for (count = 0; count < msg->len; count++) { 1778c2ecf20Sopenharmony_ci if (read) { /* Read transaction */ 1788c2ecf20Sopenharmony_ci msg->buf[count] = readb(priv->base + I2C_OFS_IIC0); 1798c2ecf20Sopenharmony_ci em_clear_set_bit(priv, 0, I2C_BIT_WREL0, I2C_OFS_IICC0); 1808c2ecf20Sopenharmony_ci 1818c2ecf20Sopenharmony_ci } else { /* Write transaction */ 1828c2ecf20Sopenharmony_ci /* Received NACK */ 1838c2ecf20Sopenharmony_ci if (!(status & I2C_BIT_ACKD0)) { 1848c2ecf20Sopenharmony_ci em_i2c_stop(priv); 1858c2ecf20Sopenharmony_ci goto out; 1868c2ecf20Sopenharmony_ci } 1878c2ecf20Sopenharmony_ci 1888c2ecf20Sopenharmony_ci /* Write data */ 1898c2ecf20Sopenharmony_ci writeb(msg->buf[count], priv->base + I2C_OFS_IIC0); 1908c2ecf20Sopenharmony_ci } 1918c2ecf20Sopenharmony_ci 1928c2ecf20Sopenharmony_ci /* Wait for R/W transaction */ 1938c2ecf20Sopenharmony_ci status = em_i2c_wait_for_event(priv); 1948c2ecf20Sopenharmony_ci if (status < 0) 1958c2ecf20Sopenharmony_ci goto out_reset; 1968c2ecf20Sopenharmony_ci } 1978c2ecf20Sopenharmony_ci 1988c2ecf20Sopenharmony_ci if (stop) 1998c2ecf20Sopenharmony_ci em_i2c_stop(priv); 2008c2ecf20Sopenharmony_ci 2018c2ecf20Sopenharmony_ci return count; 2028c2ecf20Sopenharmony_ci 2038c2ecf20Sopenharmony_ciout_reset: 2048c2ecf20Sopenharmony_ci em_i2c_reset(adap); 2058c2ecf20Sopenharmony_ciout: 2068c2ecf20Sopenharmony_ci return status < 0 ? status : -ENXIO; 2078c2ecf20Sopenharmony_ci} 2088c2ecf20Sopenharmony_ci 2098c2ecf20Sopenharmony_cistatic int em_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, 2108c2ecf20Sopenharmony_ci int num) 2118c2ecf20Sopenharmony_ci{ 2128c2ecf20Sopenharmony_ci struct em_i2c_device *priv = i2c_get_adapdata(adap); 2138c2ecf20Sopenharmony_ci int ret, i; 2148c2ecf20Sopenharmony_ci 2158c2ecf20Sopenharmony_ci if (readb(priv->base + I2C_OFS_IICF0) & I2C_BIT_IICBSY) 2168c2ecf20Sopenharmony_ci return -EAGAIN; 2178c2ecf20Sopenharmony_ci 2188c2ecf20Sopenharmony_ci for (i = 0; i < num; i++) { 2198c2ecf20Sopenharmony_ci ret = __em_i2c_xfer(adap, &msgs[i], (i == (num - 1))); 2208c2ecf20Sopenharmony_ci if (ret < 0) 2218c2ecf20Sopenharmony_ci return ret; 2228c2ecf20Sopenharmony_ci } 2238c2ecf20Sopenharmony_ci 2248c2ecf20Sopenharmony_ci /* I2C transfer completed */ 2258c2ecf20Sopenharmony_ci return num; 2268c2ecf20Sopenharmony_ci} 2278c2ecf20Sopenharmony_ci 2288c2ecf20Sopenharmony_cistatic bool em_i2c_slave_irq(struct em_i2c_device *priv) 2298c2ecf20Sopenharmony_ci{ 2308c2ecf20Sopenharmony_ci u8 status, value; 2318c2ecf20Sopenharmony_ci enum i2c_slave_event event; 2328c2ecf20Sopenharmony_ci int ret; 2338c2ecf20Sopenharmony_ci 2348c2ecf20Sopenharmony_ci if (!priv->slave) 2358c2ecf20Sopenharmony_ci return false; 2368c2ecf20Sopenharmony_ci 2378c2ecf20Sopenharmony_ci status = readb(priv->base + I2C_OFS_IICSE0); 2388c2ecf20Sopenharmony_ci 2398c2ecf20Sopenharmony_ci /* Extension code, do not participate */ 2408c2ecf20Sopenharmony_ci if (status & I2C_BIT_EXC0) { 2418c2ecf20Sopenharmony_ci em_clear_set_bit(priv, 0, I2C_BIT_LREL0, I2C_OFS_IICC0); 2428c2ecf20Sopenharmony_ci return true; 2438c2ecf20Sopenharmony_ci } 2448c2ecf20Sopenharmony_ci 2458c2ecf20Sopenharmony_ci /* Stop detected, we don't know if it's for slave or master */ 2468c2ecf20Sopenharmony_ci if (status & I2C_BIT_SPD0) { 2478c2ecf20Sopenharmony_ci /* Notify slave device */ 2488c2ecf20Sopenharmony_ci i2c_slave_event(priv->slave, I2C_SLAVE_STOP, &value); 2498c2ecf20Sopenharmony_ci /* Pretend we did not handle the interrupt */ 2508c2ecf20Sopenharmony_ci return false; 2518c2ecf20Sopenharmony_ci } 2528c2ecf20Sopenharmony_ci 2538c2ecf20Sopenharmony_ci /* Only handle interrupts addressed to us */ 2548c2ecf20Sopenharmony_ci if (!(status & I2C_BIT_COI0)) 2558c2ecf20Sopenharmony_ci return false; 2568c2ecf20Sopenharmony_ci 2578c2ecf20Sopenharmony_ci /* Enable stop interrupts */ 2588c2ecf20Sopenharmony_ci em_clear_set_bit(priv, 0, I2C_BIT_SPIE0, I2C_OFS_IICC0); 2598c2ecf20Sopenharmony_ci 2608c2ecf20Sopenharmony_ci /* Transmission or Reception */ 2618c2ecf20Sopenharmony_ci if (status & I2C_BIT_TRC0) { 2628c2ecf20Sopenharmony_ci if (status & I2C_BIT_ACKD0) { 2638c2ecf20Sopenharmony_ci /* 9 bit interrupt mode */ 2648c2ecf20Sopenharmony_ci em_clear_set_bit(priv, 0, I2C_BIT_WTIM0, I2C_OFS_IICC0); 2658c2ecf20Sopenharmony_ci 2668c2ecf20Sopenharmony_ci /* Send data */ 2678c2ecf20Sopenharmony_ci event = status & I2C_BIT_STD0 ? 2688c2ecf20Sopenharmony_ci I2C_SLAVE_READ_REQUESTED : 2698c2ecf20Sopenharmony_ci I2C_SLAVE_READ_PROCESSED; 2708c2ecf20Sopenharmony_ci i2c_slave_event(priv->slave, event, &value); 2718c2ecf20Sopenharmony_ci writeb(value, priv->base + I2C_OFS_IIC0); 2728c2ecf20Sopenharmony_ci } else { 2738c2ecf20Sopenharmony_ci /* NACK, stop transmitting */ 2748c2ecf20Sopenharmony_ci em_clear_set_bit(priv, 0, I2C_BIT_LREL0, I2C_OFS_IICC0); 2758c2ecf20Sopenharmony_ci } 2768c2ecf20Sopenharmony_ci } else { 2778c2ecf20Sopenharmony_ci /* 8 bit interrupt mode */ 2788c2ecf20Sopenharmony_ci em_clear_set_bit(priv, I2C_BIT_WTIM0, I2C_BIT_ACKE0, 2798c2ecf20Sopenharmony_ci I2C_OFS_IICC0); 2808c2ecf20Sopenharmony_ci em_clear_set_bit(priv, I2C_BIT_WTIM0, I2C_BIT_WREL0, 2818c2ecf20Sopenharmony_ci I2C_OFS_IICC0); 2828c2ecf20Sopenharmony_ci 2838c2ecf20Sopenharmony_ci if (status & I2C_BIT_STD0) { 2848c2ecf20Sopenharmony_ci i2c_slave_event(priv->slave, I2C_SLAVE_WRITE_REQUESTED, 2858c2ecf20Sopenharmony_ci &value); 2868c2ecf20Sopenharmony_ci } else { 2878c2ecf20Sopenharmony_ci /* Recv data */ 2888c2ecf20Sopenharmony_ci value = readb(priv->base + I2C_OFS_IIC0); 2898c2ecf20Sopenharmony_ci ret = i2c_slave_event(priv->slave, 2908c2ecf20Sopenharmony_ci I2C_SLAVE_WRITE_RECEIVED, &value); 2918c2ecf20Sopenharmony_ci if (ret < 0) 2928c2ecf20Sopenharmony_ci em_clear_set_bit(priv, I2C_BIT_ACKE0, 0, 2938c2ecf20Sopenharmony_ci I2C_OFS_IICC0); 2948c2ecf20Sopenharmony_ci } 2958c2ecf20Sopenharmony_ci } 2968c2ecf20Sopenharmony_ci 2978c2ecf20Sopenharmony_ci return true; 2988c2ecf20Sopenharmony_ci} 2998c2ecf20Sopenharmony_ci 3008c2ecf20Sopenharmony_cistatic irqreturn_t em_i2c_irq_handler(int this_irq, void *dev_id) 3018c2ecf20Sopenharmony_ci{ 3028c2ecf20Sopenharmony_ci struct em_i2c_device *priv = dev_id; 3038c2ecf20Sopenharmony_ci 3048c2ecf20Sopenharmony_ci if (em_i2c_slave_irq(priv)) 3058c2ecf20Sopenharmony_ci return IRQ_HANDLED; 3068c2ecf20Sopenharmony_ci 3078c2ecf20Sopenharmony_ci complete(&priv->msg_done); 3088c2ecf20Sopenharmony_ci 3098c2ecf20Sopenharmony_ci return IRQ_HANDLED; 3108c2ecf20Sopenharmony_ci} 3118c2ecf20Sopenharmony_ci 3128c2ecf20Sopenharmony_cistatic u32 em_i2c_func(struct i2c_adapter *adap) 3138c2ecf20Sopenharmony_ci{ 3148c2ecf20Sopenharmony_ci return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_SLAVE; 3158c2ecf20Sopenharmony_ci} 3168c2ecf20Sopenharmony_ci 3178c2ecf20Sopenharmony_cistatic int em_i2c_reg_slave(struct i2c_client *slave) 3188c2ecf20Sopenharmony_ci{ 3198c2ecf20Sopenharmony_ci struct em_i2c_device *priv = i2c_get_adapdata(slave->adapter); 3208c2ecf20Sopenharmony_ci 3218c2ecf20Sopenharmony_ci if (priv->slave) 3228c2ecf20Sopenharmony_ci return -EBUSY; 3238c2ecf20Sopenharmony_ci 3248c2ecf20Sopenharmony_ci if (slave->flags & I2C_CLIENT_TEN) 3258c2ecf20Sopenharmony_ci return -EAFNOSUPPORT; 3268c2ecf20Sopenharmony_ci 3278c2ecf20Sopenharmony_ci priv->slave = slave; 3288c2ecf20Sopenharmony_ci 3298c2ecf20Sopenharmony_ci /* Set slave address */ 3308c2ecf20Sopenharmony_ci writeb(slave->addr << 1, priv->base + I2C_OFS_SVA0); 3318c2ecf20Sopenharmony_ci 3328c2ecf20Sopenharmony_ci return 0; 3338c2ecf20Sopenharmony_ci} 3348c2ecf20Sopenharmony_ci 3358c2ecf20Sopenharmony_cistatic int em_i2c_unreg_slave(struct i2c_client *slave) 3368c2ecf20Sopenharmony_ci{ 3378c2ecf20Sopenharmony_ci struct em_i2c_device *priv = i2c_get_adapdata(slave->adapter); 3388c2ecf20Sopenharmony_ci 3398c2ecf20Sopenharmony_ci WARN_ON(!priv->slave); 3408c2ecf20Sopenharmony_ci 3418c2ecf20Sopenharmony_ci writeb(0, priv->base + I2C_OFS_SVA0); 3428c2ecf20Sopenharmony_ci 3438c2ecf20Sopenharmony_ci /* 3448c2ecf20Sopenharmony_ci * Wait for interrupt to finish. New slave irqs cannot happen because we 3458c2ecf20Sopenharmony_ci * cleared the slave address and, thus, only extension codes will be 3468c2ecf20Sopenharmony_ci * detected which do not use the slave ptr. 3478c2ecf20Sopenharmony_ci */ 3488c2ecf20Sopenharmony_ci synchronize_irq(priv->irq); 3498c2ecf20Sopenharmony_ci priv->slave = NULL; 3508c2ecf20Sopenharmony_ci 3518c2ecf20Sopenharmony_ci return 0; 3528c2ecf20Sopenharmony_ci} 3538c2ecf20Sopenharmony_ci 3548c2ecf20Sopenharmony_cistatic const struct i2c_algorithm em_i2c_algo = { 3558c2ecf20Sopenharmony_ci .master_xfer = em_i2c_xfer, 3568c2ecf20Sopenharmony_ci .functionality = em_i2c_func, 3578c2ecf20Sopenharmony_ci .reg_slave = em_i2c_reg_slave, 3588c2ecf20Sopenharmony_ci .unreg_slave = em_i2c_unreg_slave, 3598c2ecf20Sopenharmony_ci}; 3608c2ecf20Sopenharmony_ci 3618c2ecf20Sopenharmony_cistatic int em_i2c_probe(struct platform_device *pdev) 3628c2ecf20Sopenharmony_ci{ 3638c2ecf20Sopenharmony_ci struct em_i2c_device *priv; 3648c2ecf20Sopenharmony_ci int ret; 3658c2ecf20Sopenharmony_ci 3668c2ecf20Sopenharmony_ci priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); 3678c2ecf20Sopenharmony_ci if (!priv) 3688c2ecf20Sopenharmony_ci return -ENOMEM; 3698c2ecf20Sopenharmony_ci 3708c2ecf20Sopenharmony_ci priv->base = devm_platform_ioremap_resource(pdev, 0); 3718c2ecf20Sopenharmony_ci if (IS_ERR(priv->base)) 3728c2ecf20Sopenharmony_ci return PTR_ERR(priv->base); 3738c2ecf20Sopenharmony_ci 3748c2ecf20Sopenharmony_ci strlcpy(priv->adap.name, "EMEV2 I2C", sizeof(priv->adap.name)); 3758c2ecf20Sopenharmony_ci 3768c2ecf20Sopenharmony_ci priv->sclk = devm_clk_get(&pdev->dev, "sclk"); 3778c2ecf20Sopenharmony_ci if (IS_ERR(priv->sclk)) 3788c2ecf20Sopenharmony_ci return PTR_ERR(priv->sclk); 3798c2ecf20Sopenharmony_ci 3808c2ecf20Sopenharmony_ci ret = clk_prepare_enable(priv->sclk); 3818c2ecf20Sopenharmony_ci if (ret) 3828c2ecf20Sopenharmony_ci return ret; 3838c2ecf20Sopenharmony_ci 3848c2ecf20Sopenharmony_ci priv->adap.timeout = msecs_to_jiffies(100); 3858c2ecf20Sopenharmony_ci priv->adap.retries = 5; 3868c2ecf20Sopenharmony_ci priv->adap.dev.parent = &pdev->dev; 3878c2ecf20Sopenharmony_ci priv->adap.algo = &em_i2c_algo; 3888c2ecf20Sopenharmony_ci priv->adap.owner = THIS_MODULE; 3898c2ecf20Sopenharmony_ci priv->adap.dev.of_node = pdev->dev.of_node; 3908c2ecf20Sopenharmony_ci 3918c2ecf20Sopenharmony_ci init_completion(&priv->msg_done); 3928c2ecf20Sopenharmony_ci 3938c2ecf20Sopenharmony_ci platform_set_drvdata(pdev, priv); 3948c2ecf20Sopenharmony_ci i2c_set_adapdata(&priv->adap, priv); 3958c2ecf20Sopenharmony_ci 3968c2ecf20Sopenharmony_ci em_i2c_reset(&priv->adap); 3978c2ecf20Sopenharmony_ci 3988c2ecf20Sopenharmony_ci ret = platform_get_irq(pdev, 0); 3998c2ecf20Sopenharmony_ci if (ret < 0) 4008c2ecf20Sopenharmony_ci goto err_clk; 4018c2ecf20Sopenharmony_ci priv->irq = ret; 4028c2ecf20Sopenharmony_ci ret = devm_request_irq(&pdev->dev, priv->irq, em_i2c_irq_handler, 0, 4038c2ecf20Sopenharmony_ci "em_i2c", priv); 4048c2ecf20Sopenharmony_ci if (ret) 4058c2ecf20Sopenharmony_ci goto err_clk; 4068c2ecf20Sopenharmony_ci 4078c2ecf20Sopenharmony_ci ret = i2c_add_adapter(&priv->adap); 4088c2ecf20Sopenharmony_ci 4098c2ecf20Sopenharmony_ci if (ret) 4108c2ecf20Sopenharmony_ci goto err_clk; 4118c2ecf20Sopenharmony_ci 4128c2ecf20Sopenharmony_ci dev_info(&pdev->dev, "Added i2c controller %d, irq %d\n", priv->adap.nr, 4138c2ecf20Sopenharmony_ci priv->irq); 4148c2ecf20Sopenharmony_ci 4158c2ecf20Sopenharmony_ci return 0; 4168c2ecf20Sopenharmony_ci 4178c2ecf20Sopenharmony_cierr_clk: 4188c2ecf20Sopenharmony_ci clk_disable_unprepare(priv->sclk); 4198c2ecf20Sopenharmony_ci return ret; 4208c2ecf20Sopenharmony_ci} 4218c2ecf20Sopenharmony_ci 4228c2ecf20Sopenharmony_cistatic int em_i2c_remove(struct platform_device *dev) 4238c2ecf20Sopenharmony_ci{ 4248c2ecf20Sopenharmony_ci struct em_i2c_device *priv = platform_get_drvdata(dev); 4258c2ecf20Sopenharmony_ci 4268c2ecf20Sopenharmony_ci i2c_del_adapter(&priv->adap); 4278c2ecf20Sopenharmony_ci clk_disable_unprepare(priv->sclk); 4288c2ecf20Sopenharmony_ci 4298c2ecf20Sopenharmony_ci return 0; 4308c2ecf20Sopenharmony_ci} 4318c2ecf20Sopenharmony_ci 4328c2ecf20Sopenharmony_cistatic const struct of_device_id em_i2c_ids[] = { 4338c2ecf20Sopenharmony_ci { .compatible = "renesas,iic-emev2", }, 4348c2ecf20Sopenharmony_ci { } 4358c2ecf20Sopenharmony_ci}; 4368c2ecf20Sopenharmony_ci 4378c2ecf20Sopenharmony_cistatic struct platform_driver em_i2c_driver = { 4388c2ecf20Sopenharmony_ci .probe = em_i2c_probe, 4398c2ecf20Sopenharmony_ci .remove = em_i2c_remove, 4408c2ecf20Sopenharmony_ci .driver = { 4418c2ecf20Sopenharmony_ci .name = "em-i2c", 4428c2ecf20Sopenharmony_ci .of_match_table = em_i2c_ids, 4438c2ecf20Sopenharmony_ci } 4448c2ecf20Sopenharmony_ci}; 4458c2ecf20Sopenharmony_cimodule_platform_driver(em_i2c_driver); 4468c2ecf20Sopenharmony_ci 4478c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("EMEV2 I2C bus driver"); 4488c2ecf20Sopenharmony_ciMODULE_AUTHOR("Ian Molton"); 4498c2ecf20Sopenharmony_ciMODULE_AUTHOR("Wolfram Sang <wsa@sang-engineering.com>"); 4508c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL v2"); 4518c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(of, em_i2c_ids); 452