blob: 2059e4a9558a0428029fd1c5a52232f11dc1c49a [file] [log] [blame]
wongab.jeona2d272e2012-07-18 21:49:59 +09001/*
2 * Copyright (C) 2012 Broadcom Corporation.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17 *
18 */
19
20#include <linux/kernel.h>
21#include <linux/module.h>
22#include <linux/fs.h>
23#include <linux/slab.h>
24#include <linux/init.h>
25#include <linux/list.h>
26#include <linux/i2c.h>
27#include <linux/irq.h>
28#include <linux/jiffies.h>
29#include <linux/uaccess.h>
30#include <linux/delay.h>
31#include <linux/interrupt.h>
32#include <linux/io.h>
33#include <linux/platform_device.h>
34#include <linux/gpio.h>
35#include <linux/miscdevice.h>
36#include <linux/spinlock.h>
37#include <linux/poll.h>
38#include <linux/version.h>
39
40#include <linux/nfc/bcm2079x.h>
41
42/* do not change below */
43#define MAX_BUFFER_SIZE 780
44
45/* Read data */
46#define PACKET_HEADER_SIZE_NCI (4)
47#define PACKET_HEADER_SIZE_HCI (3)
48#define PACKET_TYPE_NCI (16)
49#define PACKET_TYPE_HCIEV (4)
50#define MAX_PACKET_SIZE (PACKET_HEADER_SIZE_NCI + 255)
51
52struct bcm2079x_dev {
53 wait_queue_head_t read_wq;
54 struct mutex read_mutex;
55 struct i2c_client *client;
56 struct miscdevice bcm2079x_device;
57 unsigned int wake_gpio;
58 unsigned int en_gpio;
59 unsigned int irq_gpio;
60 bool irq_enabled;
61 spinlock_t irq_enabled_lock;
62 unsigned int count_irq;
63};
64
65static void bcm2079x_init_stat(struct bcm2079x_dev *bcm2079x_dev)
66{
67 bcm2079x_dev->count_irq = 0;
68}
69
70static void bcm2079x_disable_irq(struct bcm2079x_dev *bcm2079x_dev)
71{
72 unsigned long flags;
73 spin_lock_irqsave(&bcm2079x_dev->irq_enabled_lock, flags);
74 if (bcm2079x_dev->irq_enabled) {
75 disable_irq_nosync(bcm2079x_dev->client->irq);
76 bcm2079x_dev->irq_enabled = false;
77 }
78 spin_unlock_irqrestore(&bcm2079x_dev->irq_enabled_lock, flags);
79}
80
81static void bcm2079x_enable_irq(struct bcm2079x_dev *bcm2079x_dev)
82{
83 unsigned long flags;
84 spin_lock_irqsave(&bcm2079x_dev->irq_enabled_lock, flags);
85 if (!bcm2079x_dev->irq_enabled) {
86 bcm2079x_dev->irq_enabled = true;
87 enable_irq(bcm2079x_dev->client->irq);
88 }
89 spin_unlock_irqrestore(&bcm2079x_dev->irq_enabled_lock, flags);
90}
91
92/*
93 The alias address 0x79, when sent as a 7-bit address from the host processor
94 will match the first byte (highest 2 bits) of the default client address
95 (0x1FA) that is programmed in bcm20791.
96 When used together with the first byte (0xFA) of the byte sequence below,
97 it can be used to address the bcm20791 in a system that does not support
98 10-bit address and change the default address to 0x38.
99 the new address can be changed by changing the CLIENT_ADDRESS below if 0x38
100 conflicts with other device on the same i2c bus.
101 */
102#define ALIAS_ADDRESS 0x79
103
Martijn Coenen0fac0bb2012-09-30 14:54:05 -0700104static int change_client_addr(struct bcm2079x_dev *bcm2079x_dev, int addr)
wongab.jeona2d272e2012-07-18 21:49:59 +0900105{
106 struct i2c_client *client;
107 int ret;
108 int i;
wongab.jeona2d272e2012-07-18 21:49:59 +0900109 char addr_data[] = {
110 0xFA, 0xF2, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x2A
111 };
wongab.jeona2d272e2012-07-18 21:49:59 +0900112 client = bcm2079x_dev->client;
113 client->addr = ALIAS_ADDRESS;
114 client->flags &= ~I2C_CLIENT_TEN;
wongab.jeona2d272e2012-07-18 21:49:59 +0900115
116 addr_data[5] = addr & 0xFF;
117 ret = 0;
118 for (i = 1; i < sizeof(addr_data) - 1; ++i)
119 ret += addr_data[i];
120 addr_data[sizeof(addr_data) - 1] = (ret & 0xFF);
121 dev_info(&client->dev,
122 "Change client device from (0x%04X) flag = "\
123 "%04x, addr_data[%d] = %02x\n",
124 client->addr, client->flags, sizeof(addr_data) - 1,
125 addr_data[sizeof(addr_data) - 1]);
Martijn Coenen0fac0bb2012-09-30 14:54:05 -0700126 ret = i2c_master_send(client, addr_data, sizeof(addr_data));
127 if (ret != sizeof(addr_data)) {
wongab.jeona2d272e2012-07-18 21:49:59 +0900128 client->addr = ALIAS_ADDRESS;
129 client->flags &= ~I2C_CLIENT_TEN;
130 dev_info(&client->dev,
131 "Change client device from (0x%04X) flag = "\
132 "%04x, addr_data[%d] = %02x\n",
133 client->addr, client->flags, sizeof(addr_data) - 1,
134 addr_data[sizeof(addr_data) - 1]);
135 ret = i2c_master_send(client, addr_data, sizeof(addr_data));
136 }
137 client->addr = addr_data[5];
138
139 dev_info(&client->dev,
140 "Change client device changed to (0x%04X) flag = %04x, ret = %d\n",
141 client->addr, client->flags, ret);
Martijn Coenen0fac0bb2012-09-30 14:54:05 -0700142
143 return (ret == sizeof(addr_data) ? 0 : -EIO);
wongab.jeona2d272e2012-07-18 21:49:59 +0900144}
145
146static irqreturn_t bcm2079x_dev_irq_handler(int irq, void *dev_id)
147{
148 struct bcm2079x_dev *bcm2079x_dev = dev_id;
149 unsigned long flags;
150
151 spin_lock_irqsave(&bcm2079x_dev->irq_enabled_lock, flags);
152 bcm2079x_dev->count_irq++;
153 spin_unlock_irqrestore(&bcm2079x_dev->irq_enabled_lock, flags);
154 wake_up(&bcm2079x_dev->read_wq);
155
156 return IRQ_HANDLED;
157}
158
159static unsigned int bcm2079x_dev_poll(struct file *filp, poll_table *wait)
160{
161 struct bcm2079x_dev *bcm2079x_dev = filp->private_data;
162 unsigned int mask = 0;
163 unsigned long flags;
164
165 poll_wait(filp, &bcm2079x_dev->read_wq, wait);
166
167 spin_lock_irqsave(&bcm2079x_dev->irq_enabled_lock, flags);
168 if (bcm2079x_dev->count_irq > 0)
169 {
170 bcm2079x_dev->count_irq--;
171 mask |= POLLIN | POLLRDNORM;
172 }
173 spin_unlock_irqrestore(&bcm2079x_dev->irq_enabled_lock, flags);
174
175 return mask;
176}
177
178static ssize_t bcm2079x_dev_read(struct file *filp, char __user *buf,
179 size_t count, loff_t *offset)
180{
181 struct bcm2079x_dev *bcm2079x_dev = filp->private_data;
182 unsigned char tmp[MAX_BUFFER_SIZE];
183 int total, len, ret;
184
185 total = 0;
186 len = 0;
187
188 if (count > MAX_BUFFER_SIZE)
189 count = MAX_BUFFER_SIZE;
190
191 mutex_lock(&bcm2079x_dev->read_mutex);
192
193 /** Read the first 4 bytes to include the length of the NCI or HCI packet.
194 **/
195 ret = i2c_master_recv(bcm2079x_dev->client, tmp, 4);
196 if (ret == 4) {
197 total = ret;
198 /** First byte is the packet type
199 **/
200 switch(tmp[0]) {
201 case PACKET_TYPE_NCI:
202 len = tmp[PACKET_HEADER_SIZE_NCI-1];
203 break;
204
205 case PACKET_TYPE_HCIEV:
206 len = tmp[PACKET_HEADER_SIZE_HCI-1];
207 if (len == 0)
208 total--;/*Since payload is 0, decrement total size (from 4 to 3) */
209 else
210 len--;/*First byte of payload is in tmp[3] already */
211 break;
212
213 default:
214 len = 0;/*Unknown packet byte */
215 break;
216 } /* switch*/
217
218 /** make sure full packet fits in the buffer
219 **/
220 if (len > 0 && (len + total) <= count) {
221 /** read the remainder of the packet.
222 **/
223 ret = i2c_master_recv(bcm2079x_dev->client, tmp+total, len);
224 if (ret == len)
225 total += len;
226 } /* if */
227 } /* if */
228
229 mutex_unlock(&bcm2079x_dev->read_mutex);
230
231 if (total > count || copy_to_user(buf, tmp, total)) {
232 dev_err(&bcm2079x_dev->client->dev,
233 "failed to copy to user space, total = %d\n", total);
234 total = -EFAULT;
235 }
236
237 return total;
238}
239
240static ssize_t bcm2079x_dev_write(struct file *filp, const char __user *buf,
241 size_t count, loff_t *offset)
242{
243 struct bcm2079x_dev *bcm2079x_dev = filp->private_data;
244 char tmp[MAX_BUFFER_SIZE];
245 int ret;
246
247 if (count > MAX_BUFFER_SIZE) {
248 dev_err(&bcm2079x_dev->client->dev, "out of memory\n");
249 return -ENOMEM;
250 }
251
252 if (copy_from_user(tmp, buf, count)) {
253 dev_err(&bcm2079x_dev->client->dev,
254 "failed to copy from user space\n");
255 return -EFAULT;
256 }
257
258 mutex_lock(&bcm2079x_dev->read_mutex);
259 /* Write data */
260
261 ret = i2c_master_send(bcm2079x_dev->client, tmp, count);
262 if (ret != count) {
263 dev_err(&bcm2079x_dev->client->dev,
264 "failed to write %d\n", ret);
265 ret = -EIO;
266 }
267 mutex_unlock(&bcm2079x_dev->read_mutex);
268
269 return ret;
270}
271
272static int bcm2079x_dev_open(struct inode *inode, struct file *filp)
273{
274 int ret = 0;
275
276 struct bcm2079x_dev *bcm2079x_dev = container_of(filp->private_data,
277 struct bcm2079x_dev,
278 bcm2079x_device);
279 filp->private_data = bcm2079x_dev;
280 bcm2079x_init_stat(bcm2079x_dev);
281 bcm2079x_enable_irq(bcm2079x_dev);
282 dev_info(&bcm2079x_dev->client->dev,
283 "%d,%d\n", imajor(inode), iminor(inode));
284
285 return ret;
286}
287
288static long bcm2079x_dev_unlocked_ioctl(struct file *filp,
289 unsigned int cmd, unsigned long arg)
290{
291 struct bcm2079x_dev *bcm2079x_dev = filp->private_data;
292
293 switch (cmd) {
294 case BCMNFC_READ_FULL_PACKET:
295 break;
296 case BCMNFC_READ_MULTI_PACKETS:
297 break;
298 case BCMNFC_CHANGE_ADDR:
299 dev_info(&bcm2079x_dev->client->dev,
300 "%s, BCMNFC_CHANGE_ADDR (%x, %lx):\n", __func__, cmd,
301 arg);
Martijn Coenen0fac0bb2012-09-30 14:54:05 -0700302 return change_client_addr(bcm2079x_dev, arg);
wongab.jeona2d272e2012-07-18 21:49:59 +0900303 case BCMNFC_POWER_CTL:
304 gpio_set_value(bcm2079x_dev->en_gpio, arg);
305 break;
306 case BCMNFC_WAKE_CTL:
307 gpio_set_value(bcm2079x_dev->wake_gpio, arg);
308 break;
309 default:
310 dev_err(&bcm2079x_dev->client->dev,
311 "%s, unknown cmd (%x, %lx)\n", __func__, cmd, arg);
312 return 0;
313 }
314
315 return 0;
316}
317
318static const struct file_operations bcm2079x_dev_fops = {
319 .owner = THIS_MODULE,
320 .llseek = no_llseek,
321 .poll = bcm2079x_dev_poll,
322 .read = bcm2079x_dev_read,
323 .write = bcm2079x_dev_write,
324 .open = bcm2079x_dev_open,
325 .unlocked_ioctl = bcm2079x_dev_unlocked_ioctl
326};
327
328static int bcm2079x_probe(struct i2c_client *client,
329 const struct i2c_device_id *id)
330{
331 int ret;
332 struct bcm2079x_platform_data *platform_data;
333 struct bcm2079x_dev *bcm2079x_dev;
334
335 platform_data = client->dev.platform_data;
336
337 dev_info(&client->dev, "%s, probing bcm2079x driver flags = %x\n", __func__, client->flags);
338 if (platform_data == NULL) {
339 dev_err(&client->dev, "nfc probe fail\n");
340 return -ENODEV;
341 }
342
343 if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
344 dev_err(&client->dev, "need I2C_FUNC_I2C\n");
345 return -ENODEV;
346 }
347
348 ret = gpio_request_one(platform_data->irq_gpio, GPIOF_IN, "nfc_int");
349 if (ret)
350 return -ENODEV;
351 ret = gpio_request_one(platform_data->en_gpio, GPIOF_OUT_INIT_LOW, "nfc_ven");
352 if (ret)
353 goto err_en;
354 ret = gpio_request_one(platform_data->wake_gpio, GPIOF_OUT_INIT_LOW,"nfc_firm");
355 if (ret)
356 goto err_firm;
357
358 gpio_set_value(platform_data->en_gpio, 0);
359 gpio_set_value(platform_data->wake_gpio, 0);
360
361 bcm2079x_dev = kzalloc(sizeof(*bcm2079x_dev), GFP_KERNEL);
362 if (bcm2079x_dev == NULL) {
363 dev_err(&client->dev,
364 "failed to allocate memory for module data\n");
365 ret = -ENOMEM;
366 goto err_exit;
367 }
368
369 bcm2079x_dev->wake_gpio = platform_data->wake_gpio;
370 bcm2079x_dev->irq_gpio = platform_data->irq_gpio;
371 bcm2079x_dev->en_gpio = platform_data->en_gpio;
372 bcm2079x_dev->client = client;
373
374 /* init mutex and queues */
375 init_waitqueue_head(&bcm2079x_dev->read_wq);
376 mutex_init(&bcm2079x_dev->read_mutex);
377 spin_lock_init(&bcm2079x_dev->irq_enabled_lock);
378
379 bcm2079x_dev->bcm2079x_device.minor = MISC_DYNAMIC_MINOR;
380 bcm2079x_dev->bcm2079x_device.name = "bcm2079x-i2c";
381 bcm2079x_dev->bcm2079x_device.fops = &bcm2079x_dev_fops;
382
383 ret = misc_register(&bcm2079x_dev->bcm2079x_device);
384 if (ret) {
385 dev_err(&client->dev, "misc_register failed\n");
386 goto err_misc_register;
387 }
388
389 /* request irq. the irq is set whenever the chip has data available
390 * for reading. it is cleared when all data has been read.
391 */
392 dev_info(&client->dev, "requesting IRQ %d\n", client->irq);
393 bcm2079x_dev->irq_enabled = true;
394 ret = request_irq(client->irq, bcm2079x_dev_irq_handler,
395 IRQF_TRIGGER_RISING, client->name, bcm2079x_dev);
396 if (ret) {
397 dev_err(&client->dev, "request_irq failed\n");
398 goto err_request_irq_failed;
399 }
400 bcm2079x_disable_irq(bcm2079x_dev);
401 i2c_set_clientdata(client, bcm2079x_dev);
402 dev_info(&client->dev,
403 "%s, probing bcm2079x driver exited successfully\n",
404 __func__);
405 return 0;
406
407err_request_irq_failed:
408 misc_deregister(&bcm2079x_dev->bcm2079x_device);
409err_misc_register:
410 mutex_destroy(&bcm2079x_dev->read_mutex);
411 kfree(bcm2079x_dev);
412err_exit:
413 gpio_free(platform_data->wake_gpio);
414err_firm:
415 gpio_free(platform_data->en_gpio);
416err_en:
417 gpio_free(platform_data->irq_gpio);
418 return ret;
419}
420
421static int bcm2079x_remove(struct i2c_client *client)
422{
423 struct bcm2079x_dev *bcm2079x_dev;
424
425 bcm2079x_dev = i2c_get_clientdata(client);
426 free_irq(client->irq, bcm2079x_dev);
427 misc_deregister(&bcm2079x_dev->bcm2079x_device);
428 mutex_destroy(&bcm2079x_dev->read_mutex);
429 gpio_free(bcm2079x_dev->irq_gpio);
430 gpio_free(bcm2079x_dev->en_gpio);
431 gpio_free(bcm2079x_dev->wake_gpio);
432 kfree(bcm2079x_dev);
433
434 return 0;
435}
436
437static const struct i2c_device_id bcm2079x_id[] = {
438 {"bcm2079x-i2c", 0},
439 {}
440};
441
442static struct i2c_driver bcm2079x_driver = {
443 .id_table = bcm2079x_id,
444 .probe = bcm2079x_probe,
445 .remove = bcm2079x_remove,
446 .driver = {
447 .owner = THIS_MODULE,
448 .name = "bcm2079x-i2c",
449 },
450};
451
452/*
453 * module load/unload record keeping
454 */
455
456static int __init bcm2079x_dev_init(void)
457{
458 return i2c_add_driver(&bcm2079x_driver);
459}
460module_init(bcm2079x_dev_init);
461
462static void __exit bcm2079x_dev_exit(void)
463{
464 i2c_del_driver(&bcm2079x_driver);
465}
466module_exit(bcm2079x_dev_exit);
467
468MODULE_AUTHOR("Broadcom");
469MODULE_DESCRIPTION("NFC bcm2079x driver");
470MODULE_LICENSE("GPL");