2 * Copyright 2011, Netlogic Microsystems Inc.
3 * Copyright 2004, Matt Porter <mporter@kernel.crashing.org>
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.
10 #include <linux/err.h>
11 #include <linux/kernel.h>
12 #include <linux/module.h>
13 #include <linux/slab.h>
14 #include <linux/init.h>
15 #include <linux/ioport.h>
16 #include <linux/delay.h>
17 #include <linux/errno.h>
18 #include <linux/i2c.h>
20 #include <linux/platform_device.h>
22 /* XLR I2C REGISTERS */
23 #define XLR_I2C_CFG 0x00
24 #define XLR_I2C_CLKDIV 0x01
25 #define XLR_I2C_DEVADDR 0x02
26 #define XLR_I2C_ADDR 0x03
27 #define XLR_I2C_DATAOUT 0x04
28 #define XLR_I2C_DATAIN 0x05
29 #define XLR_I2C_STATUS 0x06
30 #define XLR_I2C_STARTXFR 0x07
31 #define XLR_I2C_BYTECNT 0x08
32 #define XLR_I2C_HDSTATIM 0x09
34 /* XLR I2C REGISTERS FLAGS */
35 #define XLR_I2C_BUS_BUSY 0x01
36 #define XLR_I2C_SDOEMPTY 0x02
37 #define XLR_I2C_RXRDY 0x04
38 #define XLR_I2C_ACK_ERR 0x08
39 #define XLR_I2C_ARB_STARTERR 0x30
42 #define XLR_I2C_CFG_ADDR 0xF8
43 #define XLR_I2C_CFG_NOADDR 0xFA
44 #define XLR_I2C_STARTXFR_ND 0x02 /* No Data */
45 #define XLR_I2C_STARTXFR_RD 0x01 /* Read */
46 #define XLR_I2C_STARTXFR_WR 0x00 /* Write */
48 #define XLR_I2C_TIMEOUT 10 /* timeout per byte in msec */
51 * On XLR/XLS, we need to use __raw_ IO to read the I2C registers
52 * because they are in the big-endian MMIO area on the SoC.
54 * The readl/writel implementation on XLR/XLS byteswaps, because
55 * those are for its little-endian PCI space (see arch/mips/Kconfig).
57 static inline void xlr_i2c_wreg(u32 __iomem
*base
, unsigned int reg
, u32 val
)
59 __raw_writel(val
, base
+ reg
);
62 static inline u32
xlr_i2c_rdreg(u32 __iomem
*base
, unsigned int reg
)
64 return __raw_readl(base
+ reg
);
67 struct xlr_i2c_private
{
68 struct i2c_adapter adap
;
72 static int xlr_i2c_tx(struct xlr_i2c_private
*priv
, u16 len
,
75 struct i2c_adapter
*adap
= &priv
->adap
;
76 unsigned long timeout
, stoptime
, checktime
;
82 xlr_i2c_wreg(priv
->iobase
, XLR_I2C_ADDR
, offset
);
83 xlr_i2c_wreg(priv
->iobase
, XLR_I2C_DEVADDR
, addr
);
84 xlr_i2c_wreg(priv
->iobase
, XLR_I2C_CFG
, XLR_I2C_CFG_ADDR
);
85 xlr_i2c_wreg(priv
->iobase
, XLR_I2C_BYTECNT
, len
- 1);
87 timeout
= msecs_to_jiffies(XLR_I2C_TIMEOUT
);
88 stoptime
= jiffies
+ timeout
;
93 xlr_i2c_wreg(priv
->iobase
, XLR_I2C_STARTXFR
,
96 xlr_i2c_wreg(priv
->iobase
, XLR_I2C_DATAOUT
, buf
[pos
]);
97 xlr_i2c_wreg(priv
->iobase
, XLR_I2C_STARTXFR
,
103 i2c_status
= xlr_i2c_rdreg(priv
->iobase
, XLR_I2C_STATUS
);
105 if (i2c_status
& XLR_I2C_SDOEMPTY
) {
107 /* need to do a empty dataout after the last byte */
108 byte
= (pos
< len
) ? buf
[pos
] : 0;
109 xlr_i2c_wreg(priv
->iobase
, XLR_I2C_DATAOUT
, byte
);
111 /* reset timeout on successful xmit */
112 stoptime
= jiffies
+ timeout
;
114 timedout
= time_after(checktime
, stoptime
);
116 if (i2c_status
& XLR_I2C_ARB_STARTERR
) {
122 if (i2c_status
& XLR_I2C_ACK_ERR
)
125 if ((i2c_status
& XLR_I2C_BUS_BUSY
) == 0 && pos
>= len
)
128 dev_err(&adap
->dev
, "I2C transmit timeout\n");
132 static int xlr_i2c_rx(struct xlr_i2c_private
*priv
, u16 len
, u8
*buf
, u16 addr
)
134 struct i2c_adapter
*adap
= &priv
->adap
;
136 unsigned long timeout
, stoptime
, checktime
;
137 int nbytes
, timedout
;
140 xlr_i2c_wreg(priv
->iobase
, XLR_I2C_CFG
, XLR_I2C_CFG_NOADDR
);
141 xlr_i2c_wreg(priv
->iobase
, XLR_I2C_BYTECNT
, len
);
142 xlr_i2c_wreg(priv
->iobase
, XLR_I2C_DEVADDR
, addr
);
144 timeout
= msecs_to_jiffies(XLR_I2C_TIMEOUT
);
145 stoptime
= jiffies
+ timeout
;
149 xlr_i2c_wreg(priv
->iobase
, XLR_I2C_STARTXFR
, XLR_I2C_STARTXFR_RD
);
153 i2c_status
= xlr_i2c_rdreg(priv
->iobase
, XLR_I2C_STATUS
);
154 if (i2c_status
& XLR_I2C_RXRDY
) {
156 return -EIO
; /* should not happen */
158 /* we need to do a dummy datain when nbytes == len */
159 byte
= xlr_i2c_rdreg(priv
->iobase
, XLR_I2C_DATAIN
);
164 /* reset timeout on successful read */
165 stoptime
= jiffies
+ timeout
;
168 timedout
= time_after(checktime
, stoptime
);
169 if (i2c_status
& XLR_I2C_ARB_STARTERR
) {
175 if (i2c_status
& XLR_I2C_ACK_ERR
)
178 if ((i2c_status
& XLR_I2C_BUS_BUSY
) == 0)
182 dev_err(&adap
->dev
, "I2C receive timeout\n");
186 static int xlr_i2c_xfer(struct i2c_adapter
*adap
,
187 struct i2c_msg
*msgs
, int num
)
192 struct xlr_i2c_private
*priv
= i2c_get_adapdata(adap
);
194 for (i
= 0; ret
== 0 && i
< num
; i
++) {
196 if (msg
->flags
& I2C_M_RD
)
197 ret
= xlr_i2c_rx(priv
, msg
->len
, &msg
->buf
[0],
200 ret
= xlr_i2c_tx(priv
, msg
->len
, &msg
->buf
[0],
204 return (ret
!= 0) ? ret
: num
;
207 static u32
xlr_func(struct i2c_adapter
*adap
)
209 /* Emulate SMBUS over I2C */
210 return I2C_FUNC_SMBUS_EMUL
| I2C_FUNC_I2C
;
213 static struct i2c_algorithm xlr_i2c_algo
= {
214 .master_xfer
= xlr_i2c_xfer
,
215 .functionality
= xlr_func
,
218 static int xlr_i2c_probe(struct platform_device
*pdev
)
220 struct xlr_i2c_private
*priv
;
221 struct resource
*res
;
224 priv
= devm_kzalloc(&pdev
->dev
, sizeof(*priv
), GFP_KERNEL
);
228 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
229 priv
->iobase
= devm_ioremap_resource(&pdev
->dev
, res
);
230 if (IS_ERR(priv
->iobase
))
231 return PTR_ERR(priv
->iobase
);
233 priv
->adap
.dev
.parent
= &pdev
->dev
;
234 priv
->adap
.owner
= THIS_MODULE
;
235 priv
->adap
.algo_data
= priv
;
236 priv
->adap
.algo
= &xlr_i2c_algo
;
237 priv
->adap
.nr
= pdev
->id
;
238 priv
->adap
.class = I2C_CLASS_HWMON
;
239 snprintf(priv
->adap
.name
, sizeof(priv
->adap
.name
), "xlr-i2c");
241 i2c_set_adapdata(&priv
->adap
, priv
);
242 ret
= i2c_add_numbered_adapter(&priv
->adap
);
244 dev_err(&priv
->adap
.dev
, "Failed to add i2c bus.\n");
248 platform_set_drvdata(pdev
, priv
);
249 dev_info(&priv
->adap
.dev
, "Added I2C Bus.\n");
253 static int xlr_i2c_remove(struct platform_device
*pdev
)
255 struct xlr_i2c_private
*priv
;
257 priv
= platform_get_drvdata(pdev
);
258 i2c_del_adapter(&priv
->adap
);
262 static struct platform_driver xlr_i2c_driver
= {
263 .probe
= xlr_i2c_probe
,
264 .remove
= xlr_i2c_remove
,
266 .name
= "xlr-i2cbus",
267 .owner
= THIS_MODULE
,
271 module_platform_driver(xlr_i2c_driver
);
273 MODULE_AUTHOR("Ganesan Ramalingam <ganesanr@netlogicmicro.com>");
274 MODULE_DESCRIPTION("XLR/XLS SoC I2C Controller driver");
275 MODULE_LICENSE("GPL v2");
276 MODULE_ALIAS("platform:xlr-i2cbus");