aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/misc
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2011-07-26 00:00:19 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2011-07-26 00:00:19 -0400
commit45b583b10a8b438b970e95a7d1d4db22c9e35004 (patch)
tree14fa481598289df0459580c582b48a9d95db51f6 /drivers/misc
parent154dd78d30b56ffb8b447f629bfcceb14150e5c4 (diff)
parentf19da2ce8ef5e49b8b8ea199c3601dd45d71b262 (diff)
Merge 'akpm' patch series
* Merge akpm patch series: (122 commits) drivers/connector/cn_proc.c: remove unused local Documentation/SubmitChecklist: add RCU debug config options reiserfs: use hweight_long() reiserfs: use proper little-endian bitops pnpacpi: register disabled resources drivers/rtc/rtc-tegra.c: properly initialize spinlock drivers/rtc/rtc-twl.c: check return value of twl_rtc_write_u8() in twl_rtc_set_time() drivers/rtc: add support for Qualcomm PMIC8xxx RTC drivers/rtc/rtc-s3c.c: support clock gating drivers/rtc/rtc-mpc5121.c: add support for RTC on MPC5200 init: skip calibration delay if previously done misc/eeprom: add eeprom access driver for digsy_mtc board misc/eeprom: add driver for microwire 93xx46 EEPROMs checkpatch.pl: update $logFunctions checkpatch: make utf-8 test --strict checkpatch.pl: add ability to ignore various messages checkpatch: add a "prefer __aligned" check checkpatch: validate signature styles and To: and Cc: lines checkpatch: add __rcu as a sparse modifier checkpatch: suggest using min_t or max_t ... Did this as a merge because of (trivial) conflicts in - Documentation/feature-removal-schedule.txt - arch/xtensa/include/asm/uaccess.h that were just easier to fix up in the merge than in the patch series.
Diffstat (limited to 'drivers/misc')
-rw-r--r--drivers/misc/Kconfig12
-rw-r--r--drivers/misc/Makefile1
-rw-r--r--drivers/misc/eeprom/Kconfig25
-rw-r--r--drivers/misc/eeprom/Makefile2
-rw-r--r--drivers/misc/eeprom/digsy_mtc_eeprom.c85
-rw-r--r--drivers/misc/eeprom/eeprom_93xx46.c410
-rw-r--r--drivers/misc/fsa9480.c557
-rw-r--r--drivers/misc/pch_phub.c5
8 files changed, 1094 insertions, 3 deletions
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 4e349cd98bcf..0a4d86c6c4a4 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -245,8 +245,7 @@ config SGI_XP
245 245
246config CS5535_MFGPT 246config CS5535_MFGPT
247 tristate "CS5535/CS5536 Geode Multi-Function General Purpose Timer (MFGPT) support" 247 tristate "CS5535/CS5536 Geode Multi-Function General Purpose Timer (MFGPT) support"
248 depends on PCI 248 depends on PCI && X86 && MFD_CS5535
249 depends on X86
250 default n 249 default n
251 help 250 help
252 This driver provides access to MFGPT functionality for other 251 This driver provides access to MFGPT functionality for other
@@ -490,6 +489,15 @@ config PCH_PHUB
490 To compile this driver as a module, choose M here: the module will 489 To compile this driver as a module, choose M here: the module will
491 be called pch_phub. 490 be called pch_phub.
492 491
492config USB_SWITCH_FSA9480
493 tristate "FSA9480 USB Switch"
494 depends on I2C
495 help
496 The FSA9480 is a USB port accessory detector and switch.
497 The FSA9480 is fully controlled using I2C and enables USB data,
498 stereo and mono audio, video, microphone and UART data to use
499 a common connector port.
500
493source "drivers/misc/c2port/Kconfig" 501source "drivers/misc/c2port/Kconfig"
494source "drivers/misc/eeprom/Kconfig" 502source "drivers/misc/eeprom/Kconfig"
495source "drivers/misc/cb710/Kconfig" 503source "drivers/misc/cb710/Kconfig"
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index 5f03172cc0b5..33282157bc3c 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -46,3 +46,4 @@ obj-y += ti-st/
46obj-$(CONFIG_AB8500_PWM) += ab8500-pwm.o 46obj-$(CONFIG_AB8500_PWM) += ab8500-pwm.o
47obj-y += lis3lv02d/ 47obj-y += lis3lv02d/
48obj-y += carma/ 48obj-y += carma/
49obj-$(CONFIG_USB_SWITCH_FSA9480) += fsa9480.o
diff --git a/drivers/misc/eeprom/Kconfig b/drivers/misc/eeprom/Kconfig
index 9118613af321..26cf12ca7f50 100644
--- a/drivers/misc/eeprom/Kconfig
+++ b/drivers/misc/eeprom/Kconfig
@@ -70,4 +70,29 @@ config EEPROM_93CX6
70 70
71 If unsure, say N. 71 If unsure, say N.
72 72
73config EEPROM_93XX46
74 tristate "Microwire EEPROM 93XX46 support"
75 depends on SPI && SYSFS
76 help
77 Driver for the microwire EEPROM chipsets 93xx46x. The driver
78 supports both read and write commands and also the command to
79 erase the whole EEPROM.
80
81 This driver can also be built as a module. If so, the module
82 will be called eeprom_93xx46.
83
84 If unsure, say N.
85
86config EEPROM_DIGSY_MTC_CFG
87 bool "DigsyMTC display configuration EEPROMs device"
88 depends on PPC_MPC5200_GPIO && GPIOLIB && SPI_GPIO
89 help
90 This option enables access to display configuration EEPROMs
91 on digsy_mtc board. You have to additionally select Microwire
92 EEPROM 93XX46 driver. sysfs entries will be created for that
93 EEPROM allowing to read/write the configuration data or to
94 erase the whole EEPROM.
95
96 If unsure, say N.
97
73endmenu 98endmenu
diff --git a/drivers/misc/eeprom/Makefile b/drivers/misc/eeprom/Makefile
index df3d68ffa9d1..fc1e81d29267 100644
--- a/drivers/misc/eeprom/Makefile
+++ b/drivers/misc/eeprom/Makefile
@@ -3,3 +3,5 @@ obj-$(CONFIG_EEPROM_AT25) += at25.o
3obj-$(CONFIG_EEPROM_LEGACY) += eeprom.o 3obj-$(CONFIG_EEPROM_LEGACY) += eeprom.o
4obj-$(CONFIG_EEPROM_MAX6875) += max6875.o 4obj-$(CONFIG_EEPROM_MAX6875) += max6875.o
5obj-$(CONFIG_EEPROM_93CX6) += eeprom_93cx6.o 5obj-$(CONFIG_EEPROM_93CX6) += eeprom_93cx6.o
6obj-$(CONFIG_EEPROM_93XX46) += eeprom_93xx46.o
7obj-$(CONFIG_EEPROM_DIGSY_MTC_CFG) += digsy_mtc_eeprom.o
diff --git a/drivers/misc/eeprom/digsy_mtc_eeprom.c b/drivers/misc/eeprom/digsy_mtc_eeprom.c
new file mode 100644
index 000000000000..66d9e1baeae5
--- /dev/null
+++ b/drivers/misc/eeprom/digsy_mtc_eeprom.c
@@ -0,0 +1,85 @@
1/*
2 * EEPROMs access control driver for display configuration EEPROMs
3 * on DigsyMTC board.
4 *
5 * (C) 2011 DENX Software Engineering, Anatolij Gustschin <agust@denx.de>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 */
11
12#include <linux/gpio.h>
13#include <linux/init.h>
14#include <linux/platform_device.h>
15#include <linux/spi/spi.h>
16#include <linux/spi/spi_gpio.h>
17#include <linux/eeprom_93xx46.h>
18
19#define GPIO_EEPROM_CLK 216
20#define GPIO_EEPROM_CS 210
21#define GPIO_EEPROM_DI 217
22#define GPIO_EEPROM_DO 249
23#define GPIO_EEPROM_OE 255
24#define EE_SPI_BUS_NUM 1
25
26static void digsy_mtc_op_prepare(void *p)
27{
28 /* enable */
29 gpio_set_value(GPIO_EEPROM_OE, 0);
30}
31
32static void digsy_mtc_op_finish(void *p)
33{
34 /* disable */
35 gpio_set_value(GPIO_EEPROM_OE, 1);
36}
37
38struct eeprom_93xx46_platform_data digsy_mtc_eeprom_data = {
39 .flags = EE_ADDR8,
40 .prepare = digsy_mtc_op_prepare,
41 .finish = digsy_mtc_op_finish,
42};
43
44static struct spi_gpio_platform_data eeprom_spi_gpio_data = {
45 .sck = GPIO_EEPROM_CLK,
46 .mosi = GPIO_EEPROM_DI,
47 .miso = GPIO_EEPROM_DO,
48 .num_chipselect = 1,
49};
50
51static struct platform_device digsy_mtc_eeprom = {
52 .name = "spi_gpio",
53 .id = EE_SPI_BUS_NUM,
54 .dev = {
55 .platform_data = &eeprom_spi_gpio_data,
56 },
57};
58
59static struct spi_board_info digsy_mtc_eeprom_info[] __initdata = {
60 {
61 .modalias = "93xx46",
62 .max_speed_hz = 1000000,
63 .bus_num = EE_SPI_BUS_NUM,
64 .chip_select = 0,
65 .mode = SPI_MODE_0,
66 .controller_data = (void *)GPIO_EEPROM_CS,
67 .platform_data = &digsy_mtc_eeprom_data,
68 },
69};
70
71static int __init digsy_mtc_eeprom_devices_init(void)
72{
73 int ret;
74
75 ret = gpio_request_one(GPIO_EEPROM_OE, GPIOF_OUT_INIT_HIGH,
76 "93xx46 EEPROMs OE");
77 if (ret) {
78 pr_err("can't request gpio %d\n", GPIO_EEPROM_OE);
79 return ret;
80 }
81 spi_register_board_info(digsy_mtc_eeprom_info,
82 ARRAY_SIZE(digsy_mtc_eeprom_info));
83 return platform_device_register(&digsy_mtc_eeprom);
84}
85device_initcall(digsy_mtc_eeprom_devices_init);
diff --git a/drivers/misc/eeprom/eeprom_93xx46.c b/drivers/misc/eeprom/eeprom_93xx46.c
new file mode 100644
index 000000000000..0c7ebb1e19e5
--- /dev/null
+++ b/drivers/misc/eeprom/eeprom_93xx46.c
@@ -0,0 +1,410 @@
1/*
2 * Driver for 93xx46 EEPROMs
3 *
4 * (C) 2011 DENX Software Engineering, Anatolij Gustschin <agust@denx.de>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10
11#include <linux/delay.h>
12#include <linux/device.h>
13#include <linux/kernel.h>
14#include <linux/init.h>
15#include <linux/module.h>
16#include <linux/mutex.h>
17#include <linux/slab.h>
18#include <linux/spi/spi.h>
19#include <linux/sysfs.h>
20#include <linux/eeprom_93xx46.h>
21
22#define OP_START 0x4
23#define OP_WRITE (OP_START | 0x1)
24#define OP_READ (OP_START | 0x2)
25#define ADDR_EWDS 0x00
26#define ADDR_ERAL 0x20
27#define ADDR_EWEN 0x30
28
29struct eeprom_93xx46_dev {
30 struct spi_device *spi;
31 struct eeprom_93xx46_platform_data *pdata;
32 struct bin_attribute bin;
33 struct mutex lock;
34 int addrlen;
35};
36
37static ssize_t
38eeprom_93xx46_bin_read(struct file *filp, struct kobject *kobj,
39 struct bin_attribute *bin_attr,
40 char *buf, loff_t off, size_t count)
41{
42 struct eeprom_93xx46_dev *edev;
43 struct device *dev;
44 struct spi_message m;
45 struct spi_transfer t[2];
46 int bits, ret;
47 u16 cmd_addr;
48
49 dev = container_of(kobj, struct device, kobj);
50 edev = dev_get_drvdata(dev);
51
52 if (unlikely(off >= edev->bin.size))
53 return 0;
54 if ((off + count) > edev->bin.size)
55 count = edev->bin.size - off;
56 if (unlikely(!count))
57 return count;
58
59 cmd_addr = OP_READ << edev->addrlen;
60
61 if (edev->addrlen == 7) {
62 cmd_addr |= off & 0x7f;
63 bits = 10;
64 } else {
65 cmd_addr |= off & 0x3f;
66 bits = 9;
67 }
68
69 dev_dbg(&edev->spi->dev, "read cmd 0x%x, %d Hz\n",
70 cmd_addr, edev->spi->max_speed_hz);
71
72 spi_message_init(&m);
73 memset(t, 0, sizeof(t));
74
75 t[0].tx_buf = (char *)&cmd_addr;
76 t[0].len = 2;
77 t[0].bits_per_word = bits;
78 spi_message_add_tail(&t[0], &m);
79
80 t[1].rx_buf = buf;
81 t[1].len = count;
82 t[1].bits_per_word = 8;
83 spi_message_add_tail(&t[1], &m);
84
85 mutex_lock(&edev->lock);
86
87 if (edev->pdata->prepare)
88 edev->pdata->prepare(edev);
89
90 ret = spi_sync(edev->spi, &m);
91 /* have to wait at least Tcsl ns */
92 ndelay(250);
93 if (ret) {
94 dev_err(&edev->spi->dev, "read %zu bytes at %d: err. %d\n",
95 count, (int)off, ret);
96 }
97
98 if (edev->pdata->finish)
99 edev->pdata->finish(edev);
100
101 mutex_unlock(&edev->lock);
102 return ret ? : count;
103}
104
105static int eeprom_93xx46_ew(struct eeprom_93xx46_dev *edev, int is_on)
106{
107 struct spi_message m;
108 struct spi_transfer t;
109 int bits, ret;
110 u16 cmd_addr;
111
112 cmd_addr = OP_START << edev->addrlen;
113 if (edev->addrlen == 7) {
114 cmd_addr |= (is_on ? ADDR_EWEN : ADDR_EWDS) << 1;
115 bits = 10;
116 } else {
117 cmd_addr |= (is_on ? ADDR_EWEN : ADDR_EWDS);
118 bits = 9;
119 }
120
121 dev_dbg(&edev->spi->dev, "ew cmd 0x%04x\n", cmd_addr);
122
123 spi_message_init(&m);
124 memset(&t, 0, sizeof(t));
125
126 t.tx_buf = &cmd_addr;
127 t.len = 2;
128 t.bits_per_word = bits;
129 spi_message_add_tail(&t, &m);
130
131 mutex_lock(&edev->lock);
132
133 if (edev->pdata->prepare)
134 edev->pdata->prepare(edev);
135
136 ret = spi_sync(edev->spi, &m);
137 /* have to wait at least Tcsl ns */
138 ndelay(250);
139 if (ret)
140 dev_err(&edev->spi->dev, "erase/write %sable error %d\n",
141 is_on ? "en" : "dis", ret);
142
143 if (edev->pdata->finish)
144 edev->pdata->finish(edev);
145
146 mutex_unlock(&edev->lock);
147 return ret;
148}
149
150static ssize_t
151eeprom_93xx46_write_word(struct eeprom_93xx46_dev *edev,
152 const char *buf, unsigned off)
153{
154 struct spi_message m;
155 struct spi_transfer t[2];
156 int bits, data_len, ret;
157 u16 cmd_addr;
158
159 cmd_addr = OP_WRITE << edev->addrlen;
160
161 if (edev->addrlen == 7) {
162 cmd_addr |= off & 0x7f;
163 bits = 10;
164 data_len = 1;
165 } else {
166 cmd_addr |= off & 0x3f;
167 bits = 9;
168 data_len = 2;
169 }
170
171 dev_dbg(&edev->spi->dev, "write cmd 0x%x\n", cmd_addr);
172
173 spi_message_init(&m);
174 memset(t, 0, sizeof(t));
175
176 t[0].tx_buf = (char *)&cmd_addr;
177 t[0].len = 2;
178 t[0].bits_per_word = bits;
179 spi_message_add_tail(&t[0], &m);
180
181 t[1].tx_buf = buf;
182 t[1].len = data_len;
183 t[1].bits_per_word = 8;
184 spi_message_add_tail(&t[1], &m);
185
186 ret = spi_sync(edev->spi, &m);
187 /* have to wait program cycle time Twc ms */
188 mdelay(6);
189 return ret;
190}
191
192static ssize_t
193eeprom_93xx46_bin_write(struct file *filp, struct kobject *kobj,
194 struct bin_attribute *bin_attr,
195 char *buf, loff_t off, size_t count)
196{
197 struct eeprom_93xx46_dev *edev;
198 struct device *dev;
199 int i, ret, step = 1;
200
201 dev = container_of(kobj, struct device, kobj);
202 edev = dev_get_drvdata(dev);
203
204 if (unlikely(off >= edev->bin.size))
205 return 0;
206 if ((off + count) > edev->bin.size)
207 count = edev->bin.size - off;
208 if (unlikely(!count))
209 return count;
210
211 /* only write even number of bytes on 16-bit devices */
212 if (edev->addrlen == 6) {
213 step = 2;
214 count &= ~1;
215 }
216
217 /* erase/write enable */
218 ret = eeprom_93xx46_ew(edev, 1);
219 if (ret)
220 return ret;
221
222 mutex_lock(&edev->lock);
223
224 if (edev->pdata->prepare)
225 edev->pdata->prepare(edev);
226
227 for (i = 0; i < count; i += step) {
228 ret = eeprom_93xx46_write_word(edev, &buf[i], off + i);
229 if (ret) {
230 dev_err(&edev->spi->dev, "write failed at %d: %d\n",
231 (int)off + i, ret);
232 break;
233 }
234 }
235
236 if (edev->pdata->finish)
237 edev->pdata->finish(edev);
238
239 mutex_unlock(&edev->lock);
240
241 /* erase/write disable */
242 eeprom_93xx46_ew(edev, 0);
243 return ret ? : count;
244}
245
246static int eeprom_93xx46_eral(struct eeprom_93xx46_dev *edev)
247{
248 struct eeprom_93xx46_platform_data *pd = edev->pdata;
249 struct spi_message m;
250 struct spi_transfer t;
251 int bits, ret;
252 u16 cmd_addr;
253
254 cmd_addr = OP_START << edev->addrlen;
255 if (edev->addrlen == 7) {
256 cmd_addr |= ADDR_ERAL << 1;
257 bits = 10;
258 } else {
259 cmd_addr |= ADDR_ERAL;
260 bits = 9;
261 }
262
263 spi_message_init(&m);
264 memset(&t, 0, sizeof(t));
265
266 t.tx_buf = &cmd_addr;
267 t.len = 2;
268 t.bits_per_word = bits;
269 spi_message_add_tail(&t, &m);
270
271 mutex_lock(&edev->lock);
272
273 if (edev->pdata->prepare)
274 edev->pdata->prepare(edev);
275
276 ret = spi_sync(edev->spi, &m);
277 if (ret)
278 dev_err(&edev->spi->dev, "erase error %d\n", ret);
279 /* have to wait erase cycle time Tec ms */
280 mdelay(6);
281
282 if (pd->finish)
283 pd->finish(edev);
284
285 mutex_unlock(&edev->lock);
286 return ret;
287}
288
289static ssize_t eeprom_93xx46_store_erase(struct device *dev,
290 struct device_attribute *attr,
291 const char *buf, size_t count)
292{
293 struct eeprom_93xx46_dev *edev = dev_get_drvdata(dev);
294 int erase = 0, ret;
295
296 sscanf(buf, "%d", &erase);
297 if (erase) {
298 ret = eeprom_93xx46_ew(edev, 1);
299 if (ret)
300 return ret;
301 ret = eeprom_93xx46_eral(edev);
302 if (ret)
303 return ret;
304 ret = eeprom_93xx46_ew(edev, 0);
305 if (ret)
306 return ret;
307 }
308 return count;
309}
310static DEVICE_ATTR(erase, S_IWUSR, NULL, eeprom_93xx46_store_erase);
311
312static int __devinit eeprom_93xx46_probe(struct spi_device *spi)
313{
314 struct eeprom_93xx46_platform_data *pd;
315 struct eeprom_93xx46_dev *edev;
316 int err;
317
318 pd = spi->dev.platform_data;
319 if (!pd) {
320 dev_err(&spi->dev, "missing platform data\n");
321 return -ENODEV;
322 }
323
324 edev = kzalloc(sizeof(*edev), GFP_KERNEL);
325 if (!edev)
326 return -ENOMEM;
327
328 if (pd->flags & EE_ADDR8)
329 edev->addrlen = 7;
330 else if (pd->flags & EE_ADDR16)
331 edev->addrlen = 6;
332 else {
333 dev_err(&spi->dev, "unspecified address type\n");
334 err = -EINVAL;
335 goto fail;
336 }
337
338 mutex_init(&edev->lock);
339
340 edev->spi = spi_dev_get(spi);
341 edev->pdata = pd;
342
343 sysfs_bin_attr_init(&edev->bin);
344 edev->bin.attr.name = "eeprom";
345 edev->bin.attr.mode = S_IRUSR;
346 edev->bin.read = eeprom_93xx46_bin_read;
347 edev->bin.size = 128;
348 if (!(pd->flags & EE_READONLY)) {
349 edev->bin.write = eeprom_93xx46_bin_write;
350 edev->bin.attr.mode |= S_IWUSR;
351 }
352
353 err = sysfs_create_bin_file(&spi->dev.kobj, &edev->bin);
354 if (err)
355 goto fail;
356
357 dev_info(&spi->dev, "%d-bit eeprom %s\n",
358 (pd->flags & EE_ADDR8) ? 8 : 16,
359 (pd->flags & EE_READONLY) ? "(readonly)" : "");
360
361 if (!(pd->flags & EE_READONLY)) {
362 if (device_create_file(&spi->dev, &dev_attr_erase))
363 dev_err(&spi->dev, "can't create erase interface\n");
364 }
365
366 dev_set_drvdata(&spi->dev, edev);
367 return 0;
368fail:
369 kfree(edev);
370 return err;
371}
372
373static int __devexit eeprom_93xx46_remove(struct spi_device *spi)
374{
375 struct eeprom_93xx46_dev *edev = dev_get_drvdata(&spi->dev);
376
377 if (!(edev->pdata->flags & EE_READONLY))
378 device_remove_file(&spi->dev, &dev_attr_erase);
379
380 sysfs_remove_bin_file(&spi->dev.kobj, &edev->bin);
381 dev_set_drvdata(&spi->dev, NULL);
382 kfree(edev);
383 return 0;
384}
385
386static struct spi_driver eeprom_93xx46_driver = {
387 .driver = {
388 .name = "93xx46",
389 .owner = THIS_MODULE,
390 },
391 .probe = eeprom_93xx46_probe,
392 .remove = __devexit_p(eeprom_93xx46_remove),
393};
394
395static int __init eeprom_93xx46_init(void)
396{
397 return spi_register_driver(&eeprom_93xx46_driver);
398}
399module_init(eeprom_93xx46_init);
400
401static void __exit eeprom_93xx46_exit(void)
402{
403 spi_unregister_driver(&eeprom_93xx46_driver);
404}
405module_exit(eeprom_93xx46_exit);
406
407MODULE_LICENSE("GPL");
408MODULE_DESCRIPTION("Driver for 93xx46 EEPROMs");
409MODULE_AUTHOR("Anatolij Gustschin <agust@denx.de>");
410MODULE_ALIAS("spi:93xx46");
diff --git a/drivers/misc/fsa9480.c b/drivers/misc/fsa9480.c
new file mode 100644
index 000000000000..5325a7e70dcf
--- /dev/null
+++ b/drivers/misc/fsa9480.c
@@ -0,0 +1,557 @@
1/*
2 * fsa9480.c - FSA9480 micro USB switch device driver
3 *
4 * Copyright (C) 2010 Samsung Electronics
5 * Minkyu Kang <mk7.kang@samsung.com>
6 * Wonguk Jeong <wonguk.jeong@samsung.com>
7 *
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.
11 */
12
13#include <linux/kernel.h>
14#include <linux/module.h>
15#include <linux/err.h>
16#include <linux/i2c.h>
17#include <linux/platform_data/fsa9480.h>
18#include <linux/irq.h>
19#include <linux/interrupt.h>
20#include <linux/workqueue.h>
21#include <linux/platform_device.h>
22#include <linux/slab.h>
23#include <linux/pm_runtime.h>
24
25/* FSA9480 I2C registers */
26#define FSA9480_REG_DEVID 0x01
27#define FSA9480_REG_CTRL 0x02
28#define FSA9480_REG_INT1 0x03
29#define FSA9480_REG_INT2 0x04
30#define FSA9480_REG_INT1_MASK 0x05
31#define FSA9480_REG_INT2_MASK 0x06
32#define FSA9480_REG_ADC 0x07
33#define FSA9480_REG_TIMING1 0x08
34#define FSA9480_REG_TIMING2 0x09
35#define FSA9480_REG_DEV_T1 0x0a
36#define FSA9480_REG_DEV_T2 0x0b
37#define FSA9480_REG_BTN1 0x0c
38#define FSA9480_REG_BTN2 0x0d
39#define FSA9480_REG_CK 0x0e
40#define FSA9480_REG_CK_INT1 0x0f
41#define FSA9480_REG_CK_INT2 0x10
42#define FSA9480_REG_CK_INTMASK1 0x11
43#define FSA9480_REG_CK_INTMASK2 0x12
44#define FSA9480_REG_MANSW1 0x13
45#define FSA9480_REG_MANSW2 0x14
46
47/* Control */
48#define CON_SWITCH_OPEN (1 << 4)
49#define CON_RAW_DATA (1 << 3)
50#define CON_MANUAL_SW (1 << 2)
51#define CON_WAIT (1 << 1)
52#define CON_INT_MASK (1 << 0)
53#define CON_MASK (CON_SWITCH_OPEN | CON_RAW_DATA | \
54 CON_MANUAL_SW | CON_WAIT)
55
56/* Device Type 1 */
57#define DEV_USB_OTG (1 << 7)
58#define DEV_DEDICATED_CHG (1 << 6)
59#define DEV_USB_CHG (1 << 5)
60#define DEV_CAR_KIT (1 << 4)
61#define DEV_UART (1 << 3)
62#define DEV_USB (1 << 2)
63#define DEV_AUDIO_2 (1 << 1)
64#define DEV_AUDIO_1 (1 << 0)
65
66#define DEV_T1_USB_MASK (DEV_USB_OTG | DEV_USB)
67#define DEV_T1_UART_MASK (DEV_UART)
68#define DEV_T1_CHARGER_MASK (DEV_DEDICATED_CHG | DEV_USB_CHG)
69
70/* Device Type 2 */
71#define DEV_AV (1 << 6)
72#define DEV_TTY (1 << 5)
73#define DEV_PPD (1 << 4)
74#define DEV_JIG_UART_OFF (1 << 3)
75#define DEV_JIG_UART_ON (1 << 2)
76#define DEV_JIG_USB_OFF (1 << 1)
77#define DEV_JIG_USB_ON (1 << 0)
78
79#define DEV_T2_USB_MASK (DEV_JIG_USB_OFF | DEV_JIG_USB_ON)
80#define DEV_T2_UART_MASK (DEV_JIG_UART_OFF | DEV_JIG_UART_ON)
81#define DEV_T2_JIG_MASK (DEV_JIG_USB_OFF | DEV_JIG_USB_ON | \
82 DEV_JIG_UART_OFF | DEV_JIG_UART_ON)
83
84/*
85 * Manual Switch
86 * D- [7:5] / D+ [4:2]
87 * 000: Open all / 001: USB / 010: AUDIO / 011: UART / 100: V_AUDIO
88 */
89#define SW_VAUDIO ((4 << 5) | (4 << 2))
90#define SW_UART ((3 << 5) | (3 << 2))
91#define SW_AUDIO ((2 << 5) | (2 << 2))
92#define SW_DHOST ((1 << 5) | (1 << 2))
93#define SW_AUTO ((0 << 5) | (0 << 2))
94
95/* Interrupt 1 */
96#define INT_DETACH (1 << 1)
97#define INT_ATTACH (1 << 0)
98
99struct fsa9480_usbsw {
100 struct i2c_client *client;
101 struct fsa9480_platform_data *pdata;
102 int dev1;
103 int dev2;
104 int mansw;
105};
106
107static struct fsa9480_usbsw *chip;
108
109static int fsa9480_write_reg(struct i2c_client *client,
110 int reg, int value)
111{
112 int ret;
113
114 ret = i2c_smbus_write_byte_data(client, reg, value);
115
116 if (ret < 0)
117 dev_err(&client->dev, "%s: err %d\n", __func__, ret);
118
119 return ret;
120}
121
122static int fsa9480_read_reg(struct i2c_client *client, int reg)
123{
124 int ret;
125
126 ret = i2c_smbus_read_byte_data(client, reg);
127
128 if (ret < 0)
129 dev_err(&client->dev, "%s: err %d\n", __func__, ret);
130
131 return ret;
132}
133
134static int fsa9480_read_irq(struct i2c_client *client, int *value)
135{
136 int ret;
137
138 ret = i2c_smbus_read_i2c_block_data(client,
139 FSA9480_REG_INT1, 2, (u8 *)value);
140 *value &= 0xffff;
141
142 if (ret < 0)
143 dev_err(&client->dev, "%s: err %d\n", __func__, ret);
144
145 return ret;
146}
147
148static void fsa9480_set_switch(const char *buf)
149{
150 struct fsa9480_usbsw *usbsw = chip;
151 struct i2c_client *client = usbsw->client;
152 unsigned int value;
153 unsigned int path = 0;
154
155 value = fsa9480_read_reg(client, FSA9480_REG_CTRL);
156
157 if (!strncmp(buf, "VAUDIO", 6)) {
158 path = SW_VAUDIO;
159 value &= ~CON_MANUAL_SW;
160 } else if (!strncmp(buf, "UART", 4)) {
161 path = SW_UART;
162 value &= ~CON_MANUAL_SW;
163 } else if (!strncmp(buf, "AUDIO", 5)) {
164 path = SW_AUDIO;
165 value &= ~CON_MANUAL_SW;
166 } else if (!strncmp(buf, "DHOST", 5)) {
167 path = SW_DHOST;
168 value &= ~CON_MANUAL_SW;
169 } else if (!strncmp(buf, "AUTO", 4)) {
170 path = SW_AUTO;
171 value |= CON_MANUAL_SW;
172 } else {
173 printk(KERN_ERR "Wrong command\n");
174 return;
175 }
176
177 usbsw->mansw = path;
178 fsa9480_write_reg(client, FSA9480_REG_MANSW1, path);
179 fsa9480_write_reg(client, FSA9480_REG_CTRL, value);
180}
181
182static ssize_t fsa9480_get_switch(char *buf)
183{
184 struct fsa9480_usbsw *usbsw = chip;
185 struct i2c_client *client = usbsw->client;
186 unsigned int value;
187
188 value = fsa9480_read_reg(client, FSA9480_REG_MANSW1);
189
190 if (value == SW_VAUDIO)
191 return sprintf(buf, "VAUDIO\n");
192 else if (value == SW_UART)
193 return sprintf(buf, "UART\n");
194 else if (value == SW_AUDIO)
195 return sprintf(buf, "AUDIO\n");
196 else if (value == SW_DHOST)
197 return sprintf(buf, "DHOST\n");
198 else if (value == SW_AUTO)
199 return sprintf(buf, "AUTO\n");
200 else
201 return sprintf(buf, "%x", value);
202}
203
204static ssize_t fsa9480_show_device(struct device *dev,
205 struct device_attribute *attr,
206 char *buf)
207{
208 struct fsa9480_usbsw *usbsw = dev_get_drvdata(dev);
209 struct i2c_client *client = usbsw->client;
210 int dev1, dev2;
211
212 dev1 = fsa9480_read_reg(client, FSA9480_REG_DEV_T1);
213 dev2 = fsa9480_read_reg(client, FSA9480_REG_DEV_T2);
214
215 if (!dev1 && !dev2)
216 return sprintf(buf, "NONE\n");
217
218 /* USB */
219 if (dev1 & DEV_T1_USB_MASK || dev2 & DEV_T2_USB_MASK)
220 return sprintf(buf, "USB\n");
221
222 /* UART */
223 if (dev1 & DEV_T1_UART_MASK || dev2 & DEV_T2_UART_MASK)
224 return sprintf(buf, "UART\n");
225
226 /* CHARGER */
227 if (dev1 & DEV_T1_CHARGER_MASK)
228 return sprintf(buf, "CHARGER\n");
229
230 /* JIG */
231 if (dev2 & DEV_T2_JIG_MASK)
232 return sprintf(buf, "JIG\n");
233
234 return sprintf(buf, "UNKNOWN\n");
235}
236
237static ssize_t fsa9480_show_manualsw(struct device *dev,
238 struct device_attribute *attr, char *buf)
239{
240 return fsa9480_get_switch(buf);
241
242}
243
244static ssize_t fsa9480_set_manualsw(struct device *dev,
245 struct device_attribute *attr,
246 const char *buf, size_t count)
247{
248 fsa9480_set_switch(buf);
249
250 return count;
251}
252
253static DEVICE_ATTR(device, S_IRUGO, fsa9480_show_device, NULL);
254static DEVICE_ATTR(switch, S_IRUGO | S_IWUSR,
255 fsa9480_show_manualsw, fsa9480_set_manualsw);
256
257static struct attribute *fsa9480_attributes[] = {
258 &dev_attr_device.attr,
259 &dev_attr_switch.attr,
260 NULL
261};
262
263static const struct attribute_group fsa9480_group = {
264 .attrs = fsa9480_attributes,
265};
266
267static void fsa9480_detect_dev(struct fsa9480_usbsw *usbsw, int intr)
268{
269 int val1, val2, ctrl;
270 struct fsa9480_platform_data *pdata = usbsw->pdata;
271 struct i2c_client *client = usbsw->client;
272
273 val1 = fsa9480_read_reg(client, FSA9480_REG_DEV_T1);
274 val2 = fsa9480_read_reg(client, FSA9480_REG_DEV_T2);
275 ctrl = fsa9480_read_reg(client, FSA9480_REG_CTRL);
276
277 dev_info(&client->dev, "intr: 0x%x, dev1: 0x%x, dev2: 0x%x\n",
278 intr, val1, val2);
279
280 if (!intr)
281 goto out;
282
283 if (intr & INT_ATTACH) { /* Attached */
284 /* USB */
285 if (val1 & DEV_T1_USB_MASK || val2 & DEV_T2_USB_MASK) {
286 if (pdata->usb_cb)
287 pdata->usb_cb(FSA9480_ATTACHED);
288
289 if (usbsw->mansw) {
290 fsa9480_write_reg(client,
291 FSA9480_REG_MANSW1, usbsw->mansw);
292 }
293 }
294
295 /* UART */
296 if (val1 & DEV_T1_UART_MASK || val2 & DEV_T2_UART_MASK) {
297 if (pdata->uart_cb)
298 pdata->uart_cb(FSA9480_ATTACHED);
299
300 if (!(ctrl & CON_MANUAL_SW)) {
301 fsa9480_write_reg(client,
302 FSA9480_REG_MANSW1, SW_UART);
303 }
304 }
305
306 /* CHARGER */
307 if (val1 & DEV_T1_CHARGER_MASK) {
308 if (pdata->charger_cb)
309 pdata->charger_cb(FSA9480_ATTACHED);
310 }
311
312 /* JIG */
313 if (val2 & DEV_T2_JIG_MASK) {
314 if (pdata->jig_cb)
315 pdata->jig_cb(FSA9480_ATTACHED);
316 }
317 } else if (intr & INT_DETACH) { /* Detached */
318 /* USB */
319 if (usbsw->dev1 & DEV_T1_USB_MASK ||
320 usbsw->dev2 & DEV_T2_USB_MASK) {
321 if (pdata->usb_cb)
322 pdata->usb_cb(FSA9480_DETACHED);
323 }
324
325 /* UART */
326 if (usbsw->dev1 & DEV_T1_UART_MASK ||
327 usbsw->dev2 & DEV_T2_UART_MASK) {
328 if (pdata->uart_cb)
329 pdata->uart_cb(FSA9480_DETACHED);
330 }
331
332 /* CHARGER */
333 if (usbsw->dev1 & DEV_T1_CHARGER_MASK) {
334 if (pdata->charger_cb)
335 pdata->charger_cb(FSA9480_DETACHED);
336 }
337
338 /* JIG */
339 if (usbsw->dev2 & DEV_T2_JIG_MASK) {
340 if (pdata->jig_cb)
341 pdata->jig_cb(FSA9480_DETACHED);
342 }
343 }
344
345 usbsw->dev1 = val1;
346 usbsw->dev2 = val2;
347
348out:
349 ctrl &= ~CON_INT_MASK;
350 fsa9480_write_reg(client, FSA9480_REG_CTRL, ctrl);
351}
352
353static irqreturn_t fsa9480_irq_handler(int irq, void *data)
354{
355 struct fsa9480_usbsw *usbsw = data;
356 struct i2c_client *client = usbsw->client;
357 int intr;
358
359 /* clear interrupt */
360 fsa9480_read_irq(client, &intr);
361
362 /* device detection */
363 fsa9480_detect_dev(usbsw, intr);
364
365 return IRQ_HANDLED;
366}
367
368static int fsa9480_irq_init(struct fsa9480_usbsw *usbsw)
369{
370 struct fsa9480_platform_data *pdata = usbsw->pdata;
371 struct i2c_client *client = usbsw->client;
372 int ret;
373 int intr;
374 unsigned int ctrl = CON_MASK;
375
376 /* clear interrupt */
377 fsa9480_read_irq(client, &intr);
378
379 /* unmask interrupt (attach/detach only) */
380 fsa9480_write_reg(client, FSA9480_REG_INT1_MASK, 0xfc);
381 fsa9480_write_reg(client, FSA9480_REG_INT2_MASK, 0x1f);
382
383 usbsw->mansw = fsa9480_read_reg(client, FSA9480_REG_MANSW1);
384
385 if (usbsw->mansw)
386 ctrl &= ~CON_MANUAL_SW; /* Manual Switching Mode */
387
388 fsa9480_write_reg(client, FSA9480_REG_CTRL, ctrl);
389
390 if (pdata && pdata->cfg_gpio)
391 pdata->cfg_gpio();
392
393 if (client->irq) {
394 ret = request_threaded_irq(client->irq, NULL,
395 fsa9480_irq_handler,
396 IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
397 "fsa9480 micro USB", usbsw);
398 if (ret) {
399 dev_err(&client->dev, "failed to reqeust IRQ\n");
400 return ret;
401 }
402
403 device_init_wakeup(&client->dev, pdata->wakeup);
404 }
405
406 return 0;
407}
408
409static int __devinit fsa9480_probe(struct i2c_client *client,
410 const struct i2c_device_id *id)
411{
412 struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
413 struct fsa9480_usbsw *usbsw;
414 int ret = 0;
415
416 if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
417 return -EIO;
418
419 usbsw = kzalloc(sizeof(struct fsa9480_usbsw), GFP_KERNEL);
420 if (!usbsw) {
421 dev_err(&client->dev, "failed to allocate driver data\n");
422 return -ENOMEM;
423 }
424
425 usbsw->client = client;
426 usbsw->pdata = client->dev.platform_data;
427
428 chip = usbsw;
429
430 i2c_set_clientdata(client, usbsw);
431
432 ret = fsa9480_irq_init(usbsw);
433 if (ret)
434 goto fail1;
435
436 ret = sysfs_create_group(&client->dev.kobj, &fsa9480_group);
437 if (ret) {
438 dev_err(&client->dev,
439 "failed to create fsa9480 attribute group\n");
440 goto fail2;
441 }
442
443 /* ADC Detect Time: 500ms */
444 fsa9480_write_reg(client, FSA9480_REG_TIMING1, 0x6);
445
446 if (chip->pdata->reset_cb)
447 chip->pdata->reset_cb();
448
449 /* device detection */
450 fsa9480_detect_dev(usbsw, INT_ATTACH);
451
452 pm_runtime_set_active(&client->dev);
453
454 return 0;
455
456fail2:
457 if (client->irq)
458 free_irq(client->irq, NULL);
459fail1:
460 i2c_set_clientdata(client, NULL);
461 kfree(usbsw);
462 return ret;
463}
464
465static int __devexit fsa9480_remove(struct i2c_client *client)
466{
467 struct fsa9480_usbsw *usbsw = i2c_get_clientdata(client);
468 if (client->irq)
469 free_irq(client->irq, NULL);
470 i2c_set_clientdata(client, NULL);
471
472 sysfs_remove_group(&client->dev.kobj, &fsa9480_group);
473 device_init_wakeup(&client->dev, 0);
474 kfree(usbsw);
475 return 0;
476}
477
478#ifdef CONFIG_PM
479
480static int fsa9480_suspend(struct i2c_client *client, pm_message_t state)
481{
482 struct fsa9480_usbsw *usbsw = i2c_get_clientdata(client);
483 struct fsa9480_platform_data *pdata = usbsw->pdata;
484
485 if (device_may_wakeup(&client->dev) && client->irq)
486 enable_irq_wake(client->irq);
487
488 if (pdata->usb_power)
489 pdata->usb_power(0);
490
491 return 0;
492}
493
494static int fsa9480_resume(struct i2c_client *client)
495{
496 struct fsa9480_usbsw *usbsw = i2c_get_clientdata(client);
497 int dev1, dev2;
498
499 if (device_may_wakeup(&client->dev) && client->irq)
500 disable_irq_wake(client->irq);
501
502 /*
503 * Clear Pending interrupt. Note that detect_dev does what
504 * the interrupt handler does. So, we don't miss pending and
505 * we reenable interrupt if there is one.
506 */
507 fsa9480_read_reg(client, FSA9480_REG_INT1);
508 fsa9480_read_reg(client, FSA9480_REG_INT2);
509
510 dev1 = fsa9480_read_reg(client, FSA9480_REG_DEV_T1);
511 dev2 = fsa9480_read_reg(client, FSA9480_REG_DEV_T2);
512
513 /* device detection */
514 fsa9480_detect_dev(usbsw, (dev1 || dev2) ? INT_ATTACH : INT_DETACH);
515
516 return 0;
517}
518
519#else
520
521#define fsa9480_suspend NULL
522#define fsa9480_resume NULL
523
524#endif /* CONFIG_PM */
525
526static const struct i2c_device_id fsa9480_id[] = {
527 {"fsa9480", 0},
528 {}
529};
530MODULE_DEVICE_TABLE(i2c, fsa9480_id);
531
532static struct i2c_driver fsa9480_i2c_driver = {
533 .driver = {
534 .name = "fsa9480",
535 },
536 .probe = fsa9480_probe,
537 .remove = __devexit_p(fsa9480_remove),
538 .resume = fsa9480_resume,
539 .suspend = fsa9480_suspend,
540 .id_table = fsa9480_id,
541};
542
543static int __init fsa9480_init(void)
544{
545 return i2c_add_driver(&fsa9480_i2c_driver);
546}
547module_init(fsa9480_init);
548
549static void __exit fsa9480_exit(void)
550{
551 i2c_del_driver(&fsa9480_i2c_driver);
552}
553module_exit(fsa9480_exit);
554
555MODULE_AUTHOR("Minkyu Kang <mk7.kang@samsung.com>");
556MODULE_DESCRIPTION("FSA9480 USB Switch driver");
557MODULE_LICENSE("GPL");
diff --git a/drivers/misc/pch_phub.c b/drivers/misc/pch_phub.c
index 5fe79df44838..01eb67b4871a 100644
--- a/drivers/misc/pch_phub.c
+++ b/drivers/misc/pch_phub.c
@@ -686,6 +686,8 @@ static int __devinit pch_phub_probe(struct pci_dev *pdev,
686 } 686 }
687 687
688 if (id->driver_data == 1) { /* EG20T PCH */ 688 if (id->driver_data == 1) { /* EG20T PCH */
689 const char *board_name;
690
689 retval = sysfs_create_file(&pdev->dev.kobj, 691 retval = sysfs_create_file(&pdev->dev.kobj,
690 &dev_attr_pch_mac.attr); 692 &dev_attr_pch_mac.attr);
691 if (retval) 693 if (retval)
@@ -701,7 +703,8 @@ static int __devinit pch_phub_probe(struct pci_dev *pdev,
701 CLKCFG_CANCLK_MASK); 703 CLKCFG_CANCLK_MASK);
702 704
703 /* quirk for CM-iTC board */ 705 /* quirk for CM-iTC board */
704 if (strstr(dmi_get_system_info(DMI_BOARD_NAME), "CM-iTC")) 706 board_name = dmi_get_system_info(DMI_BOARD_NAME);
707 if (board_name && strstr(board_name, "CM-iTC"))
705 pch_phub_read_modify_write_reg(chip, 708 pch_phub_read_modify_write_reg(chip,
706 (unsigned int)CLKCFG_REG_OFFSET, 709 (unsigned int)CLKCFG_REG_OFFSET,
707 CLKCFG_UART_48MHZ | CLKCFG_BAUDDIV | 710 CLKCFG_UART_48MHZ | CLKCFG_BAUDDIV |