2 * I2C driver for PKUnity-v3 SoC
3 * Code specific to PKUnity SoC and UniCore ISA
5 * Maintained by GUAN Xue-tao <gxt@mprc.pku.edu.cn>
6 * Copyright (C) 2001-2010 Guan Xuetao
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
13 #include <linux/module.h>
14 #include <linux/kernel.h>
15 #include <linux/err.h>
16 #include <linux/slab.h>
17 #include <linux/types.h>
18 #include <linux/delay.h>
19 #include <linux/i2c.h>
20 #include <linux/clk.h>
21 #include <linux/platform_device.h>
23 #include <mach/hardware.h>
26 * Poll the i2c status register until the specified bit is set.
27 * Returns 0 if timed out (100 msec).
29 static short poll_status(unsigned long bit
)
33 if (bit
& I2C_STATUS_TFNF
) {
36 } while (!(readl(I2C_STATUS
) & bit
) && (--loop_cntr
> 0));
40 if (readl(I2C_TAR
) == I2C_TAR_EEPROM
)
44 } while (!(readl(I2C_RXFLR
) & 0xf) && (--loop_cntr
> 0));
47 return (loop_cntr
> 0);
50 static int xfer_read(struct i2c_adapter
*adap
, unsigned char *buf
, int length
)
56 if (!poll_status(I2C_STATUS_TFNF
)) {
57 dev_dbg(&adap
->dev
, "Tx FIFO Not Full timeout\n");
62 writel(i2c_reg
| I2C_DATACMD_WRITE
, I2C_DATACMD
);
64 /* get ready to next write */
68 writel(I2C_DATACMD_READ
, I2C_DATACMD
);
70 /* wait until the Rx FIFO have available */
71 if (!poll_status(I2C_STATUS_RFNE
)) {
72 dev_dbg(&adap
->dev
, "RXRDY timeout\n");
76 /* read the data to buf */
77 *buf
= (readl(I2C_DATACMD
) & I2C_DATACMD_DAT_MASK
);
84 static int xfer_write(struct i2c_adapter
*adap
, unsigned char *buf
, int length
)
88 /* Do nothing but storing the reg_num to a static variable */
90 printk(KERN_WARNING
"Error i2c reg\n");
101 writel(i2c_reg
| I2C_DATACMD_WRITE
, I2C_DATACMD
);
104 writel(*buf
| I2C_DATACMD_WRITE
, I2C_DATACMD
);
106 /* wait until the Rx FIFO have available */
109 /* read the data to buf */
118 * Generic i2c master transfer entrypoint.
121 static int puv3_i2c_xfer(struct i2c_adapter
*adap
, struct i2c_msg
*pmsg
,
128 writel(I2C_ENABLE_DISABLE
, I2C_ENABLE
);
130 /* Set the work mode and speed*/
131 writel(I2C_CON_MASTER
| I2C_CON_SPEED_STD
| I2C_CON_SLAVEDISABLE
, I2C_CON
);
133 writel(pmsg
->addr
, I2C_TAR
);
136 writel(I2C_ENABLE_ENABLE
, I2C_ENABLE
);
138 dev_dbg(&adap
->dev
, "puv3_i2c_xfer: processing %d messages:\n", num
);
140 for (i
= 0; i
< num
; i
++) {
141 dev_dbg(&adap
->dev
, " #%d: %sing %d byte%s %s 0x%02x\n", i
,
142 pmsg
->flags
& I2C_M_RD
? "read" : "writ",
143 pmsg
->len
, pmsg
->len
> 1 ? "s" : "",
144 pmsg
->flags
& I2C_M_RD
? "from" : "to", pmsg
->addr
);
146 if (pmsg
->len
&& pmsg
->buf
) { /* sanity check */
147 if (pmsg
->flags
& I2C_M_RD
)
148 ret
= xfer_read(adap
, pmsg
->buf
, pmsg
->len
);
150 ret
= xfer_write(adap
, pmsg
->buf
, pmsg
->len
);
156 dev_dbg(&adap
->dev
, "transfer complete\n");
157 pmsg
++; /* next message */
160 /* XXX: fixup be16_to_cpu in bq27x00_battery.c */
161 if (pmsg
->addr
== I2C_TAR_PWIC
) {
163 pmsg
->buf
[0] = pmsg
->buf
[1];
171 * Return list of supported functionality.
173 static u32
puv3_i2c_func(struct i2c_adapter
*adapter
)
175 return I2C_FUNC_I2C
| I2C_FUNC_SMBUS_EMUL
;
178 static const struct i2c_algorithm puv3_i2c_algorithm
= {
179 .master_xfer
= puv3_i2c_xfer
,
180 .functionality
= puv3_i2c_func
,
184 * Main initialization routine.
186 static int puv3_i2c_probe(struct platform_device
*pdev
)
188 struct i2c_adapter
*adapter
;
189 struct resource
*mem
;
192 mem
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
196 if (!request_mem_region(mem
->start
, resource_size(mem
), "puv3_i2c"))
199 adapter
= kzalloc(sizeof(struct i2c_adapter
), GFP_KERNEL
);
200 if (adapter
== NULL
) {
201 dev_err(&pdev
->dev
, "can't allocate interface!\n");
205 snprintf(adapter
->name
, sizeof(adapter
->name
), "PUV3-I2C at 0x%08x",
207 adapter
->algo
= &puv3_i2c_algorithm
;
208 adapter
->class = I2C_CLASS_HWMON
;
209 adapter
->dev
.parent
= &pdev
->dev
;
211 platform_set_drvdata(pdev
, adapter
);
213 adapter
->nr
= pdev
->id
;
214 rc
= i2c_add_numbered_adapter(adapter
);
216 goto fail_add_adapter
;
218 dev_info(&pdev
->dev
, "PKUnity v3 i2c bus adapter.\n");
224 release_mem_region(mem
->start
, resource_size(mem
));
229 static int puv3_i2c_remove(struct platform_device
*pdev
)
231 struct i2c_adapter
*adapter
= platform_get_drvdata(pdev
);
232 struct resource
*mem
;
234 i2c_del_adapter(adapter
);
236 put_device(&pdev
->dev
);
238 mem
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
239 release_mem_region(mem
->start
, resource_size(mem
));
244 #ifdef CONFIG_PM_SLEEP
245 static int puv3_i2c_suspend(struct device
*dev
)
248 /* Disable the IIC */
249 writel(I2C_ENABLE_DISABLE
, I2C_ENABLE
);
250 for (poll_count
= 0; poll_count
< 50; poll_count
++) {
251 if (readl(I2C_ENSTATUS
) & I2C_ENSTATUS_ENABLE
)
258 static SIMPLE_DEV_PM_OPS(puv3_i2c_pm
, puv3_i2c_suspend
, NULL
);
259 #define PUV3_I2C_PM (&puv3_i2c_pm)
262 #define PUV3_I2C_PM NULL
265 static struct platform_driver puv3_i2c_driver
= {
266 .probe
= puv3_i2c_probe
,
267 .remove
= puv3_i2c_remove
,
269 .name
= "PKUnity-v3-I2C",
274 module_platform_driver(puv3_i2c_driver
);
276 MODULE_DESCRIPTION("PKUnity v3 I2C driver");
277 MODULE_LICENSE("GPL v2");
278 MODULE_ALIAS("platform:puv3_i2c");