blob: 48e9ec47ae47a1510242622085fc122bb9f39088 [file] [log] [blame]
Shad Ansari2f7f9be2017-06-07 13:34:53 -07001/*
2<:copyright-BRCM:2016:DUAL/GPL:standard
3
4 Broadcom Proprietary and Confidential.(c) 2016 Broadcom
5 All Rights Reserved
6
7Unless you and Broadcom execute a separate written software license
8agreement governing use of this software, this software is licensed
9to you under the terms of the GNU General Public License version 2
10(the "GPL"), available at http://www.broadcom.com/licenses/GPLv2.php,
11with the following added to such license:
12
13 As a special exception, the copyright holders of this software give
14 you permission to link this software with independent modules, and
15 to copy and distribute the resulting executable under terms of your
16 choice, provided that you also meet, for each linked independent
17 module, the terms and conditions of the license of that module.
18 An independent module is a module which is not derived from this
19 software. The special exception does not apply to any modifications
20 of the software.
21
22Not withstanding the above, under no circumstances may you combine
23this software in any way with any other Broadcom software provided
24under a license other than the GPL, without Broadcom's express prior
25written consent.
26
27:>
28 */
29
30#include <linux/module.h>
31#include <linux/init.h>
32#include <linux/slab.h>
33#include <linux/jiffies.h>
34#include <linux/i2c.h>
35#include <linux/err.h>
36#include <linux/cdev.h>
37#include <asm/uaccess.h> /*copy_from_user*/
38#include <linux/proc_fs.h>
39#include "bcmos_system.h"
40#include "bcmolt_i2c_devs.h"
41#include "bcmolt_i2c_devs_ioctl.h"
42
43#define BCM_I2C_DEV_ADDR_START typedef enum {
44#define BCM_I2C_DEV_ADDR(name, desc, val) name = val,
45#define BCM_I2C_DEV_ADDR_END } bcm_i2c_dev_addr;
46
47#include "bcmolt_i2c_devs_addr.h"
48
49#define PROC_DIR_NAME "maple_i2c"
50#define PROC_ENTRY_NAME "i2c"
51#define MAX_EAGAIN_ITERS 200 /* 10ms per iter */
52
53/* uncomment the next line to enable debug output to the kernel CLI */
54/* #define I2C_DEBUG_PRINTS 1 */
55#ifdef I2C_DEBUG_PRINTS
56#define i2c_debug_print(fmt, args...) printk("%s#%d: " fmt, __FUNCTION__, __LINE__, ## args)
57#else
58#define i2c_debug_print(...)
59#endif
60
61int maple_i2c_chrdev_major = 216;
62module_param(maple_i2c_chrdev_major, int, S_IRUSR | S_IRGRP | S_IWGRP);
63MODULE_PARM_DESC(maple_i2c_chrdev_major, "maple_i2c_major");
64
65static struct proc_dir_entry *i2c_proc_dir;
66static struct proc_dir_entry *i2c_proc_entry;
67static char is_chrdev_reg;
68static char is_cdev_add;
69static int i2c_client_num;
70static int i2c_num_clients;
71
72const unsigned short normal_i2c[] = {
73 I2C_SW0_I2C_ADDR,
74 I2C_SW1_I2C_ADDR,
75 I2C_SW2_I2C_ADDR,
76 I2C_SW3_I2C_ADDR,
77 I2C_SW4_I2C_ADDR,
78 SFP_I2C_ADDR1,
79 SFP_I2C_ADDR2,
80 FPGA_I2C_ADDR,
81 PON_DPLL_I2C_ADDR,
82 PM_DPLL_I2C_ADDR,
83 CXP_R_I2C_ADDR,
84 PCIE_SW_I2C_ADDR,
85 I2C_CLIENT_END
86};
87
88static unsigned char slave_valid[SLAVE_NUM_OF_SLAVES] = {0};
89
90/*
91 * Driver data (common to all clients)
92 */
93
94static const struct i2c_device_id maple_i2c_id_table[] = {
95 { "maple_i2c", 0 },
96 { }
97};
98MODULE_DEVICE_TABLE(i2c, maple_i2c_id_table);
99
100static void bcm_access_fpga(void);
101
102/*
103 * Client data (each client gets its own)
104 */
105struct maple_i2c_data {
106 struct i2c_client client;
107};
108
109static struct maple_i2c_data *pclient_data_ar[SLAVE_NUM_OF_SLAVES];
110
111static int get_client(unsigned char client_num, struct i2c_client **client)
112{
113 if ((client_num >= SLAVE_NUM_OF_SLAVES) || !slave_valid[client_num])
114 {
115 i2c_debug_print("I2C error: Wrong client number 0x%x\n", client_num);
116 return -1;
117 }
118 *client = &pclient_data_ar[client_num]->client;
119
120 return 0;
121}
122
123
124/*
125 * Helper functions which attempt I2C transfer until successful, or error code is other than -EAGAIN
126 */
127
128static int maple_i2c_send(unsigned char client_num, u8 *buf, size_t count)
129{
130 struct i2c_client *client;
131 int rc;
132 int niter = 0;
133
134 if (get_client(client_num, &client))
135 return -1;
136
137 do {
138 rc = i2c_master_send(client, buf, count);
139 if (rc == -EAGAIN)
140 msleep(10);
141 } while (rc == -EAGAIN && ++niter < MAX_EAGAIN_ITERS);
142 rc = (rc == count) ? 0 : (rc < 0 ) ? rc : -1;
143
144 return rc;
145}
146
147static int maple_i2c_recv(unsigned char client_num, u8 *buf, size_t count)
148{
149 struct i2c_client *client;
150 int rc;
151 int niter = 0;
152
153 if (get_client(client_num, &client))
154 return -1;
155
156 do {
157 rc = i2c_master_recv(client, buf, count);
158 if (rc == -EAGAIN)
159 msleep(10);
160 } while (rc == -EAGAIN && ++niter < MAX_EAGAIN_ITERS);
161 rc = (rc == count) ? 0 : (rc < 0 ) ? rc : -1;
162
163 return rc;
164}
165
166
167static int maple_i2c_read_with_offset(unsigned char client_num, u8 *offset, size_t offset_size, u8 *buf, size_t count)
168{
169 struct i2c_client *client;
170 struct i2c_msg msg[2];
171 int rc;
172 int niter = 0;
173
174 if (get_client(client_num, &client))
175 return -1;
176
177 msg[0].addr = msg[1].addr = client->addr;
178 msg[0].flags = msg[1].flags = client->flags & I2C_M_TEN;
179
180 msg[0].len = offset_size;
181 msg[0].buf = offset;
182
183 msg[1].flags |= I2C_M_RD;
184 msg[1].len = count;
185 msg[1].buf = buf;
186
187 do {
188 rc = i2c_transfer(client->adapter, msg, 2);
189 if (rc == -EAGAIN)
190 msleep(10);
191 } while (rc == -EAGAIN && ++niter < MAX_EAGAIN_ITERS);
192
193 rc = (rc == 2) ? 0 : (rc < 0 ) ? rc : -1;
194
195 return rc;
196}
197
198ssize_t maple_i2c_write(unsigned char client_num, char *buf, size_t count)
199{
200 int rc;
201
202 i2c_debug_print("Write to switch: client=0x%x val = 0x%x\n", normal_i2c[client_num], *buf);
203 rc = maple_i2c_send(client_num, (u8 *)buf, count);
204
205 if (rc < 0)
206 i2c_debug_print("Write Failed. rc=%d client=%u[%u]\n", rc,
207 normal_i2c[client_num], client_num);
208 else
209 i2c_debug_print("Write Successful client=%u[%u]\n",
210 normal_i2c[client_num], client_num);
211 return rc;
212}
213EXPORT_SYMBOL(maple_i2c_write);
214
215ssize_t maple_i2c_read(unsigned char client_num, char *buf, size_t count)
216{
217 int rc;
218
219 i2c_debug_print("Read from switch: client 0x%x\n", normal_i2c[client_num]);
220 rc = maple_i2c_recv(client_num, (u8 *)buf, count);
221
222 if (rc < 0)
223 i2c_debug_print("Read Failed. rc=%d client=%u[%u]\n", rc,
224 normal_i2c[client_num], client_num);
225 else
226 i2c_debug_print("Read Successful: count=%u val = 0x%x\n", (unsigned)count, *buf);
227 return rc;
228}
229EXPORT_SYMBOL(maple_i2c_read);
230
231int maple_i2c_write_byte(unsigned char client_num, unsigned char offset, unsigned char val)
232{
233 u8 buf[2];
234 int rc;
235
236 i2c_debug_print("Write Byte: client=0x%x offset = 0x%x, val = 0x%x\n", normal_i2c[client_num], offset, val);
237
238 buf[0] = offset;
239 buf[1] = val;
240 rc = maple_i2c_send(client_num, buf, 2);
241
242 if (rc < 0)
243 i2c_debug_print("Write Byte Failed. rc=%d offset=0x%x val=0x%x client=%u[%u]\n",
244 rc, offset, val,
245 normal_i2c[client_num], client_num);
246 else
247 i2c_debug_print("Write Byte: offset=0x%x val=0x%x client=%u/%u\n",
248 offset, val,
249 normal_i2c[client_num], client_num);
250 return rc;
251}
252EXPORT_SYMBOL(maple_i2c_write_byte);
253
254int maple_i2c_read_byte(unsigned char client_num, unsigned char offset, unsigned char *data)
255{
256 u8 o = offset;
257 u8 val;
258 int rc;
259
260 i2c_debug_print("Write Byte: client=0x%x offset = 0x%x, val = 0x%x\n", normal_i2c[client_num], offset, val);
261
262 rc = maple_i2c_read_with_offset(client_num, &o, 1, &val, 1);
263
264 if (rc < 0)
265 i2c_debug_print("Read Byte Failed. rc=%d client=%u[%u]\n", rc,
266 normal_i2c[client_num], client_num);
267 else
268 {
269 *data = val;
270 i2c_debug_print("Read Byte: client=0x%x offset = 0x%x, val = 0x%x\n",
271 normal_i2c[client_num], offset, *data);
272 }
273 return rc;
274}
275EXPORT_SYMBOL(maple_i2c_read_byte);
276
277
278int maple_i2c_write_word(unsigned char client_num, unsigned char offset, unsigned short val)
279{
280 u8 buf[3];
281 int rc;
282
283 i2c_debug_print("Write Word: offset = 0x%x, val = 0x%x\n", offset, val);
284
285 /* The offset to be written should be the first byte in the I2C write */
286 buf[0] = offset;
287 buf[1] = (char)(val&0xFF);
288 buf[2] = (char)(val>>8);
289 rc = maple_i2c_send(client_num, buf, sizeof(buf));
290
291 if (rc < 0)
292 i2c_debug_print("Write Word Failed. rc=%d offset=0x%x val=0x%x, client=%u[%u]\n",
293 rc, offset, val,
294 normal_i2c[client_num], client_num);
295 else
296 i2c_debug_print("Write Word: offset=0x%x val=0x%x, client=%u[%u]\n",
297 offset, val,
298 normal_i2c[client_num], client_num);
299 return rc;
300}
301EXPORT_SYMBOL(maple_i2c_write_word);
302
303int maple_i2c_read_word(unsigned char client_num, unsigned char offset, unsigned short *data)
304{
305 u8 o = offset;
306 u8 buf[2];
307 int rc;
308
309 rc = maple_i2c_read_with_offset(client_num, &o, 1, buf, sizeof(buf));
310
311 if (rc < 0)
312 i2c_debug_print("Read Word Failed. rc=%d offset=0x%x client=%u[%u]\n",
313 rc, offset,
314 normal_i2c[client_num], client_num);
315 else
316 {
317 *data = (buf[1]<<8) | buf[0]; /* I2C data is LE */
318 i2c_debug_print("Read Word: offset = 0x%x, val = 0x%x client=%u[%u]\n",
319 offset, *data,
320 normal_i2c[client_num], client_num);
321 }
322 return rc;
323}
324EXPORT_SYMBOL(maple_i2c_read_word);
325
326
327int maple_i2c_write_reg(unsigned char client_num, unsigned char offset, int val)
328{
329 u8 buf[5];
330 int rc;
331
332 i2c_debug_print("Write Register: offset = 0x%x, val = 0x%x\n", offset, val);
333
334 /* Set the buf[0] to be the offset for write operation */
335 buf[0] = offset;
336
337 /* On the I2C bus, LS Byte should go first */
338 buf[1] = val & 0xff;
339 buf[2] = (val >> 8) & 0xff;
340 buf[3] = (val >> 16) & 0xff;
341 buf[4] = (val >> 24) & 0xff;
342 rc = maple_i2c_send(client_num, buf, sizeof(buf));
343
344 if (rc < 0)
345 i2c_debug_print("Write Reg Failed. rc=%d offset=0x%x val=0x%x client=%u[%u]\n",
346 rc, offset, val,
347 normal_i2c[client_num], client_num);
348 else
349 i2c_debug_print("Write Reg Successful. offset=0x%x val=0x%x client=%u[%u]\n",
350 offset, val,
351 normal_i2c[client_num], client_num);
352 return rc;
353}
354EXPORT_SYMBOL(maple_i2c_write_reg);
355
356
357int maple_i2c_read_reg(unsigned char client_num, unsigned char offset, unsigned int *data)
358{
359 u8 o = offset;
360 u8 buf[4];
361 int rc;
362
363 rc = maple_i2c_read_with_offset(client_num, &o, 1, buf, sizeof(buf));
364
365 if (rc < 0)
366 i2c_debug_print("Read Reg Failed. rc=%d offset=0x%x client=%u[%u]\n",
367 rc, offset,
368 normal_i2c[client_num], client_num);
369 else
370 {
371 *data = buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24); /* LS byte is transferred first */
372 i2c_debug_print("Read Register: client=0x%x offset = 0x%x, val = 0x%x\n", normal_i2c[client_num], offset, *data);
373 }
374 return rc;
375}
376EXPORT_SYMBOL(maple_i2c_read_reg);
377
378
379int maple_i2c_write_fpga(unsigned char client_num, unsigned int offset, unsigned int val)
380{
381 u8 buf[8];
382 int rc;
383
384 bcm_access_fpga();
385
386 i2c_debug_print("Write fpga: offset = 0x%x, val = 0x%x\n", offset, val);
387
388 /* Set the offset for write operation */
389 // offset = swab32(offset);
390 memcpy(&buf[0], (char*)&offset, 4);
391
392 /* On the I2C bus, LS Byte should go first */
393 // val = swab32(val);
394 memcpy(&buf[4], (char*)&val, 4);
395
396 rc = maple_i2c_send(client_num, buf, sizeof(buf));
397
398 if (rc < 0)
399 i2c_debug_print("Write FPGA Failed. rc=%d offset=0x%x val=0x%x client=%u[%u]\n",
400 rc, offset, val,
401 normal_i2c[client_num], client_num);
402 else
403 i2c_debug_print("Write FPGA: offset=0x%x val=0x%x client=%u[%u]\n",
404 offset, val,
405 normal_i2c[client_num], client_num);
406 return rc;
407}
408EXPORT_SYMBOL(maple_i2c_write_fpga);
409
410int maple_i2c_read_fpga(unsigned char client_num, unsigned int offset, unsigned int *data)
411{
412 u8 obuf[4];
413 u8 buf[4];
414 int rc;
415
416 bcm_access_fpga();
417
418 /* FPGA expects 4 byte offset in BIG ENDIAN format */
419 obuf[0] = (offset >> 24) & 0xff;
420 obuf[1] = (offset >> 16) & 0xff;
421 obuf[2] = (offset >> 8) & 0xff;
422 obuf[3] = offset & 0xff;
423 rc = maple_i2c_read_with_offset(client_num, obuf, sizeof(obuf), buf, sizeof(buf));
424
425 if (rc < 0)
426 i2c_debug_print("Read FPGA Failed. rc=%d offset=0x%x client=%u[%u]\n",
427 rc, offset,
428 normal_i2c[client_num], client_num);
429 else
430 {
431 *data = buf[3] | (buf[2] << 8) | (buf[1] << 16) | (buf[0] << 24); /* MS byte is transferred first */
432 i2c_debug_print("Read FPGA: offset = 0x%x, val = 0x%x %02x %02x %02x %02x client=%u[%u]\n",
433 offset, *data, buf[0], buf[1], buf[2], buf[3],
434 normal_i2c[client_num], client_num);
435 }
436 return rc;
437}
438EXPORT_SYMBOL(maple_i2c_read_fpga);
439
440enum client_num maple_i2c_get_client(u32 addr)
441{
442 enum client_num i = 0;
443 while (i < SLAVE_NUM_OF_SLAVES)
444 {
445 if (pclient_data_ar[i])
446 {
447 if (slave_valid[i] && pclient_data_ar[i]->client.addr == addr)
448 {
449 break;
450 }
451 }
452 i++;
453 }
454 return i;
455}
456EXPORT_SYMBOL(maple_i2c_get_client);
457
458static int dev_change(u32 addr)
459{
460 enum client_num i = maple_i2c_get_client(addr);
461
462 if (i < SLAVE_NUM_OF_SLAVES)
463 {
464 i2c_client_num = i;
465 i2c_debug_print("Slave was set successfully i %d, addr 0x%x\n", i, addr);
466 }
467 else
468 {
469 i2c_debug_print("Failed to set slave i %d, addr 0x%x\n", i, addr);
470 }
471
472 return 0;
473}
474
475static void bcm_access_fpga(void)
476{
477 static int access_enabled;
478 int fpga_client_num = maple_i2c_get_client(I2C_SW1_I2C_ADDR);
479 uint8_t b;
480
481 if (access_enabled)
482 return;
483 b = 4;
484 maple_i2c_write(fpga_client_num, &b, 1);
485 access_enabled = 1;
486}
487#define BCM_FPGA_REG_RESETS 0x2
488#define BCM_FPGA_REG_FPGA_VERSION 0x0
489/* 1 = out of reset bcm_board_config_reset_value */
490void reset_maple(int bit,int param)
491{
492 int fpga_client_num = maple_i2c_get_client(FPGA_I2C_ADDR);
493 int sw_client_num = maple_i2c_get_client(I2C_SW0_I2C_ADDR);
494 uint8_t b = 1;
495 uint32_t reset_values;
496
497 maple_i2c_write(sw_client_num, &b, 1);
498
499 /* Read-modify-write so we can set only the relevant bit */
500 maple_i2c_read_fpga(fpga_client_num, BCM_FPGA_REG_RESETS, &reset_values);
501
502 if (param)
503 reset_values |= 1 << bit;
504 else
505 reset_values &= ~(1 << bit);
506 maple_i2c_write_fpga(fpga_client_num, BCM_FPGA_REG_RESETS, reset_values);
507}
508EXPORT_SYMBOL(reset_maple);
509
510/* Calls the appropriate function based on user command */
511static int exec_command(const char *buf, size_t count)
512{
513#define MAX_ARGS 4
514#define MAX_ARG_SIZE 32
515 int i, argc = 0, val = 0;
516 char cmd;
517 u32 offset = 0;
518 char arg[MAX_ARGS][MAX_ARG_SIZE];
519#define LOG_WR_KBUF_SIZE 128
520 char kbuf[LOG_WR_KBUF_SIZE];
521
522 if ((count > LOG_WR_KBUF_SIZE-1) || (copy_from_user(kbuf, buf, count) != 0))
523 return -EFAULT;
524 kbuf[count]=0;
525 argc = sscanf(kbuf, "%c %s %s %s %s", &cmd, arg[0], arg[1], arg[2], arg[3]);
526
527 if (argc < 1)
528 {
529 printk("Need at-least 2 arguments\n");
530 return -EFAULT;
531 }
532
533 for (i=0; i<MAX_ARGS; ++i) {
534 arg[i][MAX_ARG_SIZE-1] = '\0';
535 }
536 offset = (u32)simple_strtoul(arg[0], NULL, 0);
537 if (argc == 3)
538 val = (int)simple_strtoul(arg[1], NULL, 0);
539
540 switch (cmd)
541 {
542 case 'm':
543 reset_maple(0,offset); // maple out of reset(1) | reset (0)
544 break;
545 case 'k':
546 reset_maple(4,offset); // katana2 out of reset(1) | reset (0)
547 break;
548 case 'b':
549 if (argc == 3)
550 maple_i2c_write_byte(i2c_client_num, (u8)offset, (u8)val);
551 else
552 {
553 u8 data;
554 maple_i2c_read_byte(i2c_client_num, (u8)offset, &data);
555 printk("client 0x%x, offset 0x%x, data=0x%x\n", normal_i2c[i2c_client_num], offset, data);
556 }
557 break;
558
559 case 's':
560 if (argc == 2)
561 {
562 u8 data = (u8)offset;
563 maple_i2c_write(i2c_client_num, &data, 1);
564 }
565 else
566 {
567 u8 data = offset;
568 maple_i2c_read(i2c_client_num, &data, 1);
569 printk("client 0x%x, data=0x%x\n", normal_i2c[i2c_client_num], data);
570 }
571 break;
572
573 case 'w':
574 if (argc == 3)
575 maple_i2c_write_word(i2c_client_num, (u8)offset, (u16)val);
576 else
577 {
578 u16 data;
579 maple_i2c_read_word(i2c_client_num, (u8)offset, &data);
580 printk("client 0x%x, offset 0x%x, data=0x%x\n", normal_i2c[i2c_client_num], offset, data);
581 }
582 break;
583
584 case 'd':
585 if (argc == 3)
586 maple_i2c_write_reg(i2c_client_num, (u8)offset, val);
587 else
588 {
589 u32 data;
590 maple_i2c_read_reg(i2c_client_num, (u8)offset, &data);
591 printk("client 0x%x, offset 0x%x, data=0x%x\n", normal_i2c[i2c_client_num], offset, data);
592 }
593 break;
594
595 case 'f':
596 if (argc == 3)
597 maple_i2c_write_fpga(i2c_client_num, offset, val);
598 else
599 {
600 u32 data;
601 maple_i2c_read_fpga(i2c_client_num, offset, &data);
602 printk("client 0x%x, offset 0x%x, data=0x%x\n", normal_i2c[i2c_client_num], offset, data);
603 }
604 break;
605
606 case 'c':
607 dev_change(offset);
608 break;
609
610 default:
611 printk("Invalid command.\n Valid commands:\n"
612 " Change I2C Addr: c addr\n"
613 " Write Reg: d offset val\n"
614 " Read Reg: d offset\n"
615 " Write Word: w offset val\n"
616 " Read Word: w offset\n"
617 " Write Byte: b offset val\n"
618 " Read Byte: b offset\n"
619 " Write fpga: f offset val\n"
620 " Read fpga: f offset\n"
621 " Write to switch: s val (one byte)\n"
622 " Read from switch:s\n"
623 " Maple: m <0|1>\n"
624 " Katana2: k <0|1>\n"
625 );
626 break;
627 }
628 return count;
629}
630
631
632
633/* Read Function of PROCFS attribute "maple_i2c/test" */
634static ssize_t maple_i2c_proc_test_read(struct file *f, char *buf, size_t count,
635 loff_t *pos)
636{
637 printk(" Usage: echo command > "
638 " /proc/maple_i2c/test\n");
639 printk(" supported commands:\n"
640 " Change I2C Addr: c addr\n"
641 " Write Reg: d offset val\n"
642 " Read Reg: d offset\n"
643 " Write Word: w offset val\n"
644 " Read Word: w offset\n"
645 " Write Byte: b offset val\n"
646 " Read Byte: b offset\n"
647 " Write fpga: f offset val\n"
648 " Read fpga: f offset\n"
649 " Write to switch: s val (one byte)\n"
650 " Read from switch:s\n"
651 );
652 return 0;
653}
654
655/* Write Function of PROCFS attribute "maple_i2c/test" */
656static ssize_t maple_i2c_proc_test_write(struct file *f, const char *buf,
657 size_t count, loff_t *pos)
658{
659 return exec_command(buf, count);
660}
661
662/* Return 0 if detection is successful, -ENODEV otherwise */
663static int maple_i2c_dev_detect(struct i2c_client *client, struct i2c_board_info *info)
664{
665 i2c_debug_print("detecting i2c device 0x%x\n", client->addr);
666
667 /* TODO: detection and identification */
668
669 strcpy(info->type, "maple_i2c");
670 info->flags = 0;
671 return 0;
672}
673
674static struct file_operations maple_i2c_fops =
675{
676 read: maple_i2c_proc_test_read,
677 write: maple_i2c_proc_test_write
678};
679
680static int maple_i2c_dev_create_proc(void)
681{
682 i2c_proc_dir = proc_mkdir(PROC_DIR_NAME, NULL);
683 if (!i2c_proc_dir)
684 {
685 i2c_debug_print("fail to create proc dir\n");
686 return -ENOMEM;
687 }
688
689 i2c_proc_entry = create_proc_entry(PROC_ENTRY_NAME, 0, i2c_proc_dir);
690 if (!i2c_proc_entry)
691 {
692 remove_proc_entry(PROC_DIR_NAME, NULL);
693 return -ENOMEM;
694 }
695
696 i2c_proc_entry->proc_fops = &maple_i2c_fops;
697
698 return 0;
699}
700
701static int maple_i2c_chrdev_open(struct inode *inode, struct file *filp)
702{
703 return 0;
704}
705
706static int maple_i2c_chrdev_release(struct inode *inode, struct file *filp)
707{
708 return 0;
709}
710
711static long maple_i2c_chrdev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
712{
713 int linux_rc = 0;
714 int rc;
715 maple_i2c_ioctl_param params;
716
717 /* don't even decode wrong cmds: better returning ENOTTY than EFAULT */
718 if (_IOC_TYPE(cmd) != MAPLE_I2C_IOCTL_MAGIC)
719 return -ENOTTY;
720
721 /*
722 * the type is a bitmask, and VERIFY_WRITE catches R/W
723 * transfers. Note that the type is user-oriented, while
724 * verify_area is kernel-oriented, so the concept of "read" and
725 * "write" is reversed
726 */
727 if (_IOC_DIR(cmd) & _IOC_READ)
728 linux_rc = !access_ok(VERIFY_WRITE, (void __user *)arg, _IOC_SIZE(cmd));
729 else if (_IOC_DIR(cmd) & _IOC_WRITE)
730 linux_rc = !access_ok(VERIFY_READ, (void __user *)arg, _IOC_SIZE(cmd));
731 if (linux_rc)
732 return -EFAULT;
733
734 switch (cmd)
735 {
736 case MAPLE_I2C_IOCTL_OP_DEV_CHANGE:
737 {
738 linux_rc = copy_from_user((char *)&params, (char *)arg, sizeof(params));
739 if (linux_rc < 0)
740 break;
741 return dev_change(params.addr);
742 }
743 break;
744 case MAPLE_I2C_IOCTL_OP_DEV_WRITE:
745 {
746 linux_rc = copy_from_user((char *)&params, (char *)arg, sizeof(params));
747 if (linux_rc < 0)
748 break;
749 switch (params.count)
750 {
751 case 8:
752 return maple_i2c_write_byte(i2c_client_num, params.addr, params.val);
753 case 16:
754 return maple_i2c_write_word(i2c_client_num, params.addr, params.val);
755 case 32:
756 return maple_i2c_write_reg(i2c_client_num, params.addr, params.val);
757 default:
758 return -EINVAL;
759 }
760 }
761 break;
762 case MAPLE_I2C_IOCTL_OP_DEV_READ:
763 {
764 unsigned char b;
765 unsigned short w;
766 unsigned int r;
767
768 linux_rc = copy_from_user((char *)&params, (char *)arg, sizeof(params));
769 if (linux_rc < 0)
770 break;
771 switch (params.count)
772 {
773 case 8:
774 linux_rc = maple_i2c_read_byte(i2c_client_num, params.addr, &b);
775 if (linux_rc < 0)
776 break;
777 params.val = b;
778 break;
779 case 16:
780 linux_rc = maple_i2c_read_word(i2c_client_num, params.addr, &w);
781 if (linux_rc < 0)
782 break;
783 params.val = w;
784 break;
785 case 32:
786 linux_rc = maple_i2c_read_reg(i2c_client_num, params.addr, &r);
787 if (linux_rc < 0)
788 break;
789 params.val = r;
790 break;
791 default:
792 return -EINVAL;
793 }
794 if (linux_rc < 0)
795 break;
796 return copy_to_user((char *)arg, (char *)&params, sizeof(params));
797 }
798 case MAPLE_I2C_IOCTL_OP_SWITCH_WRITE:
799 {
800 char b;
801
802 linux_rc = copy_from_user((char *)&params, (char *)arg, sizeof(params));
803 if (linux_rc < 0)
804 break;
805 b = params.val;
806 return maple_i2c_write(i2c_client_num, &b, 1);
807 }
808 case MAPLE_I2C_IOCTL_OP_SWITCH_READ:
809 {
810 char b;
811
812 linux_rc = maple_i2c_read(i2c_client_num, &b, 1);
813 if (linux_rc < 0)
814 break;
815 params.val = b;
816 return copy_to_user((char *)arg, (char *)&params, sizeof(params));
817 }
818 case MAPLE_I2C_IOCTL_OP_FPGA_WRITE:
819 {
820 linux_rc = copy_from_user((char *)&params, (char *)arg, sizeof(params));
821 if (linux_rc < 0)
822 break;
823 return maple_i2c_write_fpga(i2c_client_num, params.addr, params.val);
824 }
825 case MAPLE_I2C_IOCTL_OP_FPGA_READ:
826 {
827 linux_rc = copy_from_user((char *)&params, (char *)arg, sizeof(params));
828 if (linux_rc < 0)
829 break;
830 linux_rc = maple_i2c_read_fpga(i2c_client_num, params.addr, &params.val);
831 if (linux_rc < 0)
832 break;
833 return copy_to_user((char *)arg, (char *)&params, sizeof(params));
834 }
835 default:
836 rc = -ENOTTY;
837 break;
838 }
839
840 return linux_rc;
841}
842
843static ssize_t maple_i2c_chrdev_write(struct file *filp, const char __user *buf,
844 size_t count, loff_t *f_pos)
845{
846 return 0;
847}
848
849static struct file_operations maple_i2c_chrdev_fops =
850{
851 .owner = THIS_MODULE,
852 .open = maple_i2c_chrdev_open,
853 .release = maple_i2c_chrdev_release,
854 .write = maple_i2c_chrdev_write,
855 .unlocked_ioctl = maple_i2c_chrdev_ioctl
856};
857
858static struct cdev maple_i2c_chrdev_cdev;
859
860static int maple_i2c_dev_create_chrdev(void)
861{
862 dev_t dev = MKDEV(maple_i2c_chrdev_major, 0);
863 int linux_rc;
864
865 is_chrdev_reg = 0;
866 is_cdev_add = 0;
867 /*
868 * Register your major, and accept a dynamic number.
869 */
870 if (!maple_i2c_chrdev_major)
871 return -1;
872 linux_rc = register_chrdev_region(dev, 0, "maple_i2c");
873 if (linux_rc < 0)
874 {
875 i2c_debug_print("register_chrdev_region()->%d\n", linux_rc);
876 return -EIO;
877 }
878 is_chrdev_reg = 1;
879
880 cdev_init(&maple_i2c_chrdev_cdev, &maple_i2c_chrdev_fops);
881 linux_rc = cdev_add(&maple_i2c_chrdev_cdev, dev, 1);
882 if (linux_rc < 0)
883 {
884 i2c_debug_print("cdev_add()->%d\n", linux_rc);
885 return -EIO;
886 }
887 is_cdev_add = 1;
888
889 return 0;
890}
891
892static int maple_i2c_dev_probe(struct i2c_client *client, const struct i2c_device_id *id)
893{
894 int err = 0;
895 struct maple_i2c_data *pclient_data;
896
897 i2c_debug_print("!!!! i2c device 0x%x probe\n", client->addr);
898
899 if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
900 goto exit;
901
902 if (!(pclient_data = kzalloc(sizeof(struct maple_i2c_data), GFP_KERNEL)))
903 {
904 err = -ENOMEM;
905 goto exit;
906 }
907
908 pclient_data->client.addr = client->addr;
909 pclient_data->client.adapter = client->adapter;
910 pclient_data->client.driver = client->driver;
911 pclient_data->client.flags = client->flags;
912
913 i2c_set_clientdata(client, pclient_data);
914
915 switch(client->addr)
916 {
917 case I2C_SW0_I2C_ADDR:
918 pclient_data_ar[SLAVE_SWITCH_70] = pclient_data;
919 slave_valid[SLAVE_SWITCH_70] = 1;
920 break;
921 case I2C_SW1_I2C_ADDR:
922 pclient_data_ar[SLAVE_SWITCH_71] = pclient_data;
923 slave_valid[SLAVE_SWITCH_71] = 1;
924 break;
925 case I2C_SW2_I2C_ADDR:
926 pclient_data_ar[SLAVE_SWITCH_72] = pclient_data;
927 slave_valid[SLAVE_SWITCH_72] = 1;
928 break;
929 case I2C_SW3_I2C_ADDR:
930 pclient_data_ar[SLAVE_SWITCH_73] = pclient_data;
931 slave_valid[SLAVE_SWITCH_73] = 1;
932 break;
933 case I2C_SW4_I2C_ADDR:
934 pclient_data_ar[SLAVE_SWITCH_74] = pclient_data;
935 slave_valid[SLAVE_SWITCH_74] = 1;
936 break;
937 case SFP_I2C_ADDR1:
938 pclient_data_ar[SLAVE_SFP_50] = pclient_data;
939 slave_valid[SLAVE_SFP_50] = 1;
940 break;
941 case SFP_I2C_ADDR2:
942 pclient_data_ar[SLAVE_SFP_51] = pclient_data;
943 slave_valid[SLAVE_SFP_51] = 1;
944 break;
945 case FPGA_I2C_ADDR:
946 pclient_data_ar[SLAVE_FPGA_40] = pclient_data;
947 slave_valid[SLAVE_FPGA_40] = 1;
948 break;
949 case PON_DPLL_I2C_ADDR:
950 pclient_data_ar[SLAVE_PON_DPLL_68] = pclient_data;
951 slave_valid[SLAVE_PON_DPLL_68] = 1;
952 break;
953 case PM_DPLL_I2C_ADDR:
954 pclient_data_ar[SLAVE_PM_DPLL_6A] = pclient_data;
955 slave_valid[SLAVE_PM_DPLL_6A] = 1;
956 break;
957 case CXP_R_I2C_ADDR:
958 pclient_data_ar[SLAVE_CXP_R_54] = pclient_data;
959 slave_valid[SLAVE_CXP_R_54] = 1;
960 break;
961 case PCIE_SW_I2C_ADDR:
962 pclient_data_ar[SLAVE_PCIE_SW_3C] = pclient_data;
963 slave_valid[SLAVE_PCIE_SW_3C] = 1;
964 break;
965 default:
966 i2c_debug_print("%s client addr out of range 0x%x\n", __FUNCTION__, client->addr);
967 goto exit_kfree;
968 }
969
970 /* Create only once */
971 if (i2c_proc_entry == NULL)
972 {
973 if (maple_i2c_dev_create_proc() < 0)
974 goto exit_kfree;
975 }
976 if (!is_cdev_add)
977 {
978 if (maple_i2c_dev_create_chrdev() < 0)
979 goto exit_kfree;
980 }
981 ++i2c_num_clients;
982
983 return 0;
984
985exit_kfree:
986 kfree(pclient_data);
987exit:
988 return err;
989}
990
991static int maple_i2c_dev_remove(struct i2c_client *client)
992{
993 kfree(i2c_get_clientdata(client));
994 --i2c_num_clients;
995 if (!i2c_num_clients)
996 {
997 if (i2c_proc_entry != NULL)
998 {
999 remove_proc_entry(PROC_ENTRY_NAME, i2c_proc_dir);
1000 i2c_proc_entry = NULL;
1001 }
1002 if (i2c_proc_dir != NULL)
1003 {
1004 remove_proc_entry(PROC_DIR_NAME, NULL);
1005 i2c_proc_dir = NULL;
1006 }
1007 if (is_cdev_add)
1008 {
1009 cdev_del(&maple_i2c_chrdev_cdev);
1010 is_cdev_add = 0;
1011 }
1012 if (is_chrdev_reg)
1013 {
1014 unregister_chrdev_region(MKDEV(maple_i2c_chrdev_major, 0), 1);
1015 is_chrdev_reg = 0;
1016 }
1017 }
1018
1019 return 0;
1020}
1021
1022static struct i2c_driver maple_i2c_dev_driver = {
1023 .class = ~0,
1024 .driver = {
1025 .name = "maple_i2c",
1026 },
1027 .probe = maple_i2c_dev_probe,
1028 .remove = maple_i2c_dev_remove,
1029 .id_table = maple_i2c_id_table,
1030 .detect = maple_i2c_dev_detect,
1031 .address_list = normal_i2c,
1032};
1033
1034module_i2c_driver(maple_i2c_dev_driver);
1035
1036MODULE_DESCRIPTION("maple i2c devices");
1037MODULE_LICENSE("GPL");
1038