blob: 9e0709d5fb36a0945413d591d58681b71e584eb3 [file] [log] [blame]
Peter Korsgaard18f98b12006-06-04 20:01:08 +02001/*
2 * i2c-ocores.c: I2C bus driver for OpenCores I2C controller
3 * (http://www.opencores.org/projects.cgi/web/i2c/overview).
4 *
5 * Peter Korsgaard <jacmet@sunsite.dk>
6 *
7 * This file is licensed under the terms of the GNU General Public License
8 * version 2. This program is licensed "as is" without any warranty of any
9 * kind, whether express or implied.
10 */
11
Jonas Bonnd9240e62010-11-24 17:26:22 +010012/*
Jayachandran C9ae97a82012-07-13 19:14:22 +053013 * This driver can be used from the device tree, see
14 * Documentation/devicetree/bindings/i2c/ocore-i2c.txt
Jonas Bonnd9240e62010-11-24 17:26:22 +010015 */
Peter Korsgaard18f98b12006-06-04 20:01:08 +020016#include <linux/kernel.h>
17#include <linux/module.h>
Peter Korsgaard18f98b12006-06-04 20:01:08 +020018#include <linux/init.h>
19#include <linux/errno.h>
20#include <linux/platform_device.h>
21#include <linux/i2c.h>
22#include <linux/interrupt.h>
23#include <linux/wait.h>
24#include <linux/i2c-ocores.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090025#include <linux/slab.h>
H Hartley Sweeten21782182010-05-21 18:41:01 +020026#include <linux/io.h>
Ganesan Ramalingama5063f12012-05-08 18:55:28 +053027#include <linux/of_i2c.h>
Ganesan Ramalingam8bb986a2012-07-13 19:14:23 +053028#include <linux/log2.h>
Peter Korsgaard18f98b12006-06-04 20:01:08 +020029
30struct ocores_i2c {
31 void __iomem *base;
Ganesan Ramalingam8bb986a2012-07-13 19:14:23 +053032 u32 reg_shift;
Peter Korsgaard18f98b12006-06-04 20:01:08 +020033 wait_queue_head_t wait;
34 struct i2c_adapter adap;
35 struct i2c_msg *msg;
36 int pos;
37 int nmsgs;
38 int state; /* see STATE_ */
Manuel Lauss2373c182008-07-14 22:38:33 +020039 int clock_khz;
Peter Korsgaard18f98b12006-06-04 20:01:08 +020040};
41
42/* registers */
43#define OCI2C_PRELOW 0
44#define OCI2C_PREHIGH 1
45#define OCI2C_CONTROL 2
46#define OCI2C_DATA 3
Peter Korsgaard1ded9692006-06-12 21:40:53 +020047#define OCI2C_CMD 4 /* write only */
48#define OCI2C_STATUS 4 /* read only, same address as OCI2C_CMD */
Peter Korsgaard18f98b12006-06-04 20:01:08 +020049
50#define OCI2C_CTRL_IEN 0x40
51#define OCI2C_CTRL_EN 0x80
52
53#define OCI2C_CMD_START 0x91
54#define OCI2C_CMD_STOP 0x41
55#define OCI2C_CMD_READ 0x21
56#define OCI2C_CMD_WRITE 0x11
57#define OCI2C_CMD_READ_ACK 0x21
58#define OCI2C_CMD_READ_NACK 0x29
59#define OCI2C_CMD_IACK 0x01
60
61#define OCI2C_STAT_IF 0x01
62#define OCI2C_STAT_TIP 0x02
63#define OCI2C_STAT_ARBLOST 0x20
64#define OCI2C_STAT_BUSY 0x40
65#define OCI2C_STAT_NACK 0x80
66
67#define STATE_DONE 0
68#define STATE_START 1
69#define STATE_WRITE 2
70#define STATE_READ 3
71#define STATE_ERROR 4
72
73static inline void oc_setreg(struct ocores_i2c *i2c, int reg, u8 value)
74{
Ganesan Ramalingam8bb986a2012-07-13 19:14:23 +053075 iowrite8(value, i2c->base + (reg << i2c->reg_shift));
Peter Korsgaard18f98b12006-06-04 20:01:08 +020076}
77
78static inline u8 oc_getreg(struct ocores_i2c *i2c, int reg)
79{
Ganesan Ramalingam8bb986a2012-07-13 19:14:23 +053080 return ioread8(i2c->base + (reg << i2c->reg_shift));
Peter Korsgaard18f98b12006-06-04 20:01:08 +020081}
82
83static void ocores_process(struct ocores_i2c *i2c)
84{
85 struct i2c_msg *msg = i2c->msg;
86 u8 stat = oc_getreg(i2c, OCI2C_STATUS);
87
88 if ((i2c->state == STATE_DONE) || (i2c->state == STATE_ERROR)) {
89 /* stop has been sent */
90 oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_IACK);
91 wake_up(&i2c->wait);
92 return;
93 }
94
95 /* error? */
96 if (stat & OCI2C_STAT_ARBLOST) {
97 i2c->state = STATE_ERROR;
98 oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_STOP);
99 return;
100 }
101
102 if ((i2c->state == STATE_START) || (i2c->state == STATE_WRITE)) {
103 i2c->state =
104 (msg->flags & I2C_M_RD) ? STATE_READ : STATE_WRITE;
105
106 if (stat & OCI2C_STAT_NACK) {
107 i2c->state = STATE_ERROR;
108 oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_STOP);
109 return;
110 }
111 } else
112 msg->buf[i2c->pos++] = oc_getreg(i2c, OCI2C_DATA);
113
114 /* end of msg? */
115 if (i2c->pos == msg->len) {
116 i2c->nmsgs--;
117 i2c->msg++;
118 i2c->pos = 0;
119 msg = i2c->msg;
120
121 if (i2c->nmsgs) { /* end? */
122 /* send start? */
123 if (!(msg->flags & I2C_M_NOSTART)) {
124 u8 addr = (msg->addr << 1);
125
126 if (msg->flags & I2C_M_RD)
127 addr |= 1;
128
129 i2c->state = STATE_START;
130
131 oc_setreg(i2c, OCI2C_DATA, addr);
132 oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_START);
133 return;
134 } else
135 i2c->state = (msg->flags & I2C_M_RD)
136 ? STATE_READ : STATE_WRITE;
137 } else {
138 i2c->state = STATE_DONE;
139 oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_STOP);
140 return;
141 }
142 }
143
144 if (i2c->state == STATE_READ) {
145 oc_setreg(i2c, OCI2C_CMD, i2c->pos == (msg->len-1) ?
146 OCI2C_CMD_READ_NACK : OCI2C_CMD_READ_ACK);
147 } else {
148 oc_setreg(i2c, OCI2C_DATA, msg->buf[i2c->pos++]);
149 oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_WRITE);
150 }
151}
152
David Howells7d12e782006-10-05 14:55:46 +0100153static irqreturn_t ocores_isr(int irq, void *dev_id)
Peter Korsgaard18f98b12006-06-04 20:01:08 +0200154{
155 struct ocores_i2c *i2c = dev_id;
156
157 ocores_process(i2c);
158
159 return IRQ_HANDLED;
160}
161
162static int ocores_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
163{
164 struct ocores_i2c *i2c = i2c_get_adapdata(adap);
165
166 i2c->msg = msgs;
167 i2c->pos = 0;
168 i2c->nmsgs = num;
169 i2c->state = STATE_START;
170
171 oc_setreg(i2c, OCI2C_DATA,
172 (i2c->msg->addr << 1) |
173 ((i2c->msg->flags & I2C_M_RD) ? 1:0));
174
175 oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_START);
176
177 if (wait_event_timeout(i2c->wait, (i2c->state == STATE_ERROR) ||
178 (i2c->state == STATE_DONE), HZ))
179 return (i2c->state == STATE_DONE) ? num : -EIO;
180 else
181 return -ETIMEDOUT;
182}
183
Manuel Lauss2373c182008-07-14 22:38:33 +0200184static void ocores_init(struct ocores_i2c *i2c)
Peter Korsgaard18f98b12006-06-04 20:01:08 +0200185{
186 int prescale;
187 u8 ctrl = oc_getreg(i2c, OCI2C_CONTROL);
188
189 /* make sure the device is disabled */
190 oc_setreg(i2c, OCI2C_CONTROL, ctrl & ~(OCI2C_CTRL_EN|OCI2C_CTRL_IEN));
191
Manuel Lauss2373c182008-07-14 22:38:33 +0200192 prescale = (i2c->clock_khz / (5*100)) - 1;
Peter Korsgaard18f98b12006-06-04 20:01:08 +0200193 oc_setreg(i2c, OCI2C_PRELOW, prescale & 0xff);
194 oc_setreg(i2c, OCI2C_PREHIGH, prescale >> 8);
195
196 /* Init the device */
197 oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_IACK);
198 oc_setreg(i2c, OCI2C_CONTROL, ctrl | OCI2C_CTRL_IEN | OCI2C_CTRL_EN);
199}
200
201
202static u32 ocores_func(struct i2c_adapter *adap)
203{
204 return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
205}
206
Jean Delvare8f9082c2006-09-03 22:39:46 +0200207static const struct i2c_algorithm ocores_algorithm = {
Peter Korsgaard18f98b12006-06-04 20:01:08 +0200208 .master_xfer = ocores_xfer,
209 .functionality = ocores_func,
210};
211
212static struct i2c_adapter ocores_adapter = {
213 .owner = THIS_MODULE,
214 .name = "i2c-ocores",
Jean Delvare3401b2f2008-07-14 22:38:29 +0200215 .class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
Peter Korsgaard18f98b12006-06-04 20:01:08 +0200216 .algo = &ocores_algorithm,
Peter Korsgaard18f98b12006-06-04 20:01:08 +0200217};
218
Jonas Bonn049bb69d2010-11-24 17:26:20 +0100219#ifdef CONFIG_OF
Jayachandran C9ae97a82012-07-13 19:14:22 +0530220static int ocores_i2c_of_probe(struct platform_device *pdev,
221 struct ocores_i2c *i2c)
Jonas Bonn049bb69d2010-11-24 17:26:20 +0100222{
Ganesan Ramalingam8bb986a2012-07-13 19:14:23 +0530223 struct device_node *np = pdev->dev.of_node;
224 u32 val;
Jonas Bonn049bb69d2010-11-24 17:26:20 +0100225
Ganesan Ramalingam8bb986a2012-07-13 19:14:23 +0530226 if (of_property_read_u32(np, "reg-shift", &i2c->reg_shift)) {
227 /* no 'reg-shift', check for deprecated 'regstep' */
228 if (!of_property_read_u32(np, "regstep", &val)) {
229 if (!is_power_of_2(val)) {
230 dev_err(&pdev->dev, "invalid regstep %d\n",
231 val);
232 return -EINVAL;
233 }
234 i2c->reg_shift = ilog2(val);
235 dev_warn(&pdev->dev,
236 "regstep property deprecated, use reg-shift\n");
237 }
Jonas Bonn049bb69d2010-11-24 17:26:20 +0100238 }
Jonas Bonn049bb69d2010-11-24 17:26:20 +0100239
Ganesan Ramalingam8bb986a2012-07-13 19:14:23 +0530240 if (of_property_read_u32(np, "clock-frequency", &val)) {
Jonas Bonn049bb69d2010-11-24 17:26:20 +0100241 dev_err(&pdev->dev,
Jayachandran C9ae97a82012-07-13 19:14:22 +0530242 "Missing required parameter 'clock-frequency'\n");
Jonas Bonn049bb69d2010-11-24 17:26:20 +0100243 return -ENODEV;
244 }
Ganesan Ramalingam8bb986a2012-07-13 19:14:23 +0530245 i2c->clock_khz = val / 1000;
Jonas Bonn049bb69d2010-11-24 17:26:20 +0100246
247 return 0;
248}
249#else
250#define ocores_i2c_of_probe(pdev,i2c) -ENODEV
251#endif
Peter Korsgaard18f98b12006-06-04 20:01:08 +0200252
253static int __devinit ocores_i2c_probe(struct platform_device *pdev)
254{
255 struct ocores_i2c *i2c;
256 struct ocores_i2c_platform_data *pdata;
257 struct resource *res, *res2;
258 int ret;
Richard Röjforsdd14be42009-06-05 15:40:32 +0200259 int i;
Peter Korsgaard18f98b12006-06-04 20:01:08 +0200260
261 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
262 if (!res)
263 return -ENODEV;
264
265 res2 = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
266 if (!res2)
267 return -ENODEV;
268
Jonas Bonn47def5b2010-11-24 17:26:21 +0100269 i2c = devm_kzalloc(&pdev->dev, sizeof(*i2c), GFP_KERNEL);
Peter Korsgaard18f98b12006-06-04 20:01:08 +0200270 if (!i2c)
271 return -ENOMEM;
272
Jonas Bonn47def5b2010-11-24 17:26:21 +0100273 if (!devm_request_mem_region(&pdev->dev, res->start,
274 resource_size(res), pdev->name)) {
Peter Korsgaard18f98b12006-06-04 20:01:08 +0200275 dev_err(&pdev->dev, "Memory region busy\n");
Jonas Bonn47def5b2010-11-24 17:26:21 +0100276 return -EBUSY;
Peter Korsgaard18f98b12006-06-04 20:01:08 +0200277 }
278
Jonas Bonn47def5b2010-11-24 17:26:21 +0100279 i2c->base = devm_ioremap_nocache(&pdev->dev, res->start,
280 resource_size(res));
Peter Korsgaard18f98b12006-06-04 20:01:08 +0200281 if (!i2c->base) {
282 dev_err(&pdev->dev, "Unable to map registers\n");
Jonas Bonn47def5b2010-11-24 17:26:21 +0100283 return -EIO;
Peter Korsgaard18f98b12006-06-04 20:01:08 +0200284 }
285
Samuel Ortiz3271d382011-04-08 01:23:57 +0200286 pdata = pdev->dev.platform_data;
Jonas Bonn049bb69d2010-11-24 17:26:20 +0100287 if (pdata) {
Ganesan Ramalingam8bb986a2012-07-13 19:14:23 +0530288 i2c->reg_shift = pdata->reg_shift;
Jonas Bonn049bb69d2010-11-24 17:26:20 +0100289 i2c->clock_khz = pdata->clock_khz;
290 } else {
291 ret = ocores_i2c_of_probe(pdev, i2c);
292 if (ret)
293 return ret;
294 }
295
Manuel Lauss2373c182008-07-14 22:38:33 +0200296 ocores_init(i2c);
Peter Korsgaard18f98b12006-06-04 20:01:08 +0200297
298 init_waitqueue_head(&i2c->wait);
Jonas Bonn47def5b2010-11-24 17:26:21 +0100299 ret = devm_request_irq(&pdev->dev, res2->start, ocores_isr, 0,
300 pdev->name, i2c);
Peter Korsgaard18f98b12006-06-04 20:01:08 +0200301 if (ret) {
302 dev_err(&pdev->dev, "Cannot claim IRQ\n");
Jonas Bonn47def5b2010-11-24 17:26:21 +0100303 return ret;
Peter Korsgaard18f98b12006-06-04 20:01:08 +0200304 }
305
306 /* hook up driver to tree */
307 platform_set_drvdata(pdev, i2c);
308 i2c->adap = ocores_adapter;
309 i2c_set_adapdata(&i2c->adap, i2c);
310 i2c->adap.dev.parent = &pdev->dev;
Jonas Bonn049bb69d2010-11-24 17:26:20 +0100311 i2c->adap.dev.of_node = pdev->dev.of_node;
Peter Korsgaard18f98b12006-06-04 20:01:08 +0200312
313 /* add i2c adapter to i2c tree */
314 ret = i2c_add_adapter(&i2c->adap);
315 if (ret) {
316 dev_err(&pdev->dev, "Failed to add adapter\n");
Jonas Bonn47def5b2010-11-24 17:26:21 +0100317 return ret;
Peter Korsgaard18f98b12006-06-04 20:01:08 +0200318 }
319
Richard Röjforsdd14be42009-06-05 15:40:32 +0200320 /* add in known devices to the bus */
Jonas Bonn049bb69d2010-11-24 17:26:20 +0100321 if (pdata) {
322 for (i = 0; i < pdata->num_devices; i++)
323 i2c_new_device(&i2c->adap, pdata->devices + i);
Ganesan Ramalingama5063f12012-05-08 18:55:28 +0530324 } else {
325 of_i2c_register_devices(&i2c->adap);
Jonas Bonn049bb69d2010-11-24 17:26:20 +0100326 }
Richard Röjforsdd14be42009-06-05 15:40:32 +0200327
Peter Korsgaard18f98b12006-06-04 20:01:08 +0200328 return 0;
Peter Korsgaard18f98b12006-06-04 20:01:08 +0200329}
330
Jayachandran C9ae97a82012-07-13 19:14:22 +0530331static int __devexit ocores_i2c_remove(struct platform_device *pdev)
Peter Korsgaard18f98b12006-06-04 20:01:08 +0200332{
333 struct ocores_i2c *i2c = platform_get_drvdata(pdev);
Peter Korsgaard18f98b12006-06-04 20:01:08 +0200334
335 /* disable i2c logic */
336 oc_setreg(i2c, OCI2C_CONTROL, oc_getreg(i2c, OCI2C_CONTROL)
337 & ~(OCI2C_CTRL_EN|OCI2C_CTRL_IEN));
338
339 /* remove adapter & data */
340 i2c_del_adapter(&i2c->adap);
341 platform_set_drvdata(pdev, NULL);
342
Peter Korsgaard18f98b12006-06-04 20:01:08 +0200343 return 0;
344}
345
Manuel Lauss2373c182008-07-14 22:38:33 +0200346#ifdef CONFIG_PM
Rafael J. Wysocki84603c72012-07-11 21:24:15 +0200347static int ocores_i2c_suspend(struct device *dev)
Manuel Lauss2373c182008-07-14 22:38:33 +0200348{
Rafael J. Wysocki84603c72012-07-11 21:24:15 +0200349 struct ocores_i2c *i2c = dev_get_drvdata(dev);
Manuel Lauss2373c182008-07-14 22:38:33 +0200350 u8 ctrl = oc_getreg(i2c, OCI2C_CONTROL);
351
352 /* make sure the device is disabled */
353 oc_setreg(i2c, OCI2C_CONTROL, ctrl & ~(OCI2C_CTRL_EN|OCI2C_CTRL_IEN));
354
355 return 0;
356}
357
Rafael J. Wysocki84603c72012-07-11 21:24:15 +0200358static int ocores_i2c_resume(struct device *dev)
Manuel Lauss2373c182008-07-14 22:38:33 +0200359{
Rafael J. Wysocki84603c72012-07-11 21:24:15 +0200360 struct ocores_i2c *i2c = dev_get_drvdata(dev);
Manuel Lauss2373c182008-07-14 22:38:33 +0200361
362 ocores_init(i2c);
363
364 return 0;
365}
Rafael J. Wysocki84603c72012-07-11 21:24:15 +0200366
367static SIMPLE_DEV_PM_OPS(ocores_i2c_pm, ocores_i2c_suspend, ocores_i2c_resume);
368#define OCORES_I2C_PM (&ocores_i2c_pm)
Manuel Lauss2373c182008-07-14 22:38:33 +0200369#else
Rafael J. Wysocki84603c72012-07-11 21:24:15 +0200370#define OCORES_I2C_PM NULL
Manuel Lauss2373c182008-07-14 22:38:33 +0200371#endif
372
Jonas Bonn049bb69d2010-11-24 17:26:20 +0100373static struct of_device_id ocores_i2c_match[] = {
Grant Likelyc9e358d2011-01-21 09:24:48 -0700374 { .compatible = "opencores,i2c-ocores", },
375 {},
Jonas Bonn049bb69d2010-11-24 17:26:20 +0100376};
377MODULE_DEVICE_TABLE(of, ocores_i2c_match);
Jonas Bonn049bb69d2010-11-24 17:26:20 +0100378
Peter Korsgaard18f98b12006-06-04 20:01:08 +0200379static struct platform_driver ocores_i2c_driver = {
Manuel Lauss2373c182008-07-14 22:38:33 +0200380 .probe = ocores_i2c_probe,
381 .remove = __devexit_p(ocores_i2c_remove),
Manuel Lauss2373c182008-07-14 22:38:33 +0200382 .driver = {
Peter Korsgaard18f98b12006-06-04 20:01:08 +0200383 .owner = THIS_MODULE,
384 .name = "ocores-i2c",
Grant Likelyc9e358d2011-01-21 09:24:48 -0700385 .of_match_table = ocores_i2c_match,
Rafael J. Wysocki84603c72012-07-11 21:24:15 +0200386 .pm = OCORES_I2C_PM,
Peter Korsgaard18f98b12006-06-04 20:01:08 +0200387 },
388};
389
Axel Lina3664b52012-01-12 20:32:04 +0100390module_platform_driver(ocores_i2c_driver);
Peter Korsgaard18f98b12006-06-04 20:01:08 +0200391
392MODULE_AUTHOR("Peter Korsgaard <jacmet@sunsite.dk>");
393MODULE_DESCRIPTION("OpenCores I2C bus driver");
394MODULE_LICENSE("GPL");
Axel Lina3664b52012-01-12 20:32:04 +0100395MODULE_ALIAS("platform:ocores-i2c");