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/ioport.h>
15 #include <linux/delay.h>
16 #include <linux/errno.h>
17 #include <linux/i2c.h>
19 #include <linux/platform_device.h>
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
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
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 */
47 #define XLR_I2C_TIMEOUT 10 /* timeout per byte in msec */
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.
53 * The readl/writel implementation on XLR/XLS byteswaps, because
54 * those are for its little-endian PCI space (see arch/mips/Kconfig).
56 static inline void xlr_i2c_wreg(u32 __iomem
*base
, unsigned int reg
, u32 val
)
58 __raw_writel(val
, base
+ reg
);
61 static inline u32
xlr_i2c_rdreg(u32 __iomem
*base
, unsigned int reg
)
63 return __raw_readl(base
+ reg
);
66 struct xlr_i2c_private
{
67 struct i2c_adapter adap
;
71 static int xlr_i2c_tx(struct xlr_i2c_private
*priv
, u16 len
,
74 struct i2c_adapter
*adap
= &priv
->adap
;
75 unsigned long timeout
, stoptime
, checktime
;
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);
86 timeout
= msecs_to_jiffies(XLR_I2C_TIMEOUT
);
87 stoptime
= jiffies
+ timeout
;
92 xlr_i2c_wreg(priv
->iobase
, XLR_I2C_STARTXFR
,
95 xlr_i2c_wreg(priv
->iobase
, XLR_I2C_DATAOUT
, buf
[pos
]);
96 xlr_i2c_wreg(priv
->iobase
, XLR_I2C_STARTXFR
,
102 i2c_status
= xlr_i2c_rdreg(priv
->iobase
, XLR_I2C_STATUS
);
104 if (i2c_status
& XLR_I2C_SDOEMPTY
) {
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
);
110 /* reset timeout on successful xmit */
111 stoptime
= jiffies
+ timeout
;
113 timedout
= time_after(checktime
, stoptime
);
115 if (i2c_status
& XLR_I2C_ARB_STARTERR
) {
121 if (i2c_status
& XLR_I2C_ACK_ERR
)
124 if ((i2c_status
& XLR_I2C_BUS_BUSY
) == 0 && pos
>= len
)
127 dev_err(&adap
->dev
, "I2C transmit timeout\n");
131 static int xlr_i2c_rx(struct xlr_i2c_private
*priv
, u16 len
, u8
*buf
, u16 addr
)
133 struct i2c_adapter
*adap
= &priv
->adap
;
135 unsigned long timeout
, stoptime
, checktime
;
136 int nbytes
, timedout
;
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
);
143 timeout
= msecs_to_jiffies(XLR_I2C_TIMEOUT
);
144 stoptime
= jiffies
+ timeout
;
148 xlr_i2c_wreg(priv
->iobase
, XLR_I2C_STARTXFR
, XLR_I2C_STARTXFR_RD
);
152 i2c_status
= xlr_i2c_rdreg(priv
->iobase
, XLR_I2C_STATUS
);
153 if (i2c_status
& XLR_I2C_RXRDY
) {
155 return -EIO
; /* should not happen */
157 /* we need to do a dummy datain when nbytes == len */
158 byte
= xlr_i2c_rdreg(priv
->iobase
, XLR_I2C_DATAIN
);
163 /* reset timeout on successful read */
164 stoptime
= jiffies
+ timeout
;
167 timedout
= time_after(checktime
, stoptime
);
168 if (i2c_status
& XLR_I2C_ARB_STARTERR
) {
174 if (i2c_status
& XLR_I2C_ACK_ERR
)
177 if ((i2c_status
& XLR_I2C_BUS_BUSY
) == 0)
181 dev_err(&adap
->dev
, "I2C receive timeout\n");
185 static int xlr_i2c_xfer(struct i2c_adapter
*adap
,
186 struct i2c_msg
*msgs
, int num
)
191 struct xlr_i2c_private
*priv
= i2c_get_adapdata(adap
);
193 for (i
= 0; ret
== 0 && i
< num
; i
++) {
195 if (msg
->flags
& I2C_M_RD
)
196 ret
= xlr_i2c_rx(priv
, msg
->len
, &msg
->buf
[0],
199 ret
= xlr_i2c_tx(priv
, msg
->len
, &msg
->buf
[0],
203 return (ret
!= 0) ? ret
: num
;
206 static u32
xlr_func(struct i2c_adapter
*adap
)
208 /* Emulate SMBUS over I2C */
209 return I2C_FUNC_SMBUS_EMUL
| I2C_FUNC_I2C
;
212 static struct i2c_algorithm xlr_i2c_algo
= {
213 .master_xfer
= xlr_i2c_xfer
,
214 .functionality
= xlr_func
,
217 static int xlr_i2c_probe(struct platform_device
*pdev
)
219 struct xlr_i2c_private
*priv
;
220 struct resource
*res
;
223 priv
= devm_kzalloc(&pdev
->dev
, sizeof(*priv
), GFP_KERNEL
);
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
);
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");
240 i2c_set_adapdata(&priv
->adap
, priv
);
241 ret
= i2c_add_numbered_adapter(&priv
->adap
);
243 dev_err(&priv
->adap
.dev
, "Failed to add i2c bus.\n");
247 platform_set_drvdata(pdev
, priv
);
248 dev_info(&priv
->adap
.dev
, "Added I2C Bus.\n");
252 static int xlr_i2c_remove(struct platform_device
*pdev
)
254 struct xlr_i2c_private
*priv
;
256 priv
= platform_get_drvdata(pdev
);
257 i2c_del_adapter(&priv
->adap
);
261 static struct platform_driver xlr_i2c_driver
= {
262 .probe
= xlr_i2c_probe
,
263 .remove
= xlr_i2c_remove
,
265 .name
= "xlr-i2cbus",
266 .owner
= THIS_MODULE
,
270 module_platform_driver(xlr_i2c_driver
);
272 MODULE_AUTHOR("Ganesan Ramalingam <ganesanr@netlogicmicro.com>");
273 MODULE_DESCRIPTION("XLR/XLS SoC I2C Controller driver");
274 MODULE_LICENSE("GPL v2");
275 MODULE_ALIAS("platform:xlr-i2cbus");