18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * TI DAVINCI I2C adapter driver. 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (C) 2006 Texas Instruments. 68c2ecf20Sopenharmony_ci * Copyright (C) 2007 MontaVista Software Inc. 78c2ecf20Sopenharmony_ci * 88c2ecf20Sopenharmony_ci * Updated by Vinod & Sudhakar Feb 2005 98c2ecf20Sopenharmony_ci * 108c2ecf20Sopenharmony_ci * ---------------------------------------------------------------------------- 118c2ecf20Sopenharmony_ci * 128c2ecf20Sopenharmony_ci * ---------------------------------------------------------------------------- 138c2ecf20Sopenharmony_ci */ 148c2ecf20Sopenharmony_ci#include <linux/kernel.h> 158c2ecf20Sopenharmony_ci#include <linux/module.h> 168c2ecf20Sopenharmony_ci#include <linux/delay.h> 178c2ecf20Sopenharmony_ci#include <linux/i2c.h> 188c2ecf20Sopenharmony_ci#include <linux/clk.h> 198c2ecf20Sopenharmony_ci#include <linux/errno.h> 208c2ecf20Sopenharmony_ci#include <linux/sched.h> 218c2ecf20Sopenharmony_ci#include <linux/err.h> 228c2ecf20Sopenharmony_ci#include <linux/interrupt.h> 238c2ecf20Sopenharmony_ci#include <linux/platform_device.h> 248c2ecf20Sopenharmony_ci#include <linux/io.h> 258c2ecf20Sopenharmony_ci#include <linux/slab.h> 268c2ecf20Sopenharmony_ci#include <linux/cpufreq.h> 278c2ecf20Sopenharmony_ci#include <linux/gpio/consumer.h> 288c2ecf20Sopenharmony_ci#include <linux/of_device.h> 298c2ecf20Sopenharmony_ci#include <linux/platform_data/i2c-davinci.h> 308c2ecf20Sopenharmony_ci#include <linux/pm_runtime.h> 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_ci/* ----- global defines ----------------------------------------------- */ 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_ci#define DAVINCI_I2C_TIMEOUT (1*HZ) 358c2ecf20Sopenharmony_ci#define DAVINCI_I2C_MAX_TRIES 2 368c2ecf20Sopenharmony_ci#define DAVINCI_I2C_OWN_ADDRESS 0x08 378c2ecf20Sopenharmony_ci#define I2C_DAVINCI_INTR_ALL (DAVINCI_I2C_IMR_SCD | \ 388c2ecf20Sopenharmony_ci DAVINCI_I2C_IMR_ARDY | \ 398c2ecf20Sopenharmony_ci DAVINCI_I2C_IMR_NACK | \ 408c2ecf20Sopenharmony_ci DAVINCI_I2C_IMR_AL) 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_ci#define DAVINCI_I2C_OAR_REG 0x00 438c2ecf20Sopenharmony_ci#define DAVINCI_I2C_IMR_REG 0x04 448c2ecf20Sopenharmony_ci#define DAVINCI_I2C_STR_REG 0x08 458c2ecf20Sopenharmony_ci#define DAVINCI_I2C_CLKL_REG 0x0c 468c2ecf20Sopenharmony_ci#define DAVINCI_I2C_CLKH_REG 0x10 478c2ecf20Sopenharmony_ci#define DAVINCI_I2C_CNT_REG 0x14 488c2ecf20Sopenharmony_ci#define DAVINCI_I2C_DRR_REG 0x18 498c2ecf20Sopenharmony_ci#define DAVINCI_I2C_SAR_REG 0x1c 508c2ecf20Sopenharmony_ci#define DAVINCI_I2C_DXR_REG 0x20 518c2ecf20Sopenharmony_ci#define DAVINCI_I2C_MDR_REG 0x24 528c2ecf20Sopenharmony_ci#define DAVINCI_I2C_IVR_REG 0x28 538c2ecf20Sopenharmony_ci#define DAVINCI_I2C_EMDR_REG 0x2c 548c2ecf20Sopenharmony_ci#define DAVINCI_I2C_PSC_REG 0x30 558c2ecf20Sopenharmony_ci#define DAVINCI_I2C_FUNC_REG 0x48 568c2ecf20Sopenharmony_ci#define DAVINCI_I2C_DIR_REG 0x4c 578c2ecf20Sopenharmony_ci#define DAVINCI_I2C_DIN_REG 0x50 588c2ecf20Sopenharmony_ci#define DAVINCI_I2C_DOUT_REG 0x54 598c2ecf20Sopenharmony_ci#define DAVINCI_I2C_DSET_REG 0x58 608c2ecf20Sopenharmony_ci#define DAVINCI_I2C_DCLR_REG 0x5c 618c2ecf20Sopenharmony_ci 628c2ecf20Sopenharmony_ci#define DAVINCI_I2C_IVR_AAS 0x07 638c2ecf20Sopenharmony_ci#define DAVINCI_I2C_IVR_SCD 0x06 648c2ecf20Sopenharmony_ci#define DAVINCI_I2C_IVR_XRDY 0x05 658c2ecf20Sopenharmony_ci#define DAVINCI_I2C_IVR_RDR 0x04 668c2ecf20Sopenharmony_ci#define DAVINCI_I2C_IVR_ARDY 0x03 678c2ecf20Sopenharmony_ci#define DAVINCI_I2C_IVR_NACK 0x02 688c2ecf20Sopenharmony_ci#define DAVINCI_I2C_IVR_AL 0x01 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_ci#define DAVINCI_I2C_STR_BB BIT(12) 718c2ecf20Sopenharmony_ci#define DAVINCI_I2C_STR_RSFULL BIT(11) 728c2ecf20Sopenharmony_ci#define DAVINCI_I2C_STR_SCD BIT(5) 738c2ecf20Sopenharmony_ci#define DAVINCI_I2C_STR_ARDY BIT(2) 748c2ecf20Sopenharmony_ci#define DAVINCI_I2C_STR_NACK BIT(1) 758c2ecf20Sopenharmony_ci#define DAVINCI_I2C_STR_AL BIT(0) 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_ci#define DAVINCI_I2C_MDR_NACK BIT(15) 788c2ecf20Sopenharmony_ci#define DAVINCI_I2C_MDR_STT BIT(13) 798c2ecf20Sopenharmony_ci#define DAVINCI_I2C_MDR_STP BIT(11) 808c2ecf20Sopenharmony_ci#define DAVINCI_I2C_MDR_MST BIT(10) 818c2ecf20Sopenharmony_ci#define DAVINCI_I2C_MDR_TRX BIT(9) 828c2ecf20Sopenharmony_ci#define DAVINCI_I2C_MDR_XA BIT(8) 838c2ecf20Sopenharmony_ci#define DAVINCI_I2C_MDR_RM BIT(7) 848c2ecf20Sopenharmony_ci#define DAVINCI_I2C_MDR_IRS BIT(5) 858c2ecf20Sopenharmony_ci 868c2ecf20Sopenharmony_ci#define DAVINCI_I2C_IMR_AAS BIT(6) 878c2ecf20Sopenharmony_ci#define DAVINCI_I2C_IMR_SCD BIT(5) 888c2ecf20Sopenharmony_ci#define DAVINCI_I2C_IMR_XRDY BIT(4) 898c2ecf20Sopenharmony_ci#define DAVINCI_I2C_IMR_RRDY BIT(3) 908c2ecf20Sopenharmony_ci#define DAVINCI_I2C_IMR_ARDY BIT(2) 918c2ecf20Sopenharmony_ci#define DAVINCI_I2C_IMR_NACK BIT(1) 928c2ecf20Sopenharmony_ci#define DAVINCI_I2C_IMR_AL BIT(0) 938c2ecf20Sopenharmony_ci 948c2ecf20Sopenharmony_ci/* set SDA and SCL as GPIO */ 958c2ecf20Sopenharmony_ci#define DAVINCI_I2C_FUNC_PFUNC0 BIT(0) 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_ci/* set SCL as output when used as GPIO*/ 988c2ecf20Sopenharmony_ci#define DAVINCI_I2C_DIR_PDIR0 BIT(0) 998c2ecf20Sopenharmony_ci/* set SDA as output when used as GPIO*/ 1008c2ecf20Sopenharmony_ci#define DAVINCI_I2C_DIR_PDIR1 BIT(1) 1018c2ecf20Sopenharmony_ci 1028c2ecf20Sopenharmony_ci/* read SCL GPIO level */ 1038c2ecf20Sopenharmony_ci#define DAVINCI_I2C_DIN_PDIN0 BIT(0) 1048c2ecf20Sopenharmony_ci/* read SDA GPIO level */ 1058c2ecf20Sopenharmony_ci#define DAVINCI_I2C_DIN_PDIN1 BIT(1) 1068c2ecf20Sopenharmony_ci 1078c2ecf20Sopenharmony_ci/*set the SCL GPIO high */ 1088c2ecf20Sopenharmony_ci#define DAVINCI_I2C_DSET_PDSET0 BIT(0) 1098c2ecf20Sopenharmony_ci/*set the SDA GPIO high */ 1108c2ecf20Sopenharmony_ci#define DAVINCI_I2C_DSET_PDSET1 BIT(1) 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_ci/* set the SCL GPIO low */ 1138c2ecf20Sopenharmony_ci#define DAVINCI_I2C_DCLR_PDCLR0 BIT(0) 1148c2ecf20Sopenharmony_ci/* set the SDA GPIO low */ 1158c2ecf20Sopenharmony_ci#define DAVINCI_I2C_DCLR_PDCLR1 BIT(1) 1168c2ecf20Sopenharmony_ci 1178c2ecf20Sopenharmony_ci/* timeout for pm runtime autosuspend */ 1188c2ecf20Sopenharmony_ci#define DAVINCI_I2C_PM_TIMEOUT 1000 /* ms */ 1198c2ecf20Sopenharmony_ci 1208c2ecf20Sopenharmony_cistruct davinci_i2c_dev { 1218c2ecf20Sopenharmony_ci struct device *dev; 1228c2ecf20Sopenharmony_ci void __iomem *base; 1238c2ecf20Sopenharmony_ci struct completion cmd_complete; 1248c2ecf20Sopenharmony_ci struct clk *clk; 1258c2ecf20Sopenharmony_ci int cmd_err; 1268c2ecf20Sopenharmony_ci u8 *buf; 1278c2ecf20Sopenharmony_ci size_t buf_len; 1288c2ecf20Sopenharmony_ci int irq; 1298c2ecf20Sopenharmony_ci int stop; 1308c2ecf20Sopenharmony_ci u8 terminate; 1318c2ecf20Sopenharmony_ci struct i2c_adapter adapter; 1328c2ecf20Sopenharmony_ci#ifdef CONFIG_CPU_FREQ 1338c2ecf20Sopenharmony_ci struct notifier_block freq_transition; 1348c2ecf20Sopenharmony_ci#endif 1358c2ecf20Sopenharmony_ci struct davinci_i2c_platform_data *pdata; 1368c2ecf20Sopenharmony_ci}; 1378c2ecf20Sopenharmony_ci 1388c2ecf20Sopenharmony_ci/* default platform data to use if not supplied in the platform_device */ 1398c2ecf20Sopenharmony_cistatic struct davinci_i2c_platform_data davinci_i2c_platform_data_default = { 1408c2ecf20Sopenharmony_ci .bus_freq = 100, 1418c2ecf20Sopenharmony_ci .bus_delay = 0, 1428c2ecf20Sopenharmony_ci}; 1438c2ecf20Sopenharmony_ci 1448c2ecf20Sopenharmony_cistatic inline void davinci_i2c_write_reg(struct davinci_i2c_dev *i2c_dev, 1458c2ecf20Sopenharmony_ci int reg, u16 val) 1468c2ecf20Sopenharmony_ci{ 1478c2ecf20Sopenharmony_ci writew_relaxed(val, i2c_dev->base + reg); 1488c2ecf20Sopenharmony_ci} 1498c2ecf20Sopenharmony_ci 1508c2ecf20Sopenharmony_cistatic inline u16 davinci_i2c_read_reg(struct davinci_i2c_dev *i2c_dev, int reg) 1518c2ecf20Sopenharmony_ci{ 1528c2ecf20Sopenharmony_ci return readw_relaxed(i2c_dev->base + reg); 1538c2ecf20Sopenharmony_ci} 1548c2ecf20Sopenharmony_ci 1558c2ecf20Sopenharmony_cistatic inline void davinci_i2c_reset_ctrl(struct davinci_i2c_dev *i2c_dev, 1568c2ecf20Sopenharmony_ci int val) 1578c2ecf20Sopenharmony_ci{ 1588c2ecf20Sopenharmony_ci u16 w; 1598c2ecf20Sopenharmony_ci 1608c2ecf20Sopenharmony_ci w = davinci_i2c_read_reg(i2c_dev, DAVINCI_I2C_MDR_REG); 1618c2ecf20Sopenharmony_ci if (!val) /* put I2C into reset */ 1628c2ecf20Sopenharmony_ci w &= ~DAVINCI_I2C_MDR_IRS; 1638c2ecf20Sopenharmony_ci else /* take I2C out of reset */ 1648c2ecf20Sopenharmony_ci w |= DAVINCI_I2C_MDR_IRS; 1658c2ecf20Sopenharmony_ci 1668c2ecf20Sopenharmony_ci davinci_i2c_write_reg(i2c_dev, DAVINCI_I2C_MDR_REG, w); 1678c2ecf20Sopenharmony_ci} 1688c2ecf20Sopenharmony_ci 1698c2ecf20Sopenharmony_cistatic void i2c_davinci_calc_clk_dividers(struct davinci_i2c_dev *dev) 1708c2ecf20Sopenharmony_ci{ 1718c2ecf20Sopenharmony_ci struct davinci_i2c_platform_data *pdata = dev->pdata; 1728c2ecf20Sopenharmony_ci u16 psc; 1738c2ecf20Sopenharmony_ci u32 clk; 1748c2ecf20Sopenharmony_ci u32 d; 1758c2ecf20Sopenharmony_ci u32 clkh; 1768c2ecf20Sopenharmony_ci u32 clkl; 1778c2ecf20Sopenharmony_ci u32 input_clock = clk_get_rate(dev->clk); 1788c2ecf20Sopenharmony_ci struct device_node *of_node = dev->dev->of_node; 1798c2ecf20Sopenharmony_ci 1808c2ecf20Sopenharmony_ci /* NOTE: I2C Clock divider programming info 1818c2ecf20Sopenharmony_ci * As per I2C specs the following formulas provide prescaler 1828c2ecf20Sopenharmony_ci * and low/high divider values 1838c2ecf20Sopenharmony_ci * input clk --> PSC Div -----------> ICCL/H Div --> output clock 1848c2ecf20Sopenharmony_ci * module clk 1858c2ecf20Sopenharmony_ci * 1868c2ecf20Sopenharmony_ci * output clk = module clk / (PSC + 1) [ (ICCL + d) + (ICCH + d) ] 1878c2ecf20Sopenharmony_ci * 1888c2ecf20Sopenharmony_ci * Thus, 1898c2ecf20Sopenharmony_ci * (ICCL + ICCH) = clk = (input clk / ((psc +1) * output clk)) - 2d; 1908c2ecf20Sopenharmony_ci * 1918c2ecf20Sopenharmony_ci * where if PSC == 0, d = 7, 1928c2ecf20Sopenharmony_ci * if PSC == 1, d = 6 1938c2ecf20Sopenharmony_ci * if PSC > 1 , d = 5 1948c2ecf20Sopenharmony_ci * 1958c2ecf20Sopenharmony_ci * Note: 1968c2ecf20Sopenharmony_ci * d is always 6 on Keystone I2C controller 1978c2ecf20Sopenharmony_ci */ 1988c2ecf20Sopenharmony_ci 1998c2ecf20Sopenharmony_ci /* 2008c2ecf20Sopenharmony_ci * Both Davinci and current Keystone User Guides recommend a value 2018c2ecf20Sopenharmony_ci * between 7MHz and 12MHz. In reality 7MHz module clock doesn't 2028c2ecf20Sopenharmony_ci * always produce enough margin between SDA and SCL transitions. 2038c2ecf20Sopenharmony_ci * Measurements show that the higher the module clock is, the 2048c2ecf20Sopenharmony_ci * bigger is the margin, providing more reliable communication. 2058c2ecf20Sopenharmony_ci * So we better target for 12MHz. 2068c2ecf20Sopenharmony_ci */ 2078c2ecf20Sopenharmony_ci psc = (input_clock / 12000000) - 1; 2088c2ecf20Sopenharmony_ci if ((input_clock / (psc + 1)) > 12000000) 2098c2ecf20Sopenharmony_ci psc++; /* better to run under spec than over */ 2108c2ecf20Sopenharmony_ci d = (psc >= 2) ? 5 : 7 - psc; 2118c2ecf20Sopenharmony_ci 2128c2ecf20Sopenharmony_ci if (of_node && of_device_is_compatible(of_node, "ti,keystone-i2c")) 2138c2ecf20Sopenharmony_ci d = 6; 2148c2ecf20Sopenharmony_ci 2158c2ecf20Sopenharmony_ci clk = ((input_clock / (psc + 1)) / (pdata->bus_freq * 1000)); 2168c2ecf20Sopenharmony_ci /* Avoid driving the bus too fast because of rounding errors above */ 2178c2ecf20Sopenharmony_ci if (input_clock / (psc + 1) / clk > pdata->bus_freq * 1000) 2188c2ecf20Sopenharmony_ci clk++; 2198c2ecf20Sopenharmony_ci /* 2208c2ecf20Sopenharmony_ci * According to I2C-BUS Spec 2.1, in FAST-MODE LOW period should be at 2218c2ecf20Sopenharmony_ci * least 1.3uS, which is not the case with 50% duty cycle. Driving HIGH 2228c2ecf20Sopenharmony_ci * to LOW ratio as 1 to 2 is more safe. 2238c2ecf20Sopenharmony_ci */ 2248c2ecf20Sopenharmony_ci if (pdata->bus_freq > 100) 2258c2ecf20Sopenharmony_ci clkl = (clk << 1) / 3; 2268c2ecf20Sopenharmony_ci else 2278c2ecf20Sopenharmony_ci clkl = (clk >> 1); 2288c2ecf20Sopenharmony_ci /* 2298c2ecf20Sopenharmony_ci * It's not always possible to have 1 to 2 ratio when d=7, so fall back 2308c2ecf20Sopenharmony_ci * to minimal possible clkh in this case. 2318c2ecf20Sopenharmony_ci * 2328c2ecf20Sopenharmony_ci * Note: 2338c2ecf20Sopenharmony_ci * CLKH is not allowed to be 0, in this case I2C clock is not generated 2348c2ecf20Sopenharmony_ci * at all 2358c2ecf20Sopenharmony_ci */ 2368c2ecf20Sopenharmony_ci if (clk > clkl + d) { 2378c2ecf20Sopenharmony_ci clkh = clk - clkl - d; 2388c2ecf20Sopenharmony_ci clkl -= d; 2398c2ecf20Sopenharmony_ci } else { 2408c2ecf20Sopenharmony_ci clkh = 1; 2418c2ecf20Sopenharmony_ci clkl = clk - (d << 1); 2428c2ecf20Sopenharmony_ci } 2438c2ecf20Sopenharmony_ci 2448c2ecf20Sopenharmony_ci davinci_i2c_write_reg(dev, DAVINCI_I2C_PSC_REG, psc); 2458c2ecf20Sopenharmony_ci davinci_i2c_write_reg(dev, DAVINCI_I2C_CLKH_REG, clkh); 2468c2ecf20Sopenharmony_ci davinci_i2c_write_reg(dev, DAVINCI_I2C_CLKL_REG, clkl); 2478c2ecf20Sopenharmony_ci 2488c2ecf20Sopenharmony_ci dev_dbg(dev->dev, "input_clock = %d, CLK = %d\n", input_clock, clk); 2498c2ecf20Sopenharmony_ci} 2508c2ecf20Sopenharmony_ci 2518c2ecf20Sopenharmony_ci/* 2528c2ecf20Sopenharmony_ci * This function configures I2C and brings I2C out of reset. 2538c2ecf20Sopenharmony_ci * This function is called during I2C init function. This function 2548c2ecf20Sopenharmony_ci * also gets called if I2C encounters any errors. 2558c2ecf20Sopenharmony_ci */ 2568c2ecf20Sopenharmony_cistatic int i2c_davinci_init(struct davinci_i2c_dev *dev) 2578c2ecf20Sopenharmony_ci{ 2588c2ecf20Sopenharmony_ci struct davinci_i2c_platform_data *pdata = dev->pdata; 2598c2ecf20Sopenharmony_ci 2608c2ecf20Sopenharmony_ci /* put I2C into reset */ 2618c2ecf20Sopenharmony_ci davinci_i2c_reset_ctrl(dev, 0); 2628c2ecf20Sopenharmony_ci 2638c2ecf20Sopenharmony_ci /* compute clock dividers */ 2648c2ecf20Sopenharmony_ci i2c_davinci_calc_clk_dividers(dev); 2658c2ecf20Sopenharmony_ci 2668c2ecf20Sopenharmony_ci /* Respond at reserved "SMBus Host" slave address" (and zero); 2678c2ecf20Sopenharmony_ci * we seem to have no option to not respond... 2688c2ecf20Sopenharmony_ci */ 2698c2ecf20Sopenharmony_ci davinci_i2c_write_reg(dev, DAVINCI_I2C_OAR_REG, DAVINCI_I2C_OWN_ADDRESS); 2708c2ecf20Sopenharmony_ci 2718c2ecf20Sopenharmony_ci dev_dbg(dev->dev, "PSC = %d\n", 2728c2ecf20Sopenharmony_ci davinci_i2c_read_reg(dev, DAVINCI_I2C_PSC_REG)); 2738c2ecf20Sopenharmony_ci dev_dbg(dev->dev, "CLKL = %d\n", 2748c2ecf20Sopenharmony_ci davinci_i2c_read_reg(dev, DAVINCI_I2C_CLKL_REG)); 2758c2ecf20Sopenharmony_ci dev_dbg(dev->dev, "CLKH = %d\n", 2768c2ecf20Sopenharmony_ci davinci_i2c_read_reg(dev, DAVINCI_I2C_CLKH_REG)); 2778c2ecf20Sopenharmony_ci dev_dbg(dev->dev, "bus_freq = %dkHz, bus_delay = %d\n", 2788c2ecf20Sopenharmony_ci pdata->bus_freq, pdata->bus_delay); 2798c2ecf20Sopenharmony_ci 2808c2ecf20Sopenharmony_ci 2818c2ecf20Sopenharmony_ci /* Take the I2C module out of reset: */ 2828c2ecf20Sopenharmony_ci davinci_i2c_reset_ctrl(dev, 1); 2838c2ecf20Sopenharmony_ci 2848c2ecf20Sopenharmony_ci /* Enable interrupts */ 2858c2ecf20Sopenharmony_ci davinci_i2c_write_reg(dev, DAVINCI_I2C_IMR_REG, I2C_DAVINCI_INTR_ALL); 2868c2ecf20Sopenharmony_ci 2878c2ecf20Sopenharmony_ci return 0; 2888c2ecf20Sopenharmony_ci} 2898c2ecf20Sopenharmony_ci 2908c2ecf20Sopenharmony_ci/* 2918c2ecf20Sopenharmony_ci * This routine does i2c bus recovery by using i2c_generic_scl_recovery 2928c2ecf20Sopenharmony_ci * which is provided by I2C Bus recovery infrastructure. 2938c2ecf20Sopenharmony_ci */ 2948c2ecf20Sopenharmony_cistatic void davinci_i2c_prepare_recovery(struct i2c_adapter *adap) 2958c2ecf20Sopenharmony_ci{ 2968c2ecf20Sopenharmony_ci struct davinci_i2c_dev *dev = i2c_get_adapdata(adap); 2978c2ecf20Sopenharmony_ci 2988c2ecf20Sopenharmony_ci /* Disable interrupts */ 2998c2ecf20Sopenharmony_ci davinci_i2c_write_reg(dev, DAVINCI_I2C_IMR_REG, 0); 3008c2ecf20Sopenharmony_ci 3018c2ecf20Sopenharmony_ci /* put I2C into reset */ 3028c2ecf20Sopenharmony_ci davinci_i2c_reset_ctrl(dev, 0); 3038c2ecf20Sopenharmony_ci} 3048c2ecf20Sopenharmony_ci 3058c2ecf20Sopenharmony_cistatic void davinci_i2c_unprepare_recovery(struct i2c_adapter *adap) 3068c2ecf20Sopenharmony_ci{ 3078c2ecf20Sopenharmony_ci struct davinci_i2c_dev *dev = i2c_get_adapdata(adap); 3088c2ecf20Sopenharmony_ci 3098c2ecf20Sopenharmony_ci i2c_davinci_init(dev); 3108c2ecf20Sopenharmony_ci} 3118c2ecf20Sopenharmony_ci 3128c2ecf20Sopenharmony_cistatic struct i2c_bus_recovery_info davinci_i2c_gpio_recovery_info = { 3138c2ecf20Sopenharmony_ci .recover_bus = i2c_generic_scl_recovery, 3148c2ecf20Sopenharmony_ci .prepare_recovery = davinci_i2c_prepare_recovery, 3158c2ecf20Sopenharmony_ci .unprepare_recovery = davinci_i2c_unprepare_recovery, 3168c2ecf20Sopenharmony_ci}; 3178c2ecf20Sopenharmony_ci 3188c2ecf20Sopenharmony_cistatic void davinci_i2c_set_scl(struct i2c_adapter *adap, int val) 3198c2ecf20Sopenharmony_ci{ 3208c2ecf20Sopenharmony_ci struct davinci_i2c_dev *dev = i2c_get_adapdata(adap); 3218c2ecf20Sopenharmony_ci 3228c2ecf20Sopenharmony_ci if (val) 3238c2ecf20Sopenharmony_ci davinci_i2c_write_reg(dev, DAVINCI_I2C_DSET_REG, 3248c2ecf20Sopenharmony_ci DAVINCI_I2C_DSET_PDSET0); 3258c2ecf20Sopenharmony_ci else 3268c2ecf20Sopenharmony_ci davinci_i2c_write_reg(dev, DAVINCI_I2C_DCLR_REG, 3278c2ecf20Sopenharmony_ci DAVINCI_I2C_DCLR_PDCLR0); 3288c2ecf20Sopenharmony_ci} 3298c2ecf20Sopenharmony_ci 3308c2ecf20Sopenharmony_cistatic int davinci_i2c_get_scl(struct i2c_adapter *adap) 3318c2ecf20Sopenharmony_ci{ 3328c2ecf20Sopenharmony_ci struct davinci_i2c_dev *dev = i2c_get_adapdata(adap); 3338c2ecf20Sopenharmony_ci int val; 3348c2ecf20Sopenharmony_ci 3358c2ecf20Sopenharmony_ci /* read the state of SCL */ 3368c2ecf20Sopenharmony_ci val = davinci_i2c_read_reg(dev, DAVINCI_I2C_DIN_REG); 3378c2ecf20Sopenharmony_ci return val & DAVINCI_I2C_DIN_PDIN0; 3388c2ecf20Sopenharmony_ci} 3398c2ecf20Sopenharmony_ci 3408c2ecf20Sopenharmony_cistatic int davinci_i2c_get_sda(struct i2c_adapter *adap) 3418c2ecf20Sopenharmony_ci{ 3428c2ecf20Sopenharmony_ci struct davinci_i2c_dev *dev = i2c_get_adapdata(adap); 3438c2ecf20Sopenharmony_ci int val; 3448c2ecf20Sopenharmony_ci 3458c2ecf20Sopenharmony_ci /* read the state of SDA */ 3468c2ecf20Sopenharmony_ci val = davinci_i2c_read_reg(dev, DAVINCI_I2C_DIN_REG); 3478c2ecf20Sopenharmony_ci return val & DAVINCI_I2C_DIN_PDIN1; 3488c2ecf20Sopenharmony_ci} 3498c2ecf20Sopenharmony_ci 3508c2ecf20Sopenharmony_cistatic void davinci_i2c_scl_prepare_recovery(struct i2c_adapter *adap) 3518c2ecf20Sopenharmony_ci{ 3528c2ecf20Sopenharmony_ci struct davinci_i2c_dev *dev = i2c_get_adapdata(adap); 3538c2ecf20Sopenharmony_ci 3548c2ecf20Sopenharmony_ci davinci_i2c_prepare_recovery(adap); 3558c2ecf20Sopenharmony_ci 3568c2ecf20Sopenharmony_ci /* SCL output, SDA input */ 3578c2ecf20Sopenharmony_ci davinci_i2c_write_reg(dev, DAVINCI_I2C_DIR_REG, DAVINCI_I2C_DIR_PDIR0); 3588c2ecf20Sopenharmony_ci 3598c2ecf20Sopenharmony_ci /* change to GPIO mode */ 3608c2ecf20Sopenharmony_ci davinci_i2c_write_reg(dev, DAVINCI_I2C_FUNC_REG, 3618c2ecf20Sopenharmony_ci DAVINCI_I2C_FUNC_PFUNC0); 3628c2ecf20Sopenharmony_ci} 3638c2ecf20Sopenharmony_ci 3648c2ecf20Sopenharmony_cistatic void davinci_i2c_scl_unprepare_recovery(struct i2c_adapter *adap) 3658c2ecf20Sopenharmony_ci{ 3668c2ecf20Sopenharmony_ci struct davinci_i2c_dev *dev = i2c_get_adapdata(adap); 3678c2ecf20Sopenharmony_ci 3688c2ecf20Sopenharmony_ci /* change back to I2C mode */ 3698c2ecf20Sopenharmony_ci davinci_i2c_write_reg(dev, DAVINCI_I2C_FUNC_REG, 0); 3708c2ecf20Sopenharmony_ci 3718c2ecf20Sopenharmony_ci davinci_i2c_unprepare_recovery(adap); 3728c2ecf20Sopenharmony_ci} 3738c2ecf20Sopenharmony_ci 3748c2ecf20Sopenharmony_cistatic struct i2c_bus_recovery_info davinci_i2c_scl_recovery_info = { 3758c2ecf20Sopenharmony_ci .recover_bus = i2c_generic_scl_recovery, 3768c2ecf20Sopenharmony_ci .set_scl = davinci_i2c_set_scl, 3778c2ecf20Sopenharmony_ci .get_scl = davinci_i2c_get_scl, 3788c2ecf20Sopenharmony_ci .get_sda = davinci_i2c_get_sda, 3798c2ecf20Sopenharmony_ci .prepare_recovery = davinci_i2c_scl_prepare_recovery, 3808c2ecf20Sopenharmony_ci .unprepare_recovery = davinci_i2c_scl_unprepare_recovery, 3818c2ecf20Sopenharmony_ci}; 3828c2ecf20Sopenharmony_ci 3838c2ecf20Sopenharmony_ci/* 3848c2ecf20Sopenharmony_ci * Waiting for bus not busy 3858c2ecf20Sopenharmony_ci */ 3868c2ecf20Sopenharmony_cistatic int i2c_davinci_wait_bus_not_busy(struct davinci_i2c_dev *dev) 3878c2ecf20Sopenharmony_ci{ 3888c2ecf20Sopenharmony_ci unsigned long timeout = jiffies + dev->adapter.timeout; 3898c2ecf20Sopenharmony_ci 3908c2ecf20Sopenharmony_ci do { 3918c2ecf20Sopenharmony_ci if (!(davinci_i2c_read_reg(dev, DAVINCI_I2C_STR_REG) & DAVINCI_I2C_STR_BB)) 3928c2ecf20Sopenharmony_ci return 0; 3938c2ecf20Sopenharmony_ci schedule_timeout_uninterruptible(1); 3948c2ecf20Sopenharmony_ci } while (time_before_eq(jiffies, timeout)); 3958c2ecf20Sopenharmony_ci 3968c2ecf20Sopenharmony_ci dev_warn(dev->dev, "timeout waiting for bus ready\n"); 3978c2ecf20Sopenharmony_ci i2c_recover_bus(&dev->adapter); 3988c2ecf20Sopenharmony_ci 3998c2ecf20Sopenharmony_ci /* 4008c2ecf20Sopenharmony_ci * if bus is still "busy" here, it's most probably a HW problem like 4018c2ecf20Sopenharmony_ci * short-circuit 4028c2ecf20Sopenharmony_ci */ 4038c2ecf20Sopenharmony_ci if (davinci_i2c_read_reg(dev, DAVINCI_I2C_STR_REG) & DAVINCI_I2C_STR_BB) 4048c2ecf20Sopenharmony_ci return -EIO; 4058c2ecf20Sopenharmony_ci 4068c2ecf20Sopenharmony_ci return 0; 4078c2ecf20Sopenharmony_ci} 4088c2ecf20Sopenharmony_ci 4098c2ecf20Sopenharmony_ci/* 4108c2ecf20Sopenharmony_ci * Low level master read/write transaction. This function is called 4118c2ecf20Sopenharmony_ci * from i2c_davinci_xfer. 4128c2ecf20Sopenharmony_ci */ 4138c2ecf20Sopenharmony_cistatic int 4148c2ecf20Sopenharmony_cii2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop) 4158c2ecf20Sopenharmony_ci{ 4168c2ecf20Sopenharmony_ci struct davinci_i2c_dev *dev = i2c_get_adapdata(adap); 4178c2ecf20Sopenharmony_ci struct davinci_i2c_platform_data *pdata = dev->pdata; 4188c2ecf20Sopenharmony_ci u32 flag; 4198c2ecf20Sopenharmony_ci u16 w; 4208c2ecf20Sopenharmony_ci unsigned long time_left; 4218c2ecf20Sopenharmony_ci 4228c2ecf20Sopenharmony_ci if (msg->addr == DAVINCI_I2C_OWN_ADDRESS) { 4238c2ecf20Sopenharmony_ci dev_warn(dev->dev, "transfer to own address aborted\n"); 4248c2ecf20Sopenharmony_ci return -EADDRNOTAVAIL; 4258c2ecf20Sopenharmony_ci } 4268c2ecf20Sopenharmony_ci 4278c2ecf20Sopenharmony_ci /* Introduce a delay, required for some boards (e.g Davinci EVM) */ 4288c2ecf20Sopenharmony_ci if (pdata->bus_delay) 4298c2ecf20Sopenharmony_ci udelay(pdata->bus_delay); 4308c2ecf20Sopenharmony_ci 4318c2ecf20Sopenharmony_ci /* set the slave address */ 4328c2ecf20Sopenharmony_ci davinci_i2c_write_reg(dev, DAVINCI_I2C_SAR_REG, msg->addr); 4338c2ecf20Sopenharmony_ci 4348c2ecf20Sopenharmony_ci dev->buf = msg->buf; 4358c2ecf20Sopenharmony_ci dev->buf_len = msg->len; 4368c2ecf20Sopenharmony_ci dev->stop = stop; 4378c2ecf20Sopenharmony_ci 4388c2ecf20Sopenharmony_ci davinci_i2c_write_reg(dev, DAVINCI_I2C_CNT_REG, dev->buf_len); 4398c2ecf20Sopenharmony_ci 4408c2ecf20Sopenharmony_ci reinit_completion(&dev->cmd_complete); 4418c2ecf20Sopenharmony_ci dev->cmd_err = 0; 4428c2ecf20Sopenharmony_ci 4438c2ecf20Sopenharmony_ci /* Take I2C out of reset and configure it as master */ 4448c2ecf20Sopenharmony_ci flag = DAVINCI_I2C_MDR_IRS | DAVINCI_I2C_MDR_MST; 4458c2ecf20Sopenharmony_ci 4468c2ecf20Sopenharmony_ci /* if the slave address is ten bit address, enable XA bit */ 4478c2ecf20Sopenharmony_ci if (msg->flags & I2C_M_TEN) 4488c2ecf20Sopenharmony_ci flag |= DAVINCI_I2C_MDR_XA; 4498c2ecf20Sopenharmony_ci if (!(msg->flags & I2C_M_RD)) 4508c2ecf20Sopenharmony_ci flag |= DAVINCI_I2C_MDR_TRX; 4518c2ecf20Sopenharmony_ci if (msg->len == 0) 4528c2ecf20Sopenharmony_ci flag |= DAVINCI_I2C_MDR_RM; 4538c2ecf20Sopenharmony_ci 4548c2ecf20Sopenharmony_ci /* Enable receive or transmit interrupts */ 4558c2ecf20Sopenharmony_ci w = davinci_i2c_read_reg(dev, DAVINCI_I2C_IMR_REG); 4568c2ecf20Sopenharmony_ci if (msg->flags & I2C_M_RD) 4578c2ecf20Sopenharmony_ci w |= DAVINCI_I2C_IMR_RRDY; 4588c2ecf20Sopenharmony_ci else 4598c2ecf20Sopenharmony_ci w |= DAVINCI_I2C_IMR_XRDY; 4608c2ecf20Sopenharmony_ci davinci_i2c_write_reg(dev, DAVINCI_I2C_IMR_REG, w); 4618c2ecf20Sopenharmony_ci 4628c2ecf20Sopenharmony_ci dev->terminate = 0; 4638c2ecf20Sopenharmony_ci 4648c2ecf20Sopenharmony_ci /* 4658c2ecf20Sopenharmony_ci * Write mode register first as needed for correct behaviour 4668c2ecf20Sopenharmony_ci * on OMAP-L138, but don't set STT yet to avoid a race with XRDY 4678c2ecf20Sopenharmony_ci * occurring before we have loaded DXR 4688c2ecf20Sopenharmony_ci */ 4698c2ecf20Sopenharmony_ci davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, flag); 4708c2ecf20Sopenharmony_ci 4718c2ecf20Sopenharmony_ci /* 4728c2ecf20Sopenharmony_ci * First byte should be set here, not after interrupt, 4738c2ecf20Sopenharmony_ci * because transmit-data-ready interrupt can come before 4748c2ecf20Sopenharmony_ci * NACK-interrupt during sending of previous message and 4758c2ecf20Sopenharmony_ci * ICDXR may have wrong data 4768c2ecf20Sopenharmony_ci * It also saves us one interrupt, slightly faster 4778c2ecf20Sopenharmony_ci */ 4788c2ecf20Sopenharmony_ci if ((!(msg->flags & I2C_M_RD)) && dev->buf_len) { 4798c2ecf20Sopenharmony_ci davinci_i2c_write_reg(dev, DAVINCI_I2C_DXR_REG, *dev->buf++); 4808c2ecf20Sopenharmony_ci dev->buf_len--; 4818c2ecf20Sopenharmony_ci } 4828c2ecf20Sopenharmony_ci 4838c2ecf20Sopenharmony_ci /* Set STT to begin transmit now DXR is loaded */ 4848c2ecf20Sopenharmony_ci flag |= DAVINCI_I2C_MDR_STT; 4858c2ecf20Sopenharmony_ci if (stop && msg->len != 0) 4868c2ecf20Sopenharmony_ci flag |= DAVINCI_I2C_MDR_STP; 4878c2ecf20Sopenharmony_ci davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, flag); 4888c2ecf20Sopenharmony_ci 4898c2ecf20Sopenharmony_ci time_left = wait_for_completion_timeout(&dev->cmd_complete, 4908c2ecf20Sopenharmony_ci dev->adapter.timeout); 4918c2ecf20Sopenharmony_ci if (!time_left) { 4928c2ecf20Sopenharmony_ci dev_err(dev->dev, "controller timed out\n"); 4938c2ecf20Sopenharmony_ci i2c_recover_bus(adap); 4948c2ecf20Sopenharmony_ci dev->buf_len = 0; 4958c2ecf20Sopenharmony_ci return -ETIMEDOUT; 4968c2ecf20Sopenharmony_ci } 4978c2ecf20Sopenharmony_ci if (dev->buf_len) { 4988c2ecf20Sopenharmony_ci /* This should be 0 if all bytes were transferred 4998c2ecf20Sopenharmony_ci * or dev->cmd_err denotes an error. 5008c2ecf20Sopenharmony_ci */ 5018c2ecf20Sopenharmony_ci dev_err(dev->dev, "abnormal termination buf_len=%zu\n", 5028c2ecf20Sopenharmony_ci dev->buf_len); 5038c2ecf20Sopenharmony_ci dev->terminate = 1; 5048c2ecf20Sopenharmony_ci wmb(); 5058c2ecf20Sopenharmony_ci dev->buf_len = 0; 5068c2ecf20Sopenharmony_ci return -EREMOTEIO; 5078c2ecf20Sopenharmony_ci } 5088c2ecf20Sopenharmony_ci 5098c2ecf20Sopenharmony_ci /* no error */ 5108c2ecf20Sopenharmony_ci if (likely(!dev->cmd_err)) 5118c2ecf20Sopenharmony_ci return msg->len; 5128c2ecf20Sopenharmony_ci 5138c2ecf20Sopenharmony_ci /* We have an error */ 5148c2ecf20Sopenharmony_ci if (dev->cmd_err & DAVINCI_I2C_STR_AL) { 5158c2ecf20Sopenharmony_ci i2c_davinci_init(dev); 5168c2ecf20Sopenharmony_ci return -EIO; 5178c2ecf20Sopenharmony_ci } 5188c2ecf20Sopenharmony_ci 5198c2ecf20Sopenharmony_ci if (dev->cmd_err & DAVINCI_I2C_STR_NACK) { 5208c2ecf20Sopenharmony_ci if (msg->flags & I2C_M_IGNORE_NAK) 5218c2ecf20Sopenharmony_ci return msg->len; 5228c2ecf20Sopenharmony_ci w = davinci_i2c_read_reg(dev, DAVINCI_I2C_MDR_REG); 5238c2ecf20Sopenharmony_ci w |= DAVINCI_I2C_MDR_STP; 5248c2ecf20Sopenharmony_ci davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, w); 5258c2ecf20Sopenharmony_ci return -EREMOTEIO; 5268c2ecf20Sopenharmony_ci } 5278c2ecf20Sopenharmony_ci return -EIO; 5288c2ecf20Sopenharmony_ci} 5298c2ecf20Sopenharmony_ci 5308c2ecf20Sopenharmony_ci/* 5318c2ecf20Sopenharmony_ci * Prepare controller for a transaction and call i2c_davinci_xfer_msg 5328c2ecf20Sopenharmony_ci */ 5338c2ecf20Sopenharmony_cistatic int 5348c2ecf20Sopenharmony_cii2c_davinci_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) 5358c2ecf20Sopenharmony_ci{ 5368c2ecf20Sopenharmony_ci struct davinci_i2c_dev *dev = i2c_get_adapdata(adap); 5378c2ecf20Sopenharmony_ci int i; 5388c2ecf20Sopenharmony_ci int ret; 5398c2ecf20Sopenharmony_ci 5408c2ecf20Sopenharmony_ci dev_dbg(dev->dev, "%s: msgs: %d\n", __func__, num); 5418c2ecf20Sopenharmony_ci 5428c2ecf20Sopenharmony_ci ret = pm_runtime_get_sync(dev->dev); 5438c2ecf20Sopenharmony_ci if (ret < 0) { 5448c2ecf20Sopenharmony_ci dev_err(dev->dev, "Failed to runtime_get device: %d\n", ret); 5458c2ecf20Sopenharmony_ci pm_runtime_put_noidle(dev->dev); 5468c2ecf20Sopenharmony_ci return ret; 5478c2ecf20Sopenharmony_ci } 5488c2ecf20Sopenharmony_ci 5498c2ecf20Sopenharmony_ci ret = i2c_davinci_wait_bus_not_busy(dev); 5508c2ecf20Sopenharmony_ci if (ret < 0) { 5518c2ecf20Sopenharmony_ci dev_warn(dev->dev, "timeout waiting for bus ready\n"); 5528c2ecf20Sopenharmony_ci goto out; 5538c2ecf20Sopenharmony_ci } 5548c2ecf20Sopenharmony_ci 5558c2ecf20Sopenharmony_ci for (i = 0; i < num; i++) { 5568c2ecf20Sopenharmony_ci ret = i2c_davinci_xfer_msg(adap, &msgs[i], (i == (num - 1))); 5578c2ecf20Sopenharmony_ci dev_dbg(dev->dev, "%s [%d/%d] ret: %d\n", __func__, i + 1, num, 5588c2ecf20Sopenharmony_ci ret); 5598c2ecf20Sopenharmony_ci if (ret < 0) 5608c2ecf20Sopenharmony_ci goto out; 5618c2ecf20Sopenharmony_ci } 5628c2ecf20Sopenharmony_ci 5638c2ecf20Sopenharmony_ci ret = num; 5648c2ecf20Sopenharmony_ci 5658c2ecf20Sopenharmony_ciout: 5668c2ecf20Sopenharmony_ci pm_runtime_mark_last_busy(dev->dev); 5678c2ecf20Sopenharmony_ci pm_runtime_put_autosuspend(dev->dev); 5688c2ecf20Sopenharmony_ci 5698c2ecf20Sopenharmony_ci return ret; 5708c2ecf20Sopenharmony_ci} 5718c2ecf20Sopenharmony_ci 5728c2ecf20Sopenharmony_cistatic u32 i2c_davinci_func(struct i2c_adapter *adap) 5738c2ecf20Sopenharmony_ci{ 5748c2ecf20Sopenharmony_ci return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; 5758c2ecf20Sopenharmony_ci} 5768c2ecf20Sopenharmony_ci 5778c2ecf20Sopenharmony_cistatic void terminate_read(struct davinci_i2c_dev *dev) 5788c2ecf20Sopenharmony_ci{ 5798c2ecf20Sopenharmony_ci u16 w = davinci_i2c_read_reg(dev, DAVINCI_I2C_MDR_REG); 5808c2ecf20Sopenharmony_ci w |= DAVINCI_I2C_MDR_NACK; 5818c2ecf20Sopenharmony_ci davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, w); 5828c2ecf20Sopenharmony_ci 5838c2ecf20Sopenharmony_ci /* Throw away data */ 5848c2ecf20Sopenharmony_ci davinci_i2c_read_reg(dev, DAVINCI_I2C_DRR_REG); 5858c2ecf20Sopenharmony_ci if (!dev->terminate) 5868c2ecf20Sopenharmony_ci dev_err(dev->dev, "RDR IRQ while no data requested\n"); 5878c2ecf20Sopenharmony_ci} 5888c2ecf20Sopenharmony_cistatic void terminate_write(struct davinci_i2c_dev *dev) 5898c2ecf20Sopenharmony_ci{ 5908c2ecf20Sopenharmony_ci u16 w = davinci_i2c_read_reg(dev, DAVINCI_I2C_MDR_REG); 5918c2ecf20Sopenharmony_ci w |= DAVINCI_I2C_MDR_RM | DAVINCI_I2C_MDR_STP; 5928c2ecf20Sopenharmony_ci davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, w); 5938c2ecf20Sopenharmony_ci 5948c2ecf20Sopenharmony_ci if (!dev->terminate) 5958c2ecf20Sopenharmony_ci dev_dbg(dev->dev, "TDR IRQ while no data to send\n"); 5968c2ecf20Sopenharmony_ci} 5978c2ecf20Sopenharmony_ci 5988c2ecf20Sopenharmony_ci/* 5998c2ecf20Sopenharmony_ci * Interrupt service routine. This gets called whenever an I2C interrupt 6008c2ecf20Sopenharmony_ci * occurs. 6018c2ecf20Sopenharmony_ci */ 6028c2ecf20Sopenharmony_cistatic irqreturn_t i2c_davinci_isr(int this_irq, void *dev_id) 6038c2ecf20Sopenharmony_ci{ 6048c2ecf20Sopenharmony_ci struct davinci_i2c_dev *dev = dev_id; 6058c2ecf20Sopenharmony_ci u32 stat; 6068c2ecf20Sopenharmony_ci int count = 0; 6078c2ecf20Sopenharmony_ci u16 w; 6088c2ecf20Sopenharmony_ci 6098c2ecf20Sopenharmony_ci if (pm_runtime_suspended(dev->dev)) 6108c2ecf20Sopenharmony_ci return IRQ_NONE; 6118c2ecf20Sopenharmony_ci 6128c2ecf20Sopenharmony_ci while ((stat = davinci_i2c_read_reg(dev, DAVINCI_I2C_IVR_REG))) { 6138c2ecf20Sopenharmony_ci dev_dbg(dev->dev, "%s: stat=0x%x\n", __func__, stat); 6148c2ecf20Sopenharmony_ci if (count++ == 100) { 6158c2ecf20Sopenharmony_ci dev_warn(dev->dev, "Too much work in one IRQ\n"); 6168c2ecf20Sopenharmony_ci break; 6178c2ecf20Sopenharmony_ci } 6188c2ecf20Sopenharmony_ci 6198c2ecf20Sopenharmony_ci switch (stat) { 6208c2ecf20Sopenharmony_ci case DAVINCI_I2C_IVR_AL: 6218c2ecf20Sopenharmony_ci /* Arbitration lost, must retry */ 6228c2ecf20Sopenharmony_ci dev->cmd_err |= DAVINCI_I2C_STR_AL; 6238c2ecf20Sopenharmony_ci dev->buf_len = 0; 6248c2ecf20Sopenharmony_ci complete(&dev->cmd_complete); 6258c2ecf20Sopenharmony_ci break; 6268c2ecf20Sopenharmony_ci 6278c2ecf20Sopenharmony_ci case DAVINCI_I2C_IVR_NACK: 6288c2ecf20Sopenharmony_ci dev->cmd_err |= DAVINCI_I2C_STR_NACK; 6298c2ecf20Sopenharmony_ci dev->buf_len = 0; 6308c2ecf20Sopenharmony_ci complete(&dev->cmd_complete); 6318c2ecf20Sopenharmony_ci break; 6328c2ecf20Sopenharmony_ci 6338c2ecf20Sopenharmony_ci case DAVINCI_I2C_IVR_ARDY: 6348c2ecf20Sopenharmony_ci davinci_i2c_write_reg(dev, 6358c2ecf20Sopenharmony_ci DAVINCI_I2C_STR_REG, DAVINCI_I2C_STR_ARDY); 6368c2ecf20Sopenharmony_ci if (((dev->buf_len == 0) && (dev->stop != 0)) || 6378c2ecf20Sopenharmony_ci (dev->cmd_err & DAVINCI_I2C_STR_NACK)) { 6388c2ecf20Sopenharmony_ci w = davinci_i2c_read_reg(dev, 6398c2ecf20Sopenharmony_ci DAVINCI_I2C_MDR_REG); 6408c2ecf20Sopenharmony_ci w |= DAVINCI_I2C_MDR_STP; 6418c2ecf20Sopenharmony_ci davinci_i2c_write_reg(dev, 6428c2ecf20Sopenharmony_ci DAVINCI_I2C_MDR_REG, w); 6438c2ecf20Sopenharmony_ci } 6448c2ecf20Sopenharmony_ci complete(&dev->cmd_complete); 6458c2ecf20Sopenharmony_ci break; 6468c2ecf20Sopenharmony_ci 6478c2ecf20Sopenharmony_ci case DAVINCI_I2C_IVR_RDR: 6488c2ecf20Sopenharmony_ci if (dev->buf_len) { 6498c2ecf20Sopenharmony_ci *dev->buf++ = 6508c2ecf20Sopenharmony_ci davinci_i2c_read_reg(dev, 6518c2ecf20Sopenharmony_ci DAVINCI_I2C_DRR_REG); 6528c2ecf20Sopenharmony_ci dev->buf_len--; 6538c2ecf20Sopenharmony_ci if (dev->buf_len) 6548c2ecf20Sopenharmony_ci continue; 6558c2ecf20Sopenharmony_ci 6568c2ecf20Sopenharmony_ci davinci_i2c_write_reg(dev, 6578c2ecf20Sopenharmony_ci DAVINCI_I2C_STR_REG, 6588c2ecf20Sopenharmony_ci DAVINCI_I2C_IMR_RRDY); 6598c2ecf20Sopenharmony_ci } else { 6608c2ecf20Sopenharmony_ci /* signal can terminate transfer */ 6618c2ecf20Sopenharmony_ci terminate_read(dev); 6628c2ecf20Sopenharmony_ci } 6638c2ecf20Sopenharmony_ci break; 6648c2ecf20Sopenharmony_ci 6658c2ecf20Sopenharmony_ci case DAVINCI_I2C_IVR_XRDY: 6668c2ecf20Sopenharmony_ci if (dev->buf_len) { 6678c2ecf20Sopenharmony_ci davinci_i2c_write_reg(dev, DAVINCI_I2C_DXR_REG, 6688c2ecf20Sopenharmony_ci *dev->buf++); 6698c2ecf20Sopenharmony_ci dev->buf_len--; 6708c2ecf20Sopenharmony_ci if (dev->buf_len) 6718c2ecf20Sopenharmony_ci continue; 6728c2ecf20Sopenharmony_ci 6738c2ecf20Sopenharmony_ci w = davinci_i2c_read_reg(dev, 6748c2ecf20Sopenharmony_ci DAVINCI_I2C_IMR_REG); 6758c2ecf20Sopenharmony_ci w &= ~DAVINCI_I2C_IMR_XRDY; 6768c2ecf20Sopenharmony_ci davinci_i2c_write_reg(dev, 6778c2ecf20Sopenharmony_ci DAVINCI_I2C_IMR_REG, 6788c2ecf20Sopenharmony_ci w); 6798c2ecf20Sopenharmony_ci } else { 6808c2ecf20Sopenharmony_ci /* signal can terminate transfer */ 6818c2ecf20Sopenharmony_ci terminate_write(dev); 6828c2ecf20Sopenharmony_ci } 6838c2ecf20Sopenharmony_ci break; 6848c2ecf20Sopenharmony_ci 6858c2ecf20Sopenharmony_ci case DAVINCI_I2C_IVR_SCD: 6868c2ecf20Sopenharmony_ci davinci_i2c_write_reg(dev, 6878c2ecf20Sopenharmony_ci DAVINCI_I2C_STR_REG, DAVINCI_I2C_STR_SCD); 6888c2ecf20Sopenharmony_ci complete(&dev->cmd_complete); 6898c2ecf20Sopenharmony_ci break; 6908c2ecf20Sopenharmony_ci 6918c2ecf20Sopenharmony_ci case DAVINCI_I2C_IVR_AAS: 6928c2ecf20Sopenharmony_ci dev_dbg(dev->dev, "Address as slave interrupt\n"); 6938c2ecf20Sopenharmony_ci break; 6948c2ecf20Sopenharmony_ci 6958c2ecf20Sopenharmony_ci default: 6968c2ecf20Sopenharmony_ci dev_warn(dev->dev, "Unrecognized irq stat %d\n", stat); 6978c2ecf20Sopenharmony_ci break; 6988c2ecf20Sopenharmony_ci } 6998c2ecf20Sopenharmony_ci } 7008c2ecf20Sopenharmony_ci 7018c2ecf20Sopenharmony_ci return count ? IRQ_HANDLED : IRQ_NONE; 7028c2ecf20Sopenharmony_ci} 7038c2ecf20Sopenharmony_ci 7048c2ecf20Sopenharmony_ci#ifdef CONFIG_CPU_FREQ 7058c2ecf20Sopenharmony_cistatic int i2c_davinci_cpufreq_transition(struct notifier_block *nb, 7068c2ecf20Sopenharmony_ci unsigned long val, void *data) 7078c2ecf20Sopenharmony_ci{ 7088c2ecf20Sopenharmony_ci struct davinci_i2c_dev *dev; 7098c2ecf20Sopenharmony_ci 7108c2ecf20Sopenharmony_ci dev = container_of(nb, struct davinci_i2c_dev, freq_transition); 7118c2ecf20Sopenharmony_ci 7128c2ecf20Sopenharmony_ci i2c_lock_bus(&dev->adapter, I2C_LOCK_ROOT_ADAPTER); 7138c2ecf20Sopenharmony_ci if (val == CPUFREQ_PRECHANGE) { 7148c2ecf20Sopenharmony_ci davinci_i2c_reset_ctrl(dev, 0); 7158c2ecf20Sopenharmony_ci } else if (val == CPUFREQ_POSTCHANGE) { 7168c2ecf20Sopenharmony_ci i2c_davinci_calc_clk_dividers(dev); 7178c2ecf20Sopenharmony_ci davinci_i2c_reset_ctrl(dev, 1); 7188c2ecf20Sopenharmony_ci } 7198c2ecf20Sopenharmony_ci i2c_unlock_bus(&dev->adapter, I2C_LOCK_ROOT_ADAPTER); 7208c2ecf20Sopenharmony_ci 7218c2ecf20Sopenharmony_ci return 0; 7228c2ecf20Sopenharmony_ci} 7238c2ecf20Sopenharmony_ci 7248c2ecf20Sopenharmony_cistatic inline int i2c_davinci_cpufreq_register(struct davinci_i2c_dev *dev) 7258c2ecf20Sopenharmony_ci{ 7268c2ecf20Sopenharmony_ci dev->freq_transition.notifier_call = i2c_davinci_cpufreq_transition; 7278c2ecf20Sopenharmony_ci 7288c2ecf20Sopenharmony_ci return cpufreq_register_notifier(&dev->freq_transition, 7298c2ecf20Sopenharmony_ci CPUFREQ_TRANSITION_NOTIFIER); 7308c2ecf20Sopenharmony_ci} 7318c2ecf20Sopenharmony_ci 7328c2ecf20Sopenharmony_cistatic inline void i2c_davinci_cpufreq_deregister(struct davinci_i2c_dev *dev) 7338c2ecf20Sopenharmony_ci{ 7348c2ecf20Sopenharmony_ci cpufreq_unregister_notifier(&dev->freq_transition, 7358c2ecf20Sopenharmony_ci CPUFREQ_TRANSITION_NOTIFIER); 7368c2ecf20Sopenharmony_ci} 7378c2ecf20Sopenharmony_ci#else 7388c2ecf20Sopenharmony_cistatic inline int i2c_davinci_cpufreq_register(struct davinci_i2c_dev *dev) 7398c2ecf20Sopenharmony_ci{ 7408c2ecf20Sopenharmony_ci return 0; 7418c2ecf20Sopenharmony_ci} 7428c2ecf20Sopenharmony_ci 7438c2ecf20Sopenharmony_cistatic inline void i2c_davinci_cpufreq_deregister(struct davinci_i2c_dev *dev) 7448c2ecf20Sopenharmony_ci{ 7458c2ecf20Sopenharmony_ci} 7468c2ecf20Sopenharmony_ci#endif 7478c2ecf20Sopenharmony_ci 7488c2ecf20Sopenharmony_cistatic const struct i2c_algorithm i2c_davinci_algo = { 7498c2ecf20Sopenharmony_ci .master_xfer = i2c_davinci_xfer, 7508c2ecf20Sopenharmony_ci .functionality = i2c_davinci_func, 7518c2ecf20Sopenharmony_ci}; 7528c2ecf20Sopenharmony_ci 7538c2ecf20Sopenharmony_cistatic const struct of_device_id davinci_i2c_of_match[] = { 7548c2ecf20Sopenharmony_ci {.compatible = "ti,davinci-i2c", }, 7558c2ecf20Sopenharmony_ci {.compatible = "ti,keystone-i2c", }, 7568c2ecf20Sopenharmony_ci {}, 7578c2ecf20Sopenharmony_ci}; 7588c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(of, davinci_i2c_of_match); 7598c2ecf20Sopenharmony_ci 7608c2ecf20Sopenharmony_cistatic int davinci_i2c_probe(struct platform_device *pdev) 7618c2ecf20Sopenharmony_ci{ 7628c2ecf20Sopenharmony_ci struct davinci_i2c_dev *dev; 7638c2ecf20Sopenharmony_ci struct i2c_adapter *adap; 7648c2ecf20Sopenharmony_ci struct i2c_bus_recovery_info *rinfo; 7658c2ecf20Sopenharmony_ci int r, irq; 7668c2ecf20Sopenharmony_ci 7678c2ecf20Sopenharmony_ci irq = platform_get_irq(pdev, 0); 7688c2ecf20Sopenharmony_ci if (irq <= 0) { 7698c2ecf20Sopenharmony_ci if (!irq) 7708c2ecf20Sopenharmony_ci irq = -ENXIO; 7718c2ecf20Sopenharmony_ci if (irq != -EPROBE_DEFER) 7728c2ecf20Sopenharmony_ci dev_err(&pdev->dev, 7738c2ecf20Sopenharmony_ci "can't get irq resource ret=%d\n", irq); 7748c2ecf20Sopenharmony_ci return irq; 7758c2ecf20Sopenharmony_ci } 7768c2ecf20Sopenharmony_ci 7778c2ecf20Sopenharmony_ci dev = devm_kzalloc(&pdev->dev, sizeof(struct davinci_i2c_dev), 7788c2ecf20Sopenharmony_ci GFP_KERNEL); 7798c2ecf20Sopenharmony_ci if (!dev) { 7808c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "Memory allocation failed\n"); 7818c2ecf20Sopenharmony_ci return -ENOMEM; 7828c2ecf20Sopenharmony_ci } 7838c2ecf20Sopenharmony_ci 7848c2ecf20Sopenharmony_ci init_completion(&dev->cmd_complete); 7858c2ecf20Sopenharmony_ci 7868c2ecf20Sopenharmony_ci dev->dev = &pdev->dev; 7878c2ecf20Sopenharmony_ci dev->irq = irq; 7888c2ecf20Sopenharmony_ci dev->pdata = dev_get_platdata(&pdev->dev); 7898c2ecf20Sopenharmony_ci platform_set_drvdata(pdev, dev); 7908c2ecf20Sopenharmony_ci 7918c2ecf20Sopenharmony_ci if (!dev->pdata && pdev->dev.of_node) { 7928c2ecf20Sopenharmony_ci u32 prop; 7938c2ecf20Sopenharmony_ci 7948c2ecf20Sopenharmony_ci dev->pdata = devm_kzalloc(&pdev->dev, 7958c2ecf20Sopenharmony_ci sizeof(struct davinci_i2c_platform_data), GFP_KERNEL); 7968c2ecf20Sopenharmony_ci if (!dev->pdata) 7978c2ecf20Sopenharmony_ci return -ENOMEM; 7988c2ecf20Sopenharmony_ci 7998c2ecf20Sopenharmony_ci memcpy(dev->pdata, &davinci_i2c_platform_data_default, 8008c2ecf20Sopenharmony_ci sizeof(struct davinci_i2c_platform_data)); 8018c2ecf20Sopenharmony_ci if (!of_property_read_u32(pdev->dev.of_node, "clock-frequency", 8028c2ecf20Sopenharmony_ci &prop)) 8038c2ecf20Sopenharmony_ci dev->pdata->bus_freq = prop / 1000; 8048c2ecf20Sopenharmony_ci 8058c2ecf20Sopenharmony_ci dev->pdata->has_pfunc = 8068c2ecf20Sopenharmony_ci of_property_read_bool(pdev->dev.of_node, 8078c2ecf20Sopenharmony_ci "ti,has-pfunc"); 8088c2ecf20Sopenharmony_ci } else if (!dev->pdata) { 8098c2ecf20Sopenharmony_ci dev->pdata = &davinci_i2c_platform_data_default; 8108c2ecf20Sopenharmony_ci } 8118c2ecf20Sopenharmony_ci 8128c2ecf20Sopenharmony_ci dev->clk = devm_clk_get(&pdev->dev, NULL); 8138c2ecf20Sopenharmony_ci if (IS_ERR(dev->clk)) 8148c2ecf20Sopenharmony_ci return PTR_ERR(dev->clk); 8158c2ecf20Sopenharmony_ci 8168c2ecf20Sopenharmony_ci dev->base = devm_platform_ioremap_resource(pdev, 0); 8178c2ecf20Sopenharmony_ci if (IS_ERR(dev->base)) { 8188c2ecf20Sopenharmony_ci return PTR_ERR(dev->base); 8198c2ecf20Sopenharmony_ci } 8208c2ecf20Sopenharmony_ci 8218c2ecf20Sopenharmony_ci pm_runtime_set_autosuspend_delay(dev->dev, 8228c2ecf20Sopenharmony_ci DAVINCI_I2C_PM_TIMEOUT); 8238c2ecf20Sopenharmony_ci pm_runtime_use_autosuspend(dev->dev); 8248c2ecf20Sopenharmony_ci 8258c2ecf20Sopenharmony_ci pm_runtime_enable(dev->dev); 8268c2ecf20Sopenharmony_ci 8278c2ecf20Sopenharmony_ci r = pm_runtime_get_sync(dev->dev); 8288c2ecf20Sopenharmony_ci if (r < 0) { 8298c2ecf20Sopenharmony_ci dev_err(dev->dev, "failed to runtime_get device: %d\n", r); 8308c2ecf20Sopenharmony_ci pm_runtime_put_noidle(dev->dev); 8318c2ecf20Sopenharmony_ci return r; 8328c2ecf20Sopenharmony_ci } 8338c2ecf20Sopenharmony_ci 8348c2ecf20Sopenharmony_ci i2c_davinci_init(dev); 8358c2ecf20Sopenharmony_ci 8368c2ecf20Sopenharmony_ci r = devm_request_irq(&pdev->dev, dev->irq, i2c_davinci_isr, 0, 8378c2ecf20Sopenharmony_ci pdev->name, dev); 8388c2ecf20Sopenharmony_ci if (r) { 8398c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "failure requesting irq %i\n", dev->irq); 8408c2ecf20Sopenharmony_ci goto err_unuse_clocks; 8418c2ecf20Sopenharmony_ci } 8428c2ecf20Sopenharmony_ci 8438c2ecf20Sopenharmony_ci r = i2c_davinci_cpufreq_register(dev); 8448c2ecf20Sopenharmony_ci if (r) { 8458c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "failed to register cpufreq\n"); 8468c2ecf20Sopenharmony_ci goto err_unuse_clocks; 8478c2ecf20Sopenharmony_ci } 8488c2ecf20Sopenharmony_ci 8498c2ecf20Sopenharmony_ci adap = &dev->adapter; 8508c2ecf20Sopenharmony_ci i2c_set_adapdata(adap, dev); 8518c2ecf20Sopenharmony_ci adap->owner = THIS_MODULE; 8528c2ecf20Sopenharmony_ci adap->class = I2C_CLASS_DEPRECATED; 8538c2ecf20Sopenharmony_ci strlcpy(adap->name, "DaVinci I2C adapter", sizeof(adap->name)); 8548c2ecf20Sopenharmony_ci adap->algo = &i2c_davinci_algo; 8558c2ecf20Sopenharmony_ci adap->dev.parent = &pdev->dev; 8568c2ecf20Sopenharmony_ci adap->timeout = DAVINCI_I2C_TIMEOUT; 8578c2ecf20Sopenharmony_ci adap->dev.of_node = pdev->dev.of_node; 8588c2ecf20Sopenharmony_ci 8598c2ecf20Sopenharmony_ci if (dev->pdata->has_pfunc) 8608c2ecf20Sopenharmony_ci adap->bus_recovery_info = &davinci_i2c_scl_recovery_info; 8618c2ecf20Sopenharmony_ci else if (dev->pdata->gpio_recovery) { 8628c2ecf20Sopenharmony_ci rinfo = &davinci_i2c_gpio_recovery_info; 8638c2ecf20Sopenharmony_ci adap->bus_recovery_info = rinfo; 8648c2ecf20Sopenharmony_ci rinfo->scl_gpiod = devm_gpiod_get(&pdev->dev, "scl", 8658c2ecf20Sopenharmony_ci GPIOD_OUT_HIGH_OPEN_DRAIN); 8668c2ecf20Sopenharmony_ci if (IS_ERR(rinfo->scl_gpiod)) { 8678c2ecf20Sopenharmony_ci r = PTR_ERR(rinfo->scl_gpiod); 8688c2ecf20Sopenharmony_ci goto err_unuse_clocks; 8698c2ecf20Sopenharmony_ci } 8708c2ecf20Sopenharmony_ci rinfo->sda_gpiod = devm_gpiod_get(&pdev->dev, "sda", GPIOD_IN); 8718c2ecf20Sopenharmony_ci if (IS_ERR(rinfo->sda_gpiod)) { 8728c2ecf20Sopenharmony_ci r = PTR_ERR(rinfo->sda_gpiod); 8738c2ecf20Sopenharmony_ci goto err_unuse_clocks; 8748c2ecf20Sopenharmony_ci } 8758c2ecf20Sopenharmony_ci } 8768c2ecf20Sopenharmony_ci 8778c2ecf20Sopenharmony_ci adap->nr = pdev->id; 8788c2ecf20Sopenharmony_ci r = i2c_add_numbered_adapter(adap); 8798c2ecf20Sopenharmony_ci if (r) 8808c2ecf20Sopenharmony_ci goto err_unuse_clocks; 8818c2ecf20Sopenharmony_ci 8828c2ecf20Sopenharmony_ci pm_runtime_mark_last_busy(dev->dev); 8838c2ecf20Sopenharmony_ci pm_runtime_put_autosuspend(dev->dev); 8848c2ecf20Sopenharmony_ci 8858c2ecf20Sopenharmony_ci return 0; 8868c2ecf20Sopenharmony_ci 8878c2ecf20Sopenharmony_cierr_unuse_clocks: 8888c2ecf20Sopenharmony_ci pm_runtime_dont_use_autosuspend(dev->dev); 8898c2ecf20Sopenharmony_ci pm_runtime_put_sync(dev->dev); 8908c2ecf20Sopenharmony_ci pm_runtime_disable(dev->dev); 8918c2ecf20Sopenharmony_ci 8928c2ecf20Sopenharmony_ci return r; 8938c2ecf20Sopenharmony_ci} 8948c2ecf20Sopenharmony_ci 8958c2ecf20Sopenharmony_cistatic int davinci_i2c_remove(struct platform_device *pdev) 8968c2ecf20Sopenharmony_ci{ 8978c2ecf20Sopenharmony_ci struct davinci_i2c_dev *dev = platform_get_drvdata(pdev); 8988c2ecf20Sopenharmony_ci int ret; 8998c2ecf20Sopenharmony_ci 9008c2ecf20Sopenharmony_ci i2c_davinci_cpufreq_deregister(dev); 9018c2ecf20Sopenharmony_ci 9028c2ecf20Sopenharmony_ci i2c_del_adapter(&dev->adapter); 9038c2ecf20Sopenharmony_ci 9048c2ecf20Sopenharmony_ci ret = pm_runtime_get_sync(&pdev->dev); 9058c2ecf20Sopenharmony_ci if (ret < 0) { 9068c2ecf20Sopenharmony_ci pm_runtime_put_noidle(&pdev->dev); 9078c2ecf20Sopenharmony_ci return ret; 9088c2ecf20Sopenharmony_ci } 9098c2ecf20Sopenharmony_ci 9108c2ecf20Sopenharmony_ci davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, 0); 9118c2ecf20Sopenharmony_ci 9128c2ecf20Sopenharmony_ci pm_runtime_dont_use_autosuspend(dev->dev); 9138c2ecf20Sopenharmony_ci pm_runtime_put_sync(dev->dev); 9148c2ecf20Sopenharmony_ci pm_runtime_disable(dev->dev); 9158c2ecf20Sopenharmony_ci 9168c2ecf20Sopenharmony_ci return 0; 9178c2ecf20Sopenharmony_ci} 9188c2ecf20Sopenharmony_ci 9198c2ecf20Sopenharmony_ci#ifdef CONFIG_PM 9208c2ecf20Sopenharmony_cistatic int davinci_i2c_suspend(struct device *dev) 9218c2ecf20Sopenharmony_ci{ 9228c2ecf20Sopenharmony_ci struct davinci_i2c_dev *i2c_dev = dev_get_drvdata(dev); 9238c2ecf20Sopenharmony_ci 9248c2ecf20Sopenharmony_ci /* put I2C into reset */ 9258c2ecf20Sopenharmony_ci davinci_i2c_reset_ctrl(i2c_dev, 0); 9268c2ecf20Sopenharmony_ci 9278c2ecf20Sopenharmony_ci return 0; 9288c2ecf20Sopenharmony_ci} 9298c2ecf20Sopenharmony_ci 9308c2ecf20Sopenharmony_cistatic int davinci_i2c_resume(struct device *dev) 9318c2ecf20Sopenharmony_ci{ 9328c2ecf20Sopenharmony_ci struct davinci_i2c_dev *i2c_dev = dev_get_drvdata(dev); 9338c2ecf20Sopenharmony_ci 9348c2ecf20Sopenharmony_ci /* take I2C out of reset */ 9358c2ecf20Sopenharmony_ci davinci_i2c_reset_ctrl(i2c_dev, 1); 9368c2ecf20Sopenharmony_ci 9378c2ecf20Sopenharmony_ci return 0; 9388c2ecf20Sopenharmony_ci} 9398c2ecf20Sopenharmony_ci 9408c2ecf20Sopenharmony_cistatic const struct dev_pm_ops davinci_i2c_pm = { 9418c2ecf20Sopenharmony_ci .suspend = davinci_i2c_suspend, 9428c2ecf20Sopenharmony_ci .resume = davinci_i2c_resume, 9438c2ecf20Sopenharmony_ci SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, 9448c2ecf20Sopenharmony_ci pm_runtime_force_resume) 9458c2ecf20Sopenharmony_ci}; 9468c2ecf20Sopenharmony_ci 9478c2ecf20Sopenharmony_ci#define davinci_i2c_pm_ops (&davinci_i2c_pm) 9488c2ecf20Sopenharmony_ci#else 9498c2ecf20Sopenharmony_ci#define davinci_i2c_pm_ops NULL 9508c2ecf20Sopenharmony_ci#endif 9518c2ecf20Sopenharmony_ci 9528c2ecf20Sopenharmony_ci/* work with hotplug and coldplug */ 9538c2ecf20Sopenharmony_ciMODULE_ALIAS("platform:i2c_davinci"); 9548c2ecf20Sopenharmony_ci 9558c2ecf20Sopenharmony_cistatic struct platform_driver davinci_i2c_driver = { 9568c2ecf20Sopenharmony_ci .probe = davinci_i2c_probe, 9578c2ecf20Sopenharmony_ci .remove = davinci_i2c_remove, 9588c2ecf20Sopenharmony_ci .driver = { 9598c2ecf20Sopenharmony_ci .name = "i2c_davinci", 9608c2ecf20Sopenharmony_ci .pm = davinci_i2c_pm_ops, 9618c2ecf20Sopenharmony_ci .of_match_table = davinci_i2c_of_match, 9628c2ecf20Sopenharmony_ci }, 9638c2ecf20Sopenharmony_ci}; 9648c2ecf20Sopenharmony_ci 9658c2ecf20Sopenharmony_ci/* I2C may be needed to bring up other drivers */ 9668c2ecf20Sopenharmony_cistatic int __init davinci_i2c_init_driver(void) 9678c2ecf20Sopenharmony_ci{ 9688c2ecf20Sopenharmony_ci return platform_driver_register(&davinci_i2c_driver); 9698c2ecf20Sopenharmony_ci} 9708c2ecf20Sopenharmony_cisubsys_initcall(davinci_i2c_init_driver); 9718c2ecf20Sopenharmony_ci 9728c2ecf20Sopenharmony_cistatic void __exit davinci_i2c_exit_driver(void) 9738c2ecf20Sopenharmony_ci{ 9748c2ecf20Sopenharmony_ci platform_driver_unregister(&davinci_i2c_driver); 9758c2ecf20Sopenharmony_ci} 9768c2ecf20Sopenharmony_cimodule_exit(davinci_i2c_exit_driver); 9778c2ecf20Sopenharmony_ci 9788c2ecf20Sopenharmony_ciMODULE_AUTHOR("Texas Instruments India"); 9798c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("TI DaVinci I2C bus adapter"); 9808c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 981