aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/mfd/Kconfig14
-rw-r--r--drivers/mfd/Makefile1
-rw-r--r--drivers/mfd/viperboard.c129
-rw-r--r--include/linux/mfd/viperboard.h105
4 files changed, 249 insertions, 0 deletions
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 34242cada125..b280639a7634 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -1065,6 +1065,20 @@ config MFD_PALMAS
1065 If you say yes here you get support for the Palmas 1065 If you say yes here you get support for the Palmas
1066 series of PMIC chips from Texas Instruments. 1066 series of PMIC chips from Texas Instruments.
1067 1067
1068config MFD_VIPERBOARD
1069 tristate "Support for Nano River Technologies Viperboard"
1070 select MFD_CORE
1071 depends on USB
1072 default n
1073 help
1074 Say yes here if you want support for Nano River Technologies
1075 Viperboard.
1076 There are mfd cell drivers available for i2c master, adc and
1077 both gpios found on the board. The spi part does not yet
1078 have a driver.
1079 You need to select the mfd cell drivers separately.
1080 The drivers do not support all features the board exposes.
1081
1068endmenu 1082endmenu
1069endif 1083endif
1070 1084
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 632cce09e407..1c3ee7c76906 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -139,6 +139,7 @@ obj-$(CONFIG_MFD_TPS65090) += tps65090.o
139obj-$(CONFIG_MFD_AAT2870_CORE) += aat2870-core.o 139obj-$(CONFIG_MFD_AAT2870_CORE) += aat2870-core.o
140obj-$(CONFIG_MFD_INTEL_MSIC) += intel_msic.o 140obj-$(CONFIG_MFD_INTEL_MSIC) += intel_msic.o
141obj-$(CONFIG_MFD_PALMAS) += palmas.o 141obj-$(CONFIG_MFD_PALMAS) += palmas.o
142obj-$(CONFIG_MFD_VIPERBOARD) += viperboard.o
142obj-$(CONFIG_MFD_RC5T583) += rc5t583.o rc5t583-irq.o 143obj-$(CONFIG_MFD_RC5T583) += rc5t583.o rc5t583-irq.o
143obj-$(CONFIG_MFD_SEC_CORE) += sec-core.o sec-irq.o 144obj-$(CONFIG_MFD_SEC_CORE) += sec-core.o sec-irq.o
144obj-$(CONFIG_MFD_SYSCON) += syscon.o 145obj-$(CONFIG_MFD_SYSCON) += syscon.o
diff --git a/drivers/mfd/viperboard.c b/drivers/mfd/viperboard.c
new file mode 100644
index 000000000000..cd1e2fe95647
--- /dev/null
+++ b/drivers/mfd/viperboard.c
@@ -0,0 +1,129 @@
1/*
2 * Nano River Technologies viperboard driver
3 *
4 * This is the core driver for the viperboard. There are cell drivers
5 * available for I2C, ADC and both GPIOs. SPI is not yet supported.
6 * The drivers do not support all features the board exposes. See user
7 * manual of the viperboard.
8 *
9 * (C) 2012 by Lemonage GmbH
10 * Author: Lars Poeschel <poeschel@lemonage.de>
11 * All rights reserved.
12 *
13 * This program is free software; you can redistribute it and/or modify it
14 * under the terms of the GNU General Public License as published by the
15 * Free Software Foundation; either version 2 of the License, or (at your
16 * option) any later version.
17 *
18 */
19
20#include <linux/kernel.h>
21#include <linux/errno.h>
22#include <linux/module.h>
23#include <linux/slab.h>
24#include <linux/types.h>
25#include <linux/mutex.h>
26
27#include <linux/mfd/core.h>
28#include <linux/mfd/viperboard.h>
29
30#include <linux/usb.h>
31
32
33static const struct usb_device_id vprbrd_table[] = {
34 { USB_DEVICE(0x2058, 0x1005) }, /* Nano River Technologies */
35 { } /* Terminating entry */
36};
37
38MODULE_DEVICE_TABLE(usb, vprbrd_table);
39
40static struct mfd_cell vprbrd_devs[] = {
41};
42
43static int vprbrd_probe(struct usb_interface *interface,
44 const struct usb_device_id *id)
45{
46 struct vprbrd *vb;
47
48 u16 version = 0;
49 int pipe, ret;
50 unsigned char buf[1];
51
52 /* allocate memory for our device state and initialize it */
53 vb = kzalloc(sizeof(*vb), GFP_KERNEL);
54 if (vb == NULL) {
55 dev_err(&interface->dev, "Out of memory\n");
56 return -ENOMEM;
57 }
58
59 mutex_init(&vb->lock);
60
61 vb->usb_dev = usb_get_dev(interface_to_usbdev(interface));
62
63 /* save our data pointer in this interface device */
64 usb_set_intfdata(interface, vb);
65 dev_set_drvdata(&vb->pdev.dev, vb);
66
67 /* get version information, major first, minor then */
68 pipe = usb_rcvctrlpipe(vb->usb_dev, 0);
69 ret = usb_control_msg(vb->usb_dev, pipe, VPRBRD_USB_REQUEST_MAJOR,
70 VPRBRD_USB_TYPE_IN, 0x0000, 0x0000, buf, 1,
71 VPRBRD_USB_TIMEOUT_MS);
72 if (ret == 1)
73 version = buf[0];
74
75 ret = usb_control_msg(vb->usb_dev, pipe, VPRBRD_USB_REQUEST_MINOR,
76 VPRBRD_USB_TYPE_IN, 0x0000, 0x0000, buf, 1,
77 VPRBRD_USB_TIMEOUT_MS);
78 if (ret == 1) {
79 version <<= 8;
80 version = version | buf[0];
81 }
82
83 dev_info(&interface->dev,
84 "version %x.%02x found at bus %03d address %03d\n",
85 version >> 8, version & 0xff,
86 vb->usb_dev->bus->busnum, vb->usb_dev->devnum);
87
88 ret = mfd_add_devices(&interface->dev, -1, vprbrd_devs,
89 ARRAY_SIZE(vprbrd_devs), NULL, 0, NULL);
90 if (ret != 0) {
91 dev_err(&interface->dev, "Failed to add mfd devices to core.");
92 goto error;
93 }
94
95 return 0;
96
97error:
98 if (vb) {
99 usb_put_dev(vb->usb_dev);
100 kfree(vb);
101 }
102
103 return ret;
104}
105
106static void vprbrd_disconnect(struct usb_interface *interface)
107{
108 struct vprbrd *vb = usb_get_intfdata(interface);
109
110 mfd_remove_devices(&interface->dev);
111 usb_set_intfdata(interface, NULL);
112 usb_put_dev(vb->usb_dev);
113 kfree(vb);
114
115 dev_dbg(&interface->dev, "disconnected\n");
116}
117
118static struct usb_driver vprbrd_driver = {
119 .name = "viperboard",
120 .probe = vprbrd_probe,
121 .disconnect = vprbrd_disconnect,
122 .id_table = vprbrd_table,
123};
124
125module_usb_driver(vprbrd_driver);
126
127MODULE_DESCRIPTION("Nano River Technologies viperboard mfd core driver");
128MODULE_AUTHOR("Lars Poeschel <poeschel@lemonage.de>");
129MODULE_LICENSE("GPL");
diff --git a/include/linux/mfd/viperboard.h b/include/linux/mfd/viperboard.h
new file mode 100644
index 000000000000..0d1342466db5
--- /dev/null
+++ b/include/linux/mfd/viperboard.h
@@ -0,0 +1,105 @@
1/*
2 * include/linux/mfd/viperboard.h
3 *
4 * Nano River Technologies viperboard definitions
5 *
6 * (C) 2012 by Lemonage GmbH
7 * Author: Lars Poeschel <poeschel@lemonage.de>
8 * All rights reserved.
9 *
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by the
12 * Free Software Foundation; either version 2 of the License, or (at your
13 * option) any later version.
14 *
15 */
16
17#ifndef __MFD_VIPERBOARD_H__
18#define __MFD_VIPERBOARD_H__
19
20#include <linux/types.h>
21#include <linux/usb.h>
22
23#define VPRBRD_EP_OUT 0x02
24#define VPRBRD_EP_IN 0x86
25
26#define VPRBRD_I2C_MSG_LEN 512 /* max length of a msg on USB level */
27
28#define VPRBRD_I2C_FREQ_6MHZ 1 /* 6 MBit/s */
29#define VPRBRD_I2C_FREQ_3MHZ 2 /* 3 MBit/s */
30#define VPRBRD_I2C_FREQ_1MHZ 3 /* 1 MBit/s */
31#define VPRBRD_I2C_FREQ_FAST 4 /* 400 kbit/s */
32#define VPRBRD_I2C_FREQ_400KHZ VPRBRD_I2C_FREQ_FAST
33#define VPRBRD_I2C_FREQ_200KHZ 5 /* 200 kbit/s */
34#define VPRBRD_I2C_FREQ_STD 6 /* 100 kbit/s */
35#define VPRBRD_I2C_FREQ_100KHZ VPRBRD_I2C_FREQ_STD
36#define VPRBRD_I2C_FREQ_10KHZ 7 /* 10 kbit/s */
37
38#define VPRBRD_I2C_CMD_WRITE 0x00
39#define VPRBRD_I2C_CMD_READ 0x01
40#define VPRBRD_I2C_CMD_ADDR 0x02
41
42#define VPRBRD_USB_TYPE_OUT 0x40
43#define VPRBRD_USB_TYPE_IN 0xc0
44#define VPRBRD_USB_TIMEOUT_MS 100
45#define VPRBRD_USB_REQUEST_MAJOR 0xea
46#define VPRBRD_USB_REQUEST_MINOR 0xeb
47
48struct vprbrd_i2c_write_hdr {
49 u8 cmd;
50 u16 addr;
51 u8 len1;
52 u8 len2;
53 u8 last;
54 u8 chan;
55 u16 spi;
56} __packed;
57
58struct vprbrd_i2c_read_hdr {
59 u8 cmd;
60 u16 addr;
61 u8 len0;
62 u8 len1;
63 u8 len2;
64 u8 len3;
65 u8 len4;
66 u8 len5;
67 u16 tf1; /* transfer 1 length */
68 u16 tf2; /* transfer 2 length */
69} __packed;
70
71struct vprbrd_i2c_status {
72 u8 unknown[11];
73 u8 status;
74} __packed;
75
76struct vprbrd_i2c_write_msg {
77 struct vprbrd_i2c_write_hdr header;
78 u8 data[VPRBRD_I2C_MSG_LEN
79 - sizeof(struct vprbrd_i2c_write_hdr)];
80} __packed;
81
82struct vprbrd_i2c_read_msg {
83 struct vprbrd_i2c_read_hdr header;
84 u8 data[VPRBRD_I2C_MSG_LEN
85 - sizeof(struct vprbrd_i2c_read_hdr)];
86} __packed;
87
88struct vprbrd_i2c_addr_msg {
89 u8 cmd;
90 u8 addr;
91 u8 unknown1;
92 u16 len;
93 u8 unknown2;
94 u8 unknown3;
95} __packed;
96
97/* Structure to hold all device specific stuff */
98struct vprbrd {
99 struct usb_device *usb_dev; /* the usb device for this device */
100 struct mutex lock;
101 u8 buf[sizeof(struct vprbrd_i2c_write_msg)];
102 struct platform_device pdev;
103};
104
105#endif /* __MFD_VIPERBOARD_H__ */