18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Renesas RIIC driver 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (C) 2013 Wolfram Sang <wsa@sang-engineering.com> 68c2ecf20Sopenharmony_ci * Copyright (C) 2013 Renesas Solutions Corp. 78c2ecf20Sopenharmony_ci */ 88c2ecf20Sopenharmony_ci 98c2ecf20Sopenharmony_ci/* 108c2ecf20Sopenharmony_ci * This i2c core has a lot of interrupts, namely 8. We use their chaining as 118c2ecf20Sopenharmony_ci * some kind of state machine. 128c2ecf20Sopenharmony_ci * 138c2ecf20Sopenharmony_ci * 1) The main xfer routine kicks off a transmission by putting the start bit 148c2ecf20Sopenharmony_ci * (or repeated start) on the bus and enabling the transmit interrupt (TIE) 158c2ecf20Sopenharmony_ci * since we need to send the slave address + RW bit in every case. 168c2ecf20Sopenharmony_ci * 178c2ecf20Sopenharmony_ci * 2) TIE sends slave address + RW bit and selects how to continue. 188c2ecf20Sopenharmony_ci * 198c2ecf20Sopenharmony_ci * 3a) Write case: We keep utilizing TIE as long as we have data to send. If we 208c2ecf20Sopenharmony_ci * are done, we switch over to the transmission done interrupt (TEIE) and mark 218c2ecf20Sopenharmony_ci * the message as completed (includes sending STOP) there. 228c2ecf20Sopenharmony_ci * 238c2ecf20Sopenharmony_ci * 3b) Read case: We switch over to receive interrupt (RIE). One dummy read is 248c2ecf20Sopenharmony_ci * needed to start clocking, then we keep receiving until we are done. Note 258c2ecf20Sopenharmony_ci * that we use the RDRFS mode all the time, i.e. we ACK/NACK every byte by 268c2ecf20Sopenharmony_ci * writing to the ACKBT bit. I tried using the RDRFS mode only at the end of a 278c2ecf20Sopenharmony_ci * message to create the final NACK as sketched in the datasheet. This caused 288c2ecf20Sopenharmony_ci * some subtle races (when byte n was processed and byte n+1 was already 298c2ecf20Sopenharmony_ci * waiting), though, and I started with the safe approach. 308c2ecf20Sopenharmony_ci * 318c2ecf20Sopenharmony_ci * 4) If we got a NACK somewhere, we flag the error and stop the transmission 328c2ecf20Sopenharmony_ci * via NAKIE. 338c2ecf20Sopenharmony_ci * 348c2ecf20Sopenharmony_ci * Also check the comments in the interrupt routines for some gory details. 358c2ecf20Sopenharmony_ci */ 368c2ecf20Sopenharmony_ci 378c2ecf20Sopenharmony_ci#include <linux/clk.h> 388c2ecf20Sopenharmony_ci#include <linux/completion.h> 398c2ecf20Sopenharmony_ci#include <linux/err.h> 408c2ecf20Sopenharmony_ci#include <linux/i2c.h> 418c2ecf20Sopenharmony_ci#include <linux/interrupt.h> 428c2ecf20Sopenharmony_ci#include <linux/io.h> 438c2ecf20Sopenharmony_ci#include <linux/module.h> 448c2ecf20Sopenharmony_ci#include <linux/of.h> 458c2ecf20Sopenharmony_ci#include <linux/platform_device.h> 468c2ecf20Sopenharmony_ci#include <linux/pm_runtime.h> 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_ci#define RIIC_ICCR1 0x00 498c2ecf20Sopenharmony_ci#define RIIC_ICCR2 0x04 508c2ecf20Sopenharmony_ci#define RIIC_ICMR1 0x08 518c2ecf20Sopenharmony_ci#define RIIC_ICMR3 0x10 528c2ecf20Sopenharmony_ci#define RIIC_ICSER 0x18 538c2ecf20Sopenharmony_ci#define RIIC_ICIER 0x1c 548c2ecf20Sopenharmony_ci#define RIIC_ICSR2 0x24 558c2ecf20Sopenharmony_ci#define RIIC_ICBRL 0x34 568c2ecf20Sopenharmony_ci#define RIIC_ICBRH 0x38 578c2ecf20Sopenharmony_ci#define RIIC_ICDRT 0x3c 588c2ecf20Sopenharmony_ci#define RIIC_ICDRR 0x40 598c2ecf20Sopenharmony_ci 608c2ecf20Sopenharmony_ci#define ICCR1_ICE 0x80 618c2ecf20Sopenharmony_ci#define ICCR1_IICRST 0x40 628c2ecf20Sopenharmony_ci#define ICCR1_SOWP 0x10 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_ci#define ICCR2_BBSY 0x80 658c2ecf20Sopenharmony_ci#define ICCR2_SP 0x08 668c2ecf20Sopenharmony_ci#define ICCR2_RS 0x04 678c2ecf20Sopenharmony_ci#define ICCR2_ST 0x02 688c2ecf20Sopenharmony_ci 698c2ecf20Sopenharmony_ci#define ICMR1_CKS_MASK 0x70 708c2ecf20Sopenharmony_ci#define ICMR1_BCWP 0x08 718c2ecf20Sopenharmony_ci#define ICMR1_CKS(_x) ((((_x) << 4) & ICMR1_CKS_MASK) | ICMR1_BCWP) 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_ci#define ICMR3_RDRFS 0x20 748c2ecf20Sopenharmony_ci#define ICMR3_ACKWP 0x10 758c2ecf20Sopenharmony_ci#define ICMR3_ACKBT 0x08 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_ci#define ICIER_TIE 0x80 788c2ecf20Sopenharmony_ci#define ICIER_TEIE 0x40 798c2ecf20Sopenharmony_ci#define ICIER_RIE 0x20 808c2ecf20Sopenharmony_ci#define ICIER_NAKIE 0x10 818c2ecf20Sopenharmony_ci#define ICIER_SPIE 0x08 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_ci#define ICSR2_NACKF 0x10 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_ci#define ICBR_RESERVED 0xe0 /* Should be 1 on writes */ 868c2ecf20Sopenharmony_ci 878c2ecf20Sopenharmony_ci#define RIIC_INIT_MSG -1 888c2ecf20Sopenharmony_ci 898c2ecf20Sopenharmony_cistruct riic_dev { 908c2ecf20Sopenharmony_ci void __iomem *base; 918c2ecf20Sopenharmony_ci u8 *buf; 928c2ecf20Sopenharmony_ci struct i2c_msg *msg; 938c2ecf20Sopenharmony_ci int bytes_left; 948c2ecf20Sopenharmony_ci int err; 958c2ecf20Sopenharmony_ci int is_last; 968c2ecf20Sopenharmony_ci struct completion msg_done; 978c2ecf20Sopenharmony_ci struct i2c_adapter adapter; 988c2ecf20Sopenharmony_ci struct clk *clk; 998c2ecf20Sopenharmony_ci}; 1008c2ecf20Sopenharmony_ci 1018c2ecf20Sopenharmony_cistruct riic_irq_desc { 1028c2ecf20Sopenharmony_ci int res_num; 1038c2ecf20Sopenharmony_ci irq_handler_t isr; 1048c2ecf20Sopenharmony_ci char *name; 1058c2ecf20Sopenharmony_ci}; 1068c2ecf20Sopenharmony_ci 1078c2ecf20Sopenharmony_cistatic inline void riic_clear_set_bit(struct riic_dev *riic, u8 clear, u8 set, u8 reg) 1088c2ecf20Sopenharmony_ci{ 1098c2ecf20Sopenharmony_ci writeb((readb(riic->base + reg) & ~clear) | set, riic->base + reg); 1108c2ecf20Sopenharmony_ci} 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_cistatic int riic_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) 1138c2ecf20Sopenharmony_ci{ 1148c2ecf20Sopenharmony_ci struct riic_dev *riic = i2c_get_adapdata(adap); 1158c2ecf20Sopenharmony_ci unsigned long time_left; 1168c2ecf20Sopenharmony_ci int i; 1178c2ecf20Sopenharmony_ci u8 start_bit; 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_ci pm_runtime_get_sync(adap->dev.parent); 1208c2ecf20Sopenharmony_ci 1218c2ecf20Sopenharmony_ci if (readb(riic->base + RIIC_ICCR2) & ICCR2_BBSY) { 1228c2ecf20Sopenharmony_ci riic->err = -EBUSY; 1238c2ecf20Sopenharmony_ci goto out; 1248c2ecf20Sopenharmony_ci } 1258c2ecf20Sopenharmony_ci 1268c2ecf20Sopenharmony_ci reinit_completion(&riic->msg_done); 1278c2ecf20Sopenharmony_ci riic->err = 0; 1288c2ecf20Sopenharmony_ci 1298c2ecf20Sopenharmony_ci writeb(0, riic->base + RIIC_ICSR2); 1308c2ecf20Sopenharmony_ci 1318c2ecf20Sopenharmony_ci for (i = 0, start_bit = ICCR2_ST; i < num; i++) { 1328c2ecf20Sopenharmony_ci riic->bytes_left = RIIC_INIT_MSG; 1338c2ecf20Sopenharmony_ci riic->buf = msgs[i].buf; 1348c2ecf20Sopenharmony_ci riic->msg = &msgs[i]; 1358c2ecf20Sopenharmony_ci riic->is_last = (i == num - 1); 1368c2ecf20Sopenharmony_ci 1378c2ecf20Sopenharmony_ci writeb(ICIER_NAKIE | ICIER_TIE, riic->base + RIIC_ICIER); 1388c2ecf20Sopenharmony_ci 1398c2ecf20Sopenharmony_ci writeb(start_bit, riic->base + RIIC_ICCR2); 1408c2ecf20Sopenharmony_ci 1418c2ecf20Sopenharmony_ci time_left = wait_for_completion_timeout(&riic->msg_done, riic->adapter.timeout); 1428c2ecf20Sopenharmony_ci if (time_left == 0) 1438c2ecf20Sopenharmony_ci riic->err = -ETIMEDOUT; 1448c2ecf20Sopenharmony_ci 1458c2ecf20Sopenharmony_ci if (riic->err) 1468c2ecf20Sopenharmony_ci break; 1478c2ecf20Sopenharmony_ci 1488c2ecf20Sopenharmony_ci start_bit = ICCR2_RS; 1498c2ecf20Sopenharmony_ci } 1508c2ecf20Sopenharmony_ci 1518c2ecf20Sopenharmony_ci out: 1528c2ecf20Sopenharmony_ci pm_runtime_put(adap->dev.parent); 1538c2ecf20Sopenharmony_ci 1548c2ecf20Sopenharmony_ci return riic->err ?: num; 1558c2ecf20Sopenharmony_ci} 1568c2ecf20Sopenharmony_ci 1578c2ecf20Sopenharmony_cistatic irqreturn_t riic_tdre_isr(int irq, void *data) 1588c2ecf20Sopenharmony_ci{ 1598c2ecf20Sopenharmony_ci struct riic_dev *riic = data; 1608c2ecf20Sopenharmony_ci u8 val; 1618c2ecf20Sopenharmony_ci 1628c2ecf20Sopenharmony_ci if (!riic->bytes_left) 1638c2ecf20Sopenharmony_ci return IRQ_NONE; 1648c2ecf20Sopenharmony_ci 1658c2ecf20Sopenharmony_ci if (riic->bytes_left == RIIC_INIT_MSG) { 1668c2ecf20Sopenharmony_ci if (riic->msg->flags & I2C_M_RD) 1678c2ecf20Sopenharmony_ci /* On read, switch over to receive interrupt */ 1688c2ecf20Sopenharmony_ci riic_clear_set_bit(riic, ICIER_TIE, ICIER_RIE, RIIC_ICIER); 1698c2ecf20Sopenharmony_ci else 1708c2ecf20Sopenharmony_ci /* On write, initialize length */ 1718c2ecf20Sopenharmony_ci riic->bytes_left = riic->msg->len; 1728c2ecf20Sopenharmony_ci 1738c2ecf20Sopenharmony_ci val = i2c_8bit_addr_from_msg(riic->msg); 1748c2ecf20Sopenharmony_ci } else { 1758c2ecf20Sopenharmony_ci val = *riic->buf; 1768c2ecf20Sopenharmony_ci riic->buf++; 1778c2ecf20Sopenharmony_ci riic->bytes_left--; 1788c2ecf20Sopenharmony_ci } 1798c2ecf20Sopenharmony_ci 1808c2ecf20Sopenharmony_ci /* 1818c2ecf20Sopenharmony_ci * Switch to transmission ended interrupt when done. Do check here 1828c2ecf20Sopenharmony_ci * after bytes_left was initialized to support SMBUS_QUICK (new msg has 1838c2ecf20Sopenharmony_ci * 0 length then) 1848c2ecf20Sopenharmony_ci */ 1858c2ecf20Sopenharmony_ci if (riic->bytes_left == 0) 1868c2ecf20Sopenharmony_ci riic_clear_set_bit(riic, ICIER_TIE, ICIER_TEIE, RIIC_ICIER); 1878c2ecf20Sopenharmony_ci 1888c2ecf20Sopenharmony_ci /* 1898c2ecf20Sopenharmony_ci * This acks the TIE interrupt. We get another TIE immediately if our 1908c2ecf20Sopenharmony_ci * value could be moved to the shadow shift register right away. So 1918c2ecf20Sopenharmony_ci * this must be after updates to ICIER (where we want to disable TIE)! 1928c2ecf20Sopenharmony_ci */ 1938c2ecf20Sopenharmony_ci writeb(val, riic->base + RIIC_ICDRT); 1948c2ecf20Sopenharmony_ci 1958c2ecf20Sopenharmony_ci return IRQ_HANDLED; 1968c2ecf20Sopenharmony_ci} 1978c2ecf20Sopenharmony_ci 1988c2ecf20Sopenharmony_cistatic irqreturn_t riic_tend_isr(int irq, void *data) 1998c2ecf20Sopenharmony_ci{ 2008c2ecf20Sopenharmony_ci struct riic_dev *riic = data; 2018c2ecf20Sopenharmony_ci 2028c2ecf20Sopenharmony_ci if (readb(riic->base + RIIC_ICSR2) & ICSR2_NACKF) { 2038c2ecf20Sopenharmony_ci /* We got a NACKIE */ 2048c2ecf20Sopenharmony_ci readb(riic->base + RIIC_ICDRR); /* dummy read */ 2058c2ecf20Sopenharmony_ci riic_clear_set_bit(riic, ICSR2_NACKF, 0, RIIC_ICSR2); 2068c2ecf20Sopenharmony_ci riic->err = -ENXIO; 2078c2ecf20Sopenharmony_ci } else if (riic->bytes_left) { 2088c2ecf20Sopenharmony_ci return IRQ_NONE; 2098c2ecf20Sopenharmony_ci } 2108c2ecf20Sopenharmony_ci 2118c2ecf20Sopenharmony_ci if (riic->is_last || riic->err) { 2128c2ecf20Sopenharmony_ci riic_clear_set_bit(riic, ICIER_TEIE, ICIER_SPIE, RIIC_ICIER); 2138c2ecf20Sopenharmony_ci writeb(ICCR2_SP, riic->base + RIIC_ICCR2); 2148c2ecf20Sopenharmony_ci } else { 2158c2ecf20Sopenharmony_ci /* Transfer is complete, but do not send STOP */ 2168c2ecf20Sopenharmony_ci riic_clear_set_bit(riic, ICIER_TEIE, 0, RIIC_ICIER); 2178c2ecf20Sopenharmony_ci complete(&riic->msg_done); 2188c2ecf20Sopenharmony_ci } 2198c2ecf20Sopenharmony_ci 2208c2ecf20Sopenharmony_ci return IRQ_HANDLED; 2218c2ecf20Sopenharmony_ci} 2228c2ecf20Sopenharmony_ci 2238c2ecf20Sopenharmony_cistatic irqreturn_t riic_rdrf_isr(int irq, void *data) 2248c2ecf20Sopenharmony_ci{ 2258c2ecf20Sopenharmony_ci struct riic_dev *riic = data; 2268c2ecf20Sopenharmony_ci 2278c2ecf20Sopenharmony_ci if (!riic->bytes_left) 2288c2ecf20Sopenharmony_ci return IRQ_NONE; 2298c2ecf20Sopenharmony_ci 2308c2ecf20Sopenharmony_ci if (riic->bytes_left == RIIC_INIT_MSG) { 2318c2ecf20Sopenharmony_ci riic->bytes_left = riic->msg->len; 2328c2ecf20Sopenharmony_ci readb(riic->base + RIIC_ICDRR); /* dummy read */ 2338c2ecf20Sopenharmony_ci return IRQ_HANDLED; 2348c2ecf20Sopenharmony_ci } 2358c2ecf20Sopenharmony_ci 2368c2ecf20Sopenharmony_ci if (riic->bytes_left == 1) { 2378c2ecf20Sopenharmony_ci /* STOP must come before we set ACKBT! */ 2388c2ecf20Sopenharmony_ci if (riic->is_last) { 2398c2ecf20Sopenharmony_ci riic_clear_set_bit(riic, 0, ICIER_SPIE, RIIC_ICIER); 2408c2ecf20Sopenharmony_ci writeb(ICCR2_SP, riic->base + RIIC_ICCR2); 2418c2ecf20Sopenharmony_ci } 2428c2ecf20Sopenharmony_ci 2438c2ecf20Sopenharmony_ci riic_clear_set_bit(riic, 0, ICMR3_ACKBT, RIIC_ICMR3); 2448c2ecf20Sopenharmony_ci 2458c2ecf20Sopenharmony_ci } else { 2468c2ecf20Sopenharmony_ci riic_clear_set_bit(riic, ICMR3_ACKBT, 0, RIIC_ICMR3); 2478c2ecf20Sopenharmony_ci } 2488c2ecf20Sopenharmony_ci 2498c2ecf20Sopenharmony_ci /* Reading acks the RIE interrupt */ 2508c2ecf20Sopenharmony_ci *riic->buf = readb(riic->base + RIIC_ICDRR); 2518c2ecf20Sopenharmony_ci riic->buf++; 2528c2ecf20Sopenharmony_ci riic->bytes_left--; 2538c2ecf20Sopenharmony_ci 2548c2ecf20Sopenharmony_ci return IRQ_HANDLED; 2558c2ecf20Sopenharmony_ci} 2568c2ecf20Sopenharmony_ci 2578c2ecf20Sopenharmony_cistatic irqreturn_t riic_stop_isr(int irq, void *data) 2588c2ecf20Sopenharmony_ci{ 2598c2ecf20Sopenharmony_ci struct riic_dev *riic = data; 2608c2ecf20Sopenharmony_ci 2618c2ecf20Sopenharmony_ci /* read back registers to confirm writes have fully propagated */ 2628c2ecf20Sopenharmony_ci writeb(0, riic->base + RIIC_ICSR2); 2638c2ecf20Sopenharmony_ci readb(riic->base + RIIC_ICSR2); 2648c2ecf20Sopenharmony_ci writeb(0, riic->base + RIIC_ICIER); 2658c2ecf20Sopenharmony_ci readb(riic->base + RIIC_ICIER); 2668c2ecf20Sopenharmony_ci 2678c2ecf20Sopenharmony_ci complete(&riic->msg_done); 2688c2ecf20Sopenharmony_ci 2698c2ecf20Sopenharmony_ci return IRQ_HANDLED; 2708c2ecf20Sopenharmony_ci} 2718c2ecf20Sopenharmony_ci 2728c2ecf20Sopenharmony_cistatic u32 riic_func(struct i2c_adapter *adap) 2738c2ecf20Sopenharmony_ci{ 2748c2ecf20Sopenharmony_ci return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; 2758c2ecf20Sopenharmony_ci} 2768c2ecf20Sopenharmony_ci 2778c2ecf20Sopenharmony_cistatic const struct i2c_algorithm riic_algo = { 2788c2ecf20Sopenharmony_ci .master_xfer = riic_xfer, 2798c2ecf20Sopenharmony_ci .functionality = riic_func, 2808c2ecf20Sopenharmony_ci}; 2818c2ecf20Sopenharmony_ci 2828c2ecf20Sopenharmony_cistatic int riic_init_hw(struct riic_dev *riic, struct i2c_timings *t) 2838c2ecf20Sopenharmony_ci{ 2848c2ecf20Sopenharmony_ci int ret = 0; 2858c2ecf20Sopenharmony_ci unsigned long rate; 2868c2ecf20Sopenharmony_ci int total_ticks, cks, brl, brh; 2878c2ecf20Sopenharmony_ci 2888c2ecf20Sopenharmony_ci pm_runtime_get_sync(riic->adapter.dev.parent); 2898c2ecf20Sopenharmony_ci 2908c2ecf20Sopenharmony_ci if (t->bus_freq_hz > I2C_MAX_FAST_MODE_FREQ) { 2918c2ecf20Sopenharmony_ci dev_err(&riic->adapter.dev, 2928c2ecf20Sopenharmony_ci "unsupported bus speed (%dHz). %d max\n", 2938c2ecf20Sopenharmony_ci t->bus_freq_hz, I2C_MAX_FAST_MODE_FREQ); 2948c2ecf20Sopenharmony_ci ret = -EINVAL; 2958c2ecf20Sopenharmony_ci goto out; 2968c2ecf20Sopenharmony_ci } 2978c2ecf20Sopenharmony_ci 2988c2ecf20Sopenharmony_ci rate = clk_get_rate(riic->clk); 2998c2ecf20Sopenharmony_ci 3008c2ecf20Sopenharmony_ci /* 3018c2ecf20Sopenharmony_ci * Assume the default register settings: 3028c2ecf20Sopenharmony_ci * FER.SCLE = 1 (SCL sync circuit enabled, adds 2 or 3 cycles) 3038c2ecf20Sopenharmony_ci * FER.NFE = 1 (noise circuit enabled) 3048c2ecf20Sopenharmony_ci * MR3.NF = 0 (1 cycle of noise filtered out) 3058c2ecf20Sopenharmony_ci * 3068c2ecf20Sopenharmony_ci * Freq (CKS=000) = (I2CCLK + tr + tf)/ (BRH + 3 + 1) + (BRL + 3 + 1) 3078c2ecf20Sopenharmony_ci * Freq (CKS!=000) = (I2CCLK + tr + tf)/ (BRH + 2 + 1) + (BRL + 2 + 1) 3088c2ecf20Sopenharmony_ci */ 3098c2ecf20Sopenharmony_ci 3108c2ecf20Sopenharmony_ci /* 3118c2ecf20Sopenharmony_ci * Determine reference clock rate. We must be able to get the desired 3128c2ecf20Sopenharmony_ci * frequency with only 62 clock ticks max (31 high, 31 low). 3138c2ecf20Sopenharmony_ci * Aim for a duty of 60% LOW, 40% HIGH. 3148c2ecf20Sopenharmony_ci */ 3158c2ecf20Sopenharmony_ci total_ticks = DIV_ROUND_UP(rate, t->bus_freq_hz); 3168c2ecf20Sopenharmony_ci 3178c2ecf20Sopenharmony_ci for (cks = 0; cks < 7; cks++) { 3188c2ecf20Sopenharmony_ci /* 3198c2ecf20Sopenharmony_ci * 60% low time must be less than BRL + 2 + 1 3208c2ecf20Sopenharmony_ci * BRL max register value is 0x1F. 3218c2ecf20Sopenharmony_ci */ 3228c2ecf20Sopenharmony_ci brl = ((total_ticks * 6) / 10); 3238c2ecf20Sopenharmony_ci if (brl <= (0x1F + 3)) 3248c2ecf20Sopenharmony_ci break; 3258c2ecf20Sopenharmony_ci 3268c2ecf20Sopenharmony_ci total_ticks /= 2; 3278c2ecf20Sopenharmony_ci rate /= 2; 3288c2ecf20Sopenharmony_ci } 3298c2ecf20Sopenharmony_ci 3308c2ecf20Sopenharmony_ci if (brl > (0x1F + 3)) { 3318c2ecf20Sopenharmony_ci dev_err(&riic->adapter.dev, "invalid speed (%lu). Too slow.\n", 3328c2ecf20Sopenharmony_ci (unsigned long)t->bus_freq_hz); 3338c2ecf20Sopenharmony_ci ret = -EINVAL; 3348c2ecf20Sopenharmony_ci goto out; 3358c2ecf20Sopenharmony_ci } 3368c2ecf20Sopenharmony_ci 3378c2ecf20Sopenharmony_ci brh = total_ticks - brl; 3388c2ecf20Sopenharmony_ci 3398c2ecf20Sopenharmony_ci /* Remove automatic clock ticks for sync circuit and NF */ 3408c2ecf20Sopenharmony_ci if (cks == 0) { 3418c2ecf20Sopenharmony_ci brl -= 4; 3428c2ecf20Sopenharmony_ci brh -= 4; 3438c2ecf20Sopenharmony_ci } else { 3448c2ecf20Sopenharmony_ci brl -= 3; 3458c2ecf20Sopenharmony_ci brh -= 3; 3468c2ecf20Sopenharmony_ci } 3478c2ecf20Sopenharmony_ci 3488c2ecf20Sopenharmony_ci /* 3498c2ecf20Sopenharmony_ci * Remove clock ticks for rise and fall times. Convert ns to clock 3508c2ecf20Sopenharmony_ci * ticks. 3518c2ecf20Sopenharmony_ci */ 3528c2ecf20Sopenharmony_ci brl -= t->scl_fall_ns / (1000000000 / rate); 3538c2ecf20Sopenharmony_ci brh -= t->scl_rise_ns / (1000000000 / rate); 3548c2ecf20Sopenharmony_ci 3558c2ecf20Sopenharmony_ci /* Adjust for min register values for when SCLE=1 and NFE=1 */ 3568c2ecf20Sopenharmony_ci if (brl < 1) 3578c2ecf20Sopenharmony_ci brl = 1; 3588c2ecf20Sopenharmony_ci if (brh < 1) 3598c2ecf20Sopenharmony_ci brh = 1; 3608c2ecf20Sopenharmony_ci 3618c2ecf20Sopenharmony_ci pr_debug("i2c-riic: freq=%lu, duty=%d, fall=%lu, rise=%lu, cks=%d, brl=%d, brh=%d\n", 3628c2ecf20Sopenharmony_ci rate / total_ticks, ((brl + 3) * 100) / (brl + brh + 6), 3638c2ecf20Sopenharmony_ci t->scl_fall_ns / (1000000000 / rate), 3648c2ecf20Sopenharmony_ci t->scl_rise_ns / (1000000000 / rate), cks, brl, brh); 3658c2ecf20Sopenharmony_ci 3668c2ecf20Sopenharmony_ci /* Changing the order of accessing IICRST and ICE may break things! */ 3678c2ecf20Sopenharmony_ci writeb(ICCR1_IICRST | ICCR1_SOWP, riic->base + RIIC_ICCR1); 3688c2ecf20Sopenharmony_ci riic_clear_set_bit(riic, 0, ICCR1_ICE, RIIC_ICCR1); 3698c2ecf20Sopenharmony_ci 3708c2ecf20Sopenharmony_ci writeb(ICMR1_CKS(cks), riic->base + RIIC_ICMR1); 3718c2ecf20Sopenharmony_ci writeb(brh | ICBR_RESERVED, riic->base + RIIC_ICBRH); 3728c2ecf20Sopenharmony_ci writeb(brl | ICBR_RESERVED, riic->base + RIIC_ICBRL); 3738c2ecf20Sopenharmony_ci 3748c2ecf20Sopenharmony_ci writeb(0, riic->base + RIIC_ICSER); 3758c2ecf20Sopenharmony_ci writeb(ICMR3_ACKWP | ICMR3_RDRFS, riic->base + RIIC_ICMR3); 3768c2ecf20Sopenharmony_ci 3778c2ecf20Sopenharmony_ci riic_clear_set_bit(riic, ICCR1_IICRST, 0, RIIC_ICCR1); 3788c2ecf20Sopenharmony_ci 3798c2ecf20Sopenharmony_ciout: 3808c2ecf20Sopenharmony_ci pm_runtime_put(riic->adapter.dev.parent); 3818c2ecf20Sopenharmony_ci return ret; 3828c2ecf20Sopenharmony_ci} 3838c2ecf20Sopenharmony_ci 3848c2ecf20Sopenharmony_cistatic struct riic_irq_desc riic_irqs[] = { 3858c2ecf20Sopenharmony_ci { .res_num = 0, .isr = riic_tend_isr, .name = "riic-tend" }, 3868c2ecf20Sopenharmony_ci { .res_num = 1, .isr = riic_rdrf_isr, .name = "riic-rdrf" }, 3878c2ecf20Sopenharmony_ci { .res_num = 2, .isr = riic_tdre_isr, .name = "riic-tdre" }, 3888c2ecf20Sopenharmony_ci { .res_num = 3, .isr = riic_stop_isr, .name = "riic-stop" }, 3898c2ecf20Sopenharmony_ci { .res_num = 5, .isr = riic_tend_isr, .name = "riic-nack" }, 3908c2ecf20Sopenharmony_ci}; 3918c2ecf20Sopenharmony_ci 3928c2ecf20Sopenharmony_cistatic int riic_i2c_probe(struct platform_device *pdev) 3938c2ecf20Sopenharmony_ci{ 3948c2ecf20Sopenharmony_ci struct riic_dev *riic; 3958c2ecf20Sopenharmony_ci struct i2c_adapter *adap; 3968c2ecf20Sopenharmony_ci struct resource *res; 3978c2ecf20Sopenharmony_ci struct i2c_timings i2c_t; 3988c2ecf20Sopenharmony_ci int i, ret; 3998c2ecf20Sopenharmony_ci 4008c2ecf20Sopenharmony_ci riic = devm_kzalloc(&pdev->dev, sizeof(*riic), GFP_KERNEL); 4018c2ecf20Sopenharmony_ci if (!riic) 4028c2ecf20Sopenharmony_ci return -ENOMEM; 4038c2ecf20Sopenharmony_ci 4048c2ecf20Sopenharmony_ci res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 4058c2ecf20Sopenharmony_ci riic->base = devm_ioremap_resource(&pdev->dev, res); 4068c2ecf20Sopenharmony_ci if (IS_ERR(riic->base)) 4078c2ecf20Sopenharmony_ci return PTR_ERR(riic->base); 4088c2ecf20Sopenharmony_ci 4098c2ecf20Sopenharmony_ci riic->clk = devm_clk_get(&pdev->dev, NULL); 4108c2ecf20Sopenharmony_ci if (IS_ERR(riic->clk)) { 4118c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "missing controller clock"); 4128c2ecf20Sopenharmony_ci return PTR_ERR(riic->clk); 4138c2ecf20Sopenharmony_ci } 4148c2ecf20Sopenharmony_ci 4158c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(riic_irqs); i++) { 4168c2ecf20Sopenharmony_ci res = platform_get_resource(pdev, IORESOURCE_IRQ, riic_irqs[i].res_num); 4178c2ecf20Sopenharmony_ci if (!res) 4188c2ecf20Sopenharmony_ci return -ENODEV; 4198c2ecf20Sopenharmony_ci 4208c2ecf20Sopenharmony_ci ret = devm_request_irq(&pdev->dev, res->start, riic_irqs[i].isr, 4218c2ecf20Sopenharmony_ci 0, riic_irqs[i].name, riic); 4228c2ecf20Sopenharmony_ci if (ret) { 4238c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "failed to request irq %s\n", riic_irqs[i].name); 4248c2ecf20Sopenharmony_ci return ret; 4258c2ecf20Sopenharmony_ci } 4268c2ecf20Sopenharmony_ci } 4278c2ecf20Sopenharmony_ci 4288c2ecf20Sopenharmony_ci adap = &riic->adapter; 4298c2ecf20Sopenharmony_ci i2c_set_adapdata(adap, riic); 4308c2ecf20Sopenharmony_ci strlcpy(adap->name, "Renesas RIIC adapter", sizeof(adap->name)); 4318c2ecf20Sopenharmony_ci adap->owner = THIS_MODULE; 4328c2ecf20Sopenharmony_ci adap->algo = &riic_algo; 4338c2ecf20Sopenharmony_ci adap->dev.parent = &pdev->dev; 4348c2ecf20Sopenharmony_ci adap->dev.of_node = pdev->dev.of_node; 4358c2ecf20Sopenharmony_ci 4368c2ecf20Sopenharmony_ci init_completion(&riic->msg_done); 4378c2ecf20Sopenharmony_ci 4388c2ecf20Sopenharmony_ci i2c_parse_fw_timings(&pdev->dev, &i2c_t, true); 4398c2ecf20Sopenharmony_ci 4408c2ecf20Sopenharmony_ci pm_runtime_enable(&pdev->dev); 4418c2ecf20Sopenharmony_ci 4428c2ecf20Sopenharmony_ci ret = riic_init_hw(riic, &i2c_t); 4438c2ecf20Sopenharmony_ci if (ret) 4448c2ecf20Sopenharmony_ci goto out; 4458c2ecf20Sopenharmony_ci 4468c2ecf20Sopenharmony_ci ret = i2c_add_adapter(adap); 4478c2ecf20Sopenharmony_ci if (ret) 4488c2ecf20Sopenharmony_ci goto out; 4498c2ecf20Sopenharmony_ci 4508c2ecf20Sopenharmony_ci platform_set_drvdata(pdev, riic); 4518c2ecf20Sopenharmony_ci 4528c2ecf20Sopenharmony_ci dev_info(&pdev->dev, "registered with %dHz bus speed\n", 4538c2ecf20Sopenharmony_ci i2c_t.bus_freq_hz); 4548c2ecf20Sopenharmony_ci return 0; 4558c2ecf20Sopenharmony_ci 4568c2ecf20Sopenharmony_ciout: 4578c2ecf20Sopenharmony_ci pm_runtime_disable(&pdev->dev); 4588c2ecf20Sopenharmony_ci return ret; 4598c2ecf20Sopenharmony_ci} 4608c2ecf20Sopenharmony_ci 4618c2ecf20Sopenharmony_cistatic int riic_i2c_remove(struct platform_device *pdev) 4628c2ecf20Sopenharmony_ci{ 4638c2ecf20Sopenharmony_ci struct riic_dev *riic = platform_get_drvdata(pdev); 4648c2ecf20Sopenharmony_ci 4658c2ecf20Sopenharmony_ci pm_runtime_get_sync(&pdev->dev); 4668c2ecf20Sopenharmony_ci writeb(0, riic->base + RIIC_ICIER); 4678c2ecf20Sopenharmony_ci pm_runtime_put(&pdev->dev); 4688c2ecf20Sopenharmony_ci i2c_del_adapter(&riic->adapter); 4698c2ecf20Sopenharmony_ci pm_runtime_disable(&pdev->dev); 4708c2ecf20Sopenharmony_ci 4718c2ecf20Sopenharmony_ci return 0; 4728c2ecf20Sopenharmony_ci} 4738c2ecf20Sopenharmony_ci 4748c2ecf20Sopenharmony_cistatic const struct of_device_id riic_i2c_dt_ids[] = { 4758c2ecf20Sopenharmony_ci { .compatible = "renesas,riic-rz" }, 4768c2ecf20Sopenharmony_ci { /* Sentinel */ }, 4778c2ecf20Sopenharmony_ci}; 4788c2ecf20Sopenharmony_ci 4798c2ecf20Sopenharmony_cistatic struct platform_driver riic_i2c_driver = { 4808c2ecf20Sopenharmony_ci .probe = riic_i2c_probe, 4818c2ecf20Sopenharmony_ci .remove = riic_i2c_remove, 4828c2ecf20Sopenharmony_ci .driver = { 4838c2ecf20Sopenharmony_ci .name = "i2c-riic", 4848c2ecf20Sopenharmony_ci .of_match_table = riic_i2c_dt_ids, 4858c2ecf20Sopenharmony_ci }, 4868c2ecf20Sopenharmony_ci}; 4878c2ecf20Sopenharmony_ci 4888c2ecf20Sopenharmony_cimodule_platform_driver(riic_i2c_driver); 4898c2ecf20Sopenharmony_ci 4908c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("Renesas RIIC adapter"); 4918c2ecf20Sopenharmony_ciMODULE_AUTHOR("Wolfram Sang <wsa@sang-engineering.com>"); 4928c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL v2"); 4938c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(of, riic_i2c_dt_ids); 494