1/* 2 * Copyright 2011, Netlogic Microsystems Inc. 3 * Copyright 2004, Matt Porter <mporter@kernel.crashing.org> 4 * 5 * This file is licensed under the terms of the GNU General Public 6 * License version 2. This program is licensed "as is" without any 7 * warranty of any kind, whether express or implied. 8 */ 9 10#include <linux/err.h> 11#include <linux/kernel.h> 12#include <linux/module.h> 13#include <linux/slab.h> 14#include <linux/ioport.h> 15#include <linux/delay.h> 16#include <linux/errno.h> 17#include <linux/i2c.h> 18#include <linux/io.h> 19#include <linux/platform_device.h> 20 21/* XLR I2C REGISTERS */ 22#define XLR_I2C_CFG 0x00 23#define XLR_I2C_CLKDIV 0x01 24#define XLR_I2C_DEVADDR 0x02 25#define XLR_I2C_ADDR 0x03 26#define XLR_I2C_DATAOUT 0x04 27#define XLR_I2C_DATAIN 0x05 28#define XLR_I2C_STATUS 0x06 29#define XLR_I2C_STARTXFR 0x07 30#define XLR_I2C_BYTECNT 0x08 31#define XLR_I2C_HDSTATIM 0x09 32 33/* XLR I2C REGISTERS FLAGS */ 34#define XLR_I2C_BUS_BUSY 0x01 35#define XLR_I2C_SDOEMPTY 0x02 36#define XLR_I2C_RXRDY 0x04 37#define XLR_I2C_ACK_ERR 0x08 38#define XLR_I2C_ARB_STARTERR 0x30 39 40/* Register Values */ 41#define XLR_I2C_CFG_ADDR 0xF8 42#define XLR_I2C_CFG_NOADDR 0xFA 43#define XLR_I2C_STARTXFR_ND 0x02 /* No Data */ 44#define XLR_I2C_STARTXFR_RD 0x01 /* Read */ 45#define XLR_I2C_STARTXFR_WR 0x00 /* Write */ 46 47#define XLR_I2C_TIMEOUT 10 /* timeout per byte in msec */ 48 49/* 50 * On XLR/XLS, we need to use __raw_ IO to read the I2C registers 51 * because they are in the big-endian MMIO area on the SoC. 52 * 53 * The readl/writel implementation on XLR/XLS byteswaps, because 54 * those are for its little-endian PCI space (see arch/mips/Kconfig). 55 */ 56static inline void xlr_i2c_wreg(u32 __iomem *base, unsigned int reg, u32 val) 57{ 58 __raw_writel(val, base + reg); 59} 60 61static inline u32 xlr_i2c_rdreg(u32 __iomem *base, unsigned int reg) 62{ 63 return __raw_readl(base + reg); 64} 65 66struct xlr_i2c_private { 67 struct i2c_adapter adap; 68 u32 __iomem *iobase; 69}; 70 71static int xlr_i2c_tx(struct xlr_i2c_private *priv, u16 len, 72 u8 *buf, u16 addr) 73{ 74 struct i2c_adapter *adap = &priv->adap; 75 unsigned long timeout, stoptime, checktime; 76 u32 i2c_status; 77 int pos, timedout; 78 u8 offset, byte; 79 80 offset = buf[0]; 81 xlr_i2c_wreg(priv->iobase, XLR_I2C_ADDR, offset); 82 xlr_i2c_wreg(priv->iobase, XLR_I2C_DEVADDR, addr); 83 xlr_i2c_wreg(priv->iobase, XLR_I2C_CFG, XLR_I2C_CFG_ADDR); 84 xlr_i2c_wreg(priv->iobase, XLR_I2C_BYTECNT, len - 1); 85 86 timeout = msecs_to_jiffies(XLR_I2C_TIMEOUT); 87 stoptime = jiffies + timeout; 88 timedout = 0; 89 pos = 1; 90retry: 91 if (len == 1) { 92 xlr_i2c_wreg(priv->iobase, XLR_I2C_STARTXFR, 93 XLR_I2C_STARTXFR_ND); 94 } else { 95 xlr_i2c_wreg(priv->iobase, XLR_I2C_DATAOUT, buf[pos]); 96 xlr_i2c_wreg(priv->iobase, XLR_I2C_STARTXFR, 97 XLR_I2C_STARTXFR_WR); 98 } 99 100 while (!timedout) { 101 checktime = jiffies; 102 i2c_status = xlr_i2c_rdreg(priv->iobase, XLR_I2C_STATUS); 103 104 if (i2c_status & XLR_I2C_SDOEMPTY) { 105 pos++; 106 /* need to do a empty dataout after the last byte */ 107 byte = (pos < len) ? buf[pos] : 0; 108 xlr_i2c_wreg(priv->iobase, XLR_I2C_DATAOUT, byte); 109 110 /* reset timeout on successful xmit */ 111 stoptime = jiffies + timeout; 112 } 113 timedout = time_after(checktime, stoptime); 114 115 if (i2c_status & XLR_I2C_ARB_STARTERR) { 116 if (timedout) 117 break; 118 goto retry; 119 } 120 121 if (i2c_status & XLR_I2C_ACK_ERR) 122 return -EIO; 123 124 if ((i2c_status & XLR_I2C_BUS_BUSY) == 0 && pos >= len) 125 return 0; 126 } 127 dev_err(&adap->dev, "I2C transmit timeout\n"); 128 return -ETIMEDOUT; 129} 130 131static int xlr_i2c_rx(struct xlr_i2c_private *priv, u16 len, u8 *buf, u16 addr) 132{ 133 struct i2c_adapter *adap = &priv->adap; 134 u32 i2c_status; 135 unsigned long timeout, stoptime, checktime; 136 int nbytes, timedout; 137 u8 byte; 138 139 xlr_i2c_wreg(priv->iobase, XLR_I2C_CFG, XLR_I2C_CFG_NOADDR); 140 xlr_i2c_wreg(priv->iobase, XLR_I2C_BYTECNT, len); 141 xlr_i2c_wreg(priv->iobase, XLR_I2C_DEVADDR, addr); 142 143 timeout = msecs_to_jiffies(XLR_I2C_TIMEOUT); 144 stoptime = jiffies + timeout; 145 timedout = 0; 146 nbytes = 0; 147retry: 148 xlr_i2c_wreg(priv->iobase, XLR_I2C_STARTXFR, XLR_I2C_STARTXFR_RD); 149 150 while (!timedout) { 151 checktime = jiffies; 152 i2c_status = xlr_i2c_rdreg(priv->iobase, XLR_I2C_STATUS); 153 if (i2c_status & XLR_I2C_RXRDY) { 154 if (nbytes > len) 155 return -EIO; /* should not happen */ 156 157 /* we need to do a dummy datain when nbytes == len */ 158 byte = xlr_i2c_rdreg(priv->iobase, XLR_I2C_DATAIN); 159 if (nbytes < len) 160 buf[nbytes] = byte; 161 nbytes++; 162 163 /* reset timeout on successful read */ 164 stoptime = jiffies + timeout; 165 } 166 167 timedout = time_after(checktime, stoptime); 168 if (i2c_status & XLR_I2C_ARB_STARTERR) { 169 if (timedout) 170 break; 171 goto retry; 172 } 173 174 if (i2c_status & XLR_I2C_ACK_ERR) 175 return -EIO; 176 177 if ((i2c_status & XLR_I2C_BUS_BUSY) == 0) 178 return 0; 179 } 180 181 dev_err(&adap->dev, "I2C receive timeout\n"); 182 return -ETIMEDOUT; 183} 184 185static int xlr_i2c_xfer(struct i2c_adapter *adap, 186 struct i2c_msg *msgs, int num) 187{ 188 struct i2c_msg *msg; 189 int i; 190 int ret = 0; 191 struct xlr_i2c_private *priv = i2c_get_adapdata(adap); 192 193 for (i = 0; ret == 0 && i < num; i++) { 194 msg = &msgs[i]; 195 if (msg->flags & I2C_M_RD) 196 ret = xlr_i2c_rx(priv, msg->len, &msg->buf[0], 197 msg->addr); 198 else 199 ret = xlr_i2c_tx(priv, msg->len, &msg->buf[0], 200 msg->addr); 201 } 202 203 return (ret != 0) ? ret : num; 204} 205 206static u32 xlr_func(struct i2c_adapter *adap) 207{ 208 /* Emulate SMBUS over I2C */ 209 return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_I2C; 210} 211 212static struct i2c_algorithm xlr_i2c_algo = { 213 .master_xfer = xlr_i2c_xfer, 214 .functionality = xlr_func, 215}; 216 217static int xlr_i2c_probe(struct platform_device *pdev) 218{ 219 struct xlr_i2c_private *priv; 220 struct resource *res; 221 int ret; 222 223 priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); 224 if (!priv) 225 return -ENOMEM; 226 227 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 228 priv->iobase = devm_ioremap_resource(&pdev->dev, res); 229 if (IS_ERR(priv->iobase)) 230 return PTR_ERR(priv->iobase); 231 232 priv->adap.dev.parent = &pdev->dev; 233 priv->adap.owner = THIS_MODULE; 234 priv->adap.algo_data = priv; 235 priv->adap.algo = &xlr_i2c_algo; 236 priv->adap.nr = pdev->id; 237 priv->adap.class = I2C_CLASS_HWMON; 238 snprintf(priv->adap.name, sizeof(priv->adap.name), "xlr-i2c"); 239 240 i2c_set_adapdata(&priv->adap, priv); 241 ret = i2c_add_numbered_adapter(&priv->adap); 242 if (ret < 0) { 243 dev_err(&priv->adap.dev, "Failed to add i2c bus.\n"); 244 return ret; 245 } 246 247 platform_set_drvdata(pdev, priv); 248 dev_info(&priv->adap.dev, "Added I2C Bus.\n"); 249 return 0; 250} 251 252static int xlr_i2c_remove(struct platform_device *pdev) 253{ 254 struct xlr_i2c_private *priv; 255 256 priv = platform_get_drvdata(pdev); 257 i2c_del_adapter(&priv->adap); 258 return 0; 259} 260 261static struct platform_driver xlr_i2c_driver = { 262 .probe = xlr_i2c_probe, 263 .remove = xlr_i2c_remove, 264 .driver = { 265 .name = "xlr-i2cbus", 266 }, 267}; 268 269module_platform_driver(xlr_i2c_driver); 270 271MODULE_AUTHOR("Ganesan Ramalingam <ganesanr@netlogicmicro.com>"); 272MODULE_DESCRIPTION("XLR/XLS SoC I2C Controller driver"); 273MODULE_LICENSE("GPL v2"); 274MODULE_ALIAS("platform:xlr-i2cbus"); 275