aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/misc
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/misc')
-rw-r--r--drivers/misc/Kconfig32
-rw-r--r--drivers/misc/Makefile3
-rw-r--r--drivers/misc/ad525x_dpot-i2c.c134
-rw-r--r--drivers/misc/ad525x_dpot-spi.c172
-rw-r--r--drivers/misc/ad525x_dpot.c1016
-rw-r--r--drivers/misc/ad525x_dpot.h202
-rw-r--r--drivers/misc/c2port/core.c4
-rw-r--r--drivers/misc/ds1682.c6
-rw-r--r--drivers/misc/eeprom/at24.c65
-rw-r--r--drivers/misc/eeprom/at25.c6
-rw-r--r--drivers/misc/eeprom/eeprom.c3
-rw-r--r--drivers/misc/eeprom/max6875.c2
-rw-r--r--drivers/misc/hdpuftrs/Makefile1
-rw-r--r--drivers/misc/hdpuftrs/hdpu_cpustate.c256
-rw-r--r--drivers/misc/hdpuftrs/hdpu_nexus.c149
-rw-r--r--drivers/misc/lkdtm.c20
16 files changed, 1142 insertions, 929 deletions
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 0d0d625fece2..26386a92f5aa 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -14,11 +14,17 @@ menuconfig MISC_DEVICES
14if MISC_DEVICES 14if MISC_DEVICES
15 15
16config AD525X_DPOT 16config AD525X_DPOT
17 tristate "Analog Devices AD525x Digital Potentiometers" 17 tristate "Analog Devices Digital Potentiometers"
18 depends on I2C && SYSFS 18 depends on (I2C || SPI) && SYSFS
19 help 19 help
20 If you say yes here, you get support for the Analog Devices 20 If you say yes here, you get support for the Analog Devices
21 AD5258, AD5259, AD5251, AD5252, AD5253, AD5254 and AD5255 21 AD5258, AD5259, AD5251, AD5252, AD5253, AD5254, AD5255
22 AD5160, AD5161, AD5162, AD5165, AD5200, AD5201, AD5203,
23 AD5204, AD5206, AD5207, AD5231, AD5232, AD5233, AD5235,
24 AD5260, AD5262, AD5263, AD5290, AD5291, AD5292, AD5293,
25 AD7376, AD8400, AD8402, AD8403, ADN2850, AD5241, AD5242,
26 AD5243, AD5245, AD5246, AD5247, AD5248, AD5280, AD5282,
27 ADN2860, AD5273, AD5171, AD5170, AD5172, AD5173
22 digital potentiometer chips. 28 digital potentiometer chips.
23 29
24 See Documentation/misc-devices/ad525x_dpot.txt for the 30 See Documentation/misc-devices/ad525x_dpot.txt for the
@@ -27,6 +33,26 @@ config AD525X_DPOT
27 This driver can also be built as a module. If so, the module 33 This driver can also be built as a module. If so, the module
28 will be called ad525x_dpot. 34 will be called ad525x_dpot.
29 35
36config AD525X_DPOT_I2C
37 tristate "support I2C bus connection"
38 depends on AD525X_DPOT && I2C
39 help
40 Say Y here if you have a digital potentiometers hooked to an I2C bus.
41
42 To compile this driver as a module, choose M here: the
43 module will be called ad525x_dpot-i2c.
44
45config AD525X_DPOT_SPI
46 tristate "support SPI bus connection"
47 depends on AD525X_DPOT && SPI_MASTER
48 help
49 Say Y here if you have a digital potentiometers hooked to an SPI bus.
50
51 If unsure, say N (but it's safe to say "Y").
52
53 To compile this driver as a module, choose M here: the
54 module will be called ad525x_dpot-spi.
55
30config ATMEL_PWM 56config ATMEL_PWM
31 tristate "Atmel AT32/AT91 PWM support" 57 tristate "Atmel AT32/AT91 PWM support"
32 depends on AVR32 || ARCH_AT91SAM9263 || ARCH_AT91SAM9RL || ARCH_AT91CAP9 58 depends on AVR32 || ARCH_AT91SAM9263 || ARCH_AT91SAM9RL || ARCH_AT91CAP9
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index 7b6f7eefdf8d..6ed06a19474a 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -3,8 +3,9 @@
3# 3#
4 4
5obj-$(CONFIG_IBM_ASM) += ibmasm/ 5obj-$(CONFIG_IBM_ASM) += ibmasm/
6obj-$(CONFIG_HDPU_FEATURES) += hdpuftrs/
7obj-$(CONFIG_AD525X_DPOT) += ad525x_dpot.o 6obj-$(CONFIG_AD525X_DPOT) += ad525x_dpot.o
7obj-$(CONFIG_AD525X_DPOT_I2C) += ad525x_dpot-i2c.o
8obj-$(CONFIG_AD525X_DPOT_SPI) += ad525x_dpot-spi.o
8obj-$(CONFIG_ATMEL_PWM) += atmel_pwm.o 9obj-$(CONFIG_ATMEL_PWM) += atmel_pwm.o
9obj-$(CONFIG_ATMEL_SSC) += atmel-ssc.o 10obj-$(CONFIG_ATMEL_SSC) += atmel-ssc.o
10obj-$(CONFIG_ATMEL_TCLIB) += atmel_tclib.o 11obj-$(CONFIG_ATMEL_TCLIB) += atmel_tclib.o
diff --git a/drivers/misc/ad525x_dpot-i2c.c b/drivers/misc/ad525x_dpot-i2c.c
new file mode 100644
index 000000000000..374352af7979
--- /dev/null
+++ b/drivers/misc/ad525x_dpot-i2c.c
@@ -0,0 +1,134 @@
1/*
2 * Driver for the Analog Devices digital potentiometers (I2C bus)
3 *
4 * Copyright (C) 2010 Michael Hennerich, Analog Devices Inc.
5 *
6 * Licensed under the GPL-2 or later.
7 */
8
9#include <linux/i2c.h>
10#include <linux/module.h>
11
12#include "ad525x_dpot.h"
13
14/* ------------------------------------------------------------------------- */
15/* I2C bus functions */
16static int write_d8(void *client, u8 val)
17{
18 return i2c_smbus_write_byte(client, val);
19}
20
21static int write_r8d8(void *client, u8 reg, u8 val)
22{
23 return i2c_smbus_write_byte_data(client, reg, val);
24}
25
26static int write_r8d16(void *client, u8 reg, u16 val)
27{
28 return i2c_smbus_write_word_data(client, reg, val);
29}
30
31static int read_d8(void *client)
32{
33 return i2c_smbus_read_byte(client);
34}
35
36static int read_r8d8(void *client, u8 reg)
37{
38 return i2c_smbus_read_byte_data(client, reg);
39}
40
41static int read_r8d16(void *client, u8 reg)
42{
43 return i2c_smbus_read_word_data(client, reg);
44}
45
46static const struct ad_dpot_bus_ops bops = {
47 .read_d8 = read_d8,
48 .read_r8d8 = read_r8d8,
49 .read_r8d16 = read_r8d16,
50 .write_d8 = write_d8,
51 .write_r8d8 = write_r8d8,
52 .write_r8d16 = write_r8d16,
53};
54
55static int __devinit ad_dpot_i2c_probe(struct i2c_client *client,
56 const struct i2c_device_id *id)
57{
58 struct ad_dpot_bus_data bdata = {
59 .client = client,
60 .bops = &bops,
61 };
62
63 struct ad_dpot_id dpot_id = {
64 .name = (char *) &id->name,
65 .devid = id->driver_data,
66 };
67
68 if (!i2c_check_functionality(client->adapter,
69 I2C_FUNC_SMBUS_WORD_DATA)) {
70 dev_err(&client->dev, "SMBUS Word Data not Supported\n");
71 return -EIO;
72 }
73
74 return ad_dpot_probe(&client->dev, &bdata, &dpot_id);
75}
76
77static int __devexit ad_dpot_i2c_remove(struct i2c_client *client)
78{
79 return ad_dpot_remove(&client->dev);
80}
81
82static const struct i2c_device_id ad_dpot_id[] = {
83 {"ad5258", AD5258_ID},
84 {"ad5259", AD5259_ID},
85 {"ad5251", AD5251_ID},
86 {"ad5252", AD5252_ID},
87 {"ad5253", AD5253_ID},
88 {"ad5254", AD5254_ID},
89 {"ad5255", AD5255_ID},
90 {"ad5241", AD5241_ID},
91 {"ad5242", AD5242_ID},
92 {"ad5243", AD5243_ID},
93 {"ad5245", AD5245_ID},
94 {"ad5246", AD5246_ID},
95 {"ad5247", AD5247_ID},
96 {"ad5248", AD5248_ID},
97 {"ad5280", AD5280_ID},
98 {"ad5282", AD5282_ID},
99 {"adn2860", ADN2860_ID},
100 {"ad5273", AD5273_ID},
101 {"ad5171", AD5171_ID},
102 {"ad5170", AD5170_ID},
103 {"ad5172", AD5172_ID},
104 {"ad5173", AD5173_ID},
105 {}
106};
107MODULE_DEVICE_TABLE(i2c, ad_dpot_id);
108
109static struct i2c_driver ad_dpot_i2c_driver = {
110 .driver = {
111 .name = "ad_dpot",
112 .owner = THIS_MODULE,
113 },
114 .probe = ad_dpot_i2c_probe,
115 .remove = __devexit_p(ad_dpot_i2c_remove),
116 .id_table = ad_dpot_id,
117};
118
119static int __init ad_dpot_i2c_init(void)
120{
121 return i2c_add_driver(&ad_dpot_i2c_driver);
122}
123module_init(ad_dpot_i2c_init);
124
125static void __exit ad_dpot_i2c_exit(void)
126{
127 i2c_del_driver(&ad_dpot_i2c_driver);
128}
129module_exit(ad_dpot_i2c_exit);
130
131MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
132MODULE_DESCRIPTION("digital potentiometer I2C bus driver");
133MODULE_LICENSE("GPL");
134MODULE_ALIAS("i2c:ad_dpot");
diff --git a/drivers/misc/ad525x_dpot-spi.c b/drivers/misc/ad525x_dpot-spi.c
new file mode 100644
index 000000000000..b8c6df9c8437
--- /dev/null
+++ b/drivers/misc/ad525x_dpot-spi.c
@@ -0,0 +1,172 @@
1/*
2 * Driver for the Analog Devices digital potentiometers (SPI bus)
3 *
4 * Copyright (C) 2010 Michael Hennerich, Analog Devices Inc.
5 *
6 * Licensed under the GPL-2 or later.
7 */
8
9#include <linux/spi/spi.h>
10#include <linux/module.h>
11
12#include "ad525x_dpot.h"
13
14static const struct ad_dpot_id ad_dpot_spi_devlist[] = {
15 {.name = "ad5160", .devid = AD5160_ID},
16 {.name = "ad5161", .devid = AD5161_ID},
17 {.name = "ad5162", .devid = AD5162_ID},
18 {.name = "ad5165", .devid = AD5165_ID},
19 {.name = "ad5200", .devid = AD5200_ID},
20 {.name = "ad5201", .devid = AD5201_ID},
21 {.name = "ad5203", .devid = AD5203_ID},
22 {.name = "ad5204", .devid = AD5204_ID},
23 {.name = "ad5206", .devid = AD5206_ID},
24 {.name = "ad5207", .devid = AD5207_ID},
25 {.name = "ad5231", .devid = AD5231_ID},
26 {.name = "ad5232", .devid = AD5232_ID},
27 {.name = "ad5233", .devid = AD5233_ID},
28 {.name = "ad5235", .devid = AD5235_ID},
29 {.name = "ad5260", .devid = AD5260_ID},
30 {.name = "ad5262", .devid = AD5262_ID},
31 {.name = "ad5263", .devid = AD5263_ID},
32 {.name = "ad5290", .devid = AD5290_ID},
33 {.name = "ad5291", .devid = AD5291_ID},
34 {.name = "ad5292", .devid = AD5292_ID},
35 {.name = "ad5293", .devid = AD5293_ID},
36 {.name = "ad7376", .devid = AD7376_ID},
37 {.name = "ad8400", .devid = AD8400_ID},
38 {.name = "ad8402", .devid = AD8402_ID},
39 {.name = "ad8403", .devid = AD8403_ID},
40 {.name = "adn2850", .devid = ADN2850_ID},
41 {}
42};
43
44/* ------------------------------------------------------------------------- */
45
46/* SPI bus functions */
47static int write8(void *client, u8 val)
48{
49 u8 data = val;
50 return spi_write(client, &data, 1);
51}
52
53static int write16(void *client, u8 reg, u8 val)
54{
55 u8 data[2] = {reg, val};
56 return spi_write(client, data, 1);
57}
58
59static int write24(void *client, u8 reg, u16 val)
60{
61 u8 data[3] = {reg, val >> 8, val};
62 return spi_write(client, data, 1);
63}
64
65static int read8(void *client)
66{
67 int ret;
68 u8 data;
69 ret = spi_read(client, &data, 1);
70 if (ret < 0)
71 return ret;
72
73 return data;
74}
75
76static int read16(void *client, u8 reg)
77{
78 int ret;
79 u8 buf_rx[2];
80
81 write16(client, reg, 0);
82 ret = spi_read(client, buf_rx, 2);
83 if (ret < 0)
84 return ret;
85
86 return (buf_rx[0] << 8) | buf_rx[1];
87}
88
89static int read24(void *client, u8 reg)
90{
91 int ret;
92 u8 buf_rx[3];
93
94 write24(client, reg, 0);
95 ret = spi_read(client, buf_rx, 3);
96 if (ret < 0)
97 return ret;
98
99 return (buf_rx[1] << 8) | buf_rx[2];
100}
101
102static const struct ad_dpot_bus_ops bops = {
103 .read_d8 = read8,
104 .read_r8d8 = read16,
105 .read_r8d16 = read24,
106 .write_d8 = write8,
107 .write_r8d8 = write16,
108 .write_r8d16 = write24,
109};
110
111static const struct ad_dpot_id *dpot_match_id(const struct ad_dpot_id *id,
112 char *name)
113{
114 while (id->name && id->name[0]) {
115 if (strcmp(name, id->name) == 0)
116 return id;
117 id++;
118 }
119 return NULL;
120}
121
122static int __devinit ad_dpot_spi_probe(struct spi_device *spi)
123{
124 char *name = spi->dev.platform_data;
125 const struct ad_dpot_id *dpot_id;
126
127 struct ad_dpot_bus_data bdata = {
128 .client = spi,
129 .bops = &bops,
130 };
131
132 dpot_id = dpot_match_id(ad_dpot_spi_devlist, name);
133
134 if (dpot_id == NULL) {
135 dev_err(&spi->dev, "%s not in supported device list", name);
136 return -ENODEV;
137 }
138
139 return ad_dpot_probe(&spi->dev, &bdata, dpot_id);
140}
141
142static int __devexit ad_dpot_spi_remove(struct spi_device *spi)
143{
144 return ad_dpot_remove(&spi->dev);
145}
146
147static struct spi_driver ad_dpot_spi_driver = {
148 .driver = {
149 .name = "ad_dpot",
150 .bus = &spi_bus_type,
151 .owner = THIS_MODULE,
152 },
153 .probe = ad_dpot_spi_probe,
154 .remove = __devexit_p(ad_dpot_spi_remove),
155};
156
157static int __init ad_dpot_spi_init(void)
158{
159 return spi_register_driver(&ad_dpot_spi_driver);
160}
161module_init(ad_dpot_spi_init);
162
163static void __exit ad_dpot_spi_exit(void)
164{
165 spi_unregister_driver(&ad_dpot_spi_driver);
166}
167module_exit(ad_dpot_spi_exit);
168
169MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
170MODULE_DESCRIPTION("digital potentiometer SPI bus driver");
171MODULE_LICENSE("GPL");
172MODULE_ALIAS("spi:ad_dpot");
diff --git a/drivers/misc/ad525x_dpot.c b/drivers/misc/ad525x_dpot.c
index 30a59f2bacd2..5e6fa8449e8b 100644
--- a/drivers/misc/ad525x_dpot.c
+++ b/drivers/misc/ad525x_dpot.c
@@ -1,6 +1,6 @@
1/* 1/*
2 * ad525x_dpot: Driver for the Analog Devices AD525x digital potentiometers 2 * ad525x_dpot: Driver for the Analog Devices digital potentiometers
3 * Copyright (c) 2009 Analog Devices, Inc. 3 * Copyright (c) 2009-2010 Analog Devices, Inc.
4 * Author: Michael Hennerich <hennerich@blackfin.uclinux.org> 4 * Author: Michael Hennerich <hennerich@blackfin.uclinux.org>
5 * 5 *
6 * DEVID #Wipers #Positions Resistor Options (kOhm) 6 * DEVID #Wipers #Positions Resistor Options (kOhm)
@@ -11,6 +11,47 @@
11 * AD5255 3 512 25, 250 11 * AD5255 3 512 25, 250
12 * AD5253 4 64 1, 10, 50, 100 12 * AD5253 4 64 1, 10, 50, 100
13 * AD5254 4 256 1, 10, 50, 100 13 * AD5254 4 256 1, 10, 50, 100
14 * AD5160 1 256 5, 10, 50, 100
15 * AD5161 1 256 5, 10, 50, 100
16 * AD5162 2 256 2.5, 10, 50, 100
17 * AD5165 1 256 100
18 * AD5200 1 256 10, 50
19 * AD5201 1 33 10, 50
20 * AD5203 4 64 10, 100
21 * AD5204 4 256 10, 50, 100
22 * AD5206 6 256 10, 50, 100
23 * AD5207 2 256 10, 50, 100
24 * AD5231 1 1024 10, 50, 100
25 * AD5232 2 256 10, 50, 100
26 * AD5233 4 64 10, 50, 100
27 * AD5235 2 1024 25, 250
28 * AD5260 1 256 20, 50, 200
29 * AD5262 2 256 20, 50, 200
30 * AD5263 4 256 20, 50, 200
31 * AD5290 1 256 10, 50, 100
32 * AD5291 1 256 20
33 * AD5292 1 1024 20
34 * AD5293 1 1024 20
35 * AD7376 1 128 10, 50, 100, 1M
36 * AD8400 1 256 1, 10, 50, 100
37 * AD8402 2 256 1, 10, 50, 100
38 * AD8403 4 256 1, 10, 50, 100
39 * ADN2850 3 512 25, 250
40 * AD5241 1 256 10, 100, 1M
41 * AD5246 1 128 5, 10, 50, 100
42 * AD5247 1 128 5, 10, 50, 100
43 * AD5245 1 256 5, 10, 50, 100
44 * AD5243 2 256 2.5, 10, 50, 100
45 * AD5248 2 256 2.5, 10, 50, 100
46 * AD5242 2 256 20, 50, 200
47 * AD5280 1 256 20, 50, 200
48 * AD5282 2 256 20, 50, 200
49 * ADN2860 3 512 25, 250
50 * AD5273 1 64 1, 10, 50, 100 (OTP)
51 * AD5171 1 64 5, 10, 50, 100 (OTP)
52 * AD5170 1 256 2.5, 10, 50, 100 (OTP)
53 * AD5172 2 256 2.5, 10, 50, 100 (OTP)
54 * AD5173 2 256 2.5, 10, 50, 100 (OTP)
14 * 55 *
15 * See Documentation/misc-devices/ad525x_dpot.txt for more info. 56 * See Documentation/misc-devices/ad525x_dpot.txt for more info.
16 * 57 *
@@ -28,77 +69,283 @@
28#include <linux/device.h> 69#include <linux/device.h>
29#include <linux/kernel.h> 70#include <linux/kernel.h>
30#include <linux/init.h> 71#include <linux/init.h>
31#include <linux/slab.h>
32#include <linux/i2c.h>
33#include <linux/delay.h> 72#include <linux/delay.h>
73#include <linux/slab.h>
34 74
35#define DRIVER_NAME "ad525x_dpot" 75#define DRIVER_VERSION "0.2"
36#define DRIVER_VERSION "0.1"
37
38enum dpot_devid {
39 AD5258_ID,
40 AD5259_ID,
41 AD5251_ID,
42 AD5252_ID,
43 AD5253_ID,
44 AD5254_ID,
45 AD5255_ID,
46};
47 76
48#define AD5258_MAX_POSITION 64 77#include "ad525x_dpot.h"
49#define AD5259_MAX_POSITION 256
50#define AD5251_MAX_POSITION 64
51#define AD5252_MAX_POSITION 256
52#define AD5253_MAX_POSITION 64
53#define AD5254_MAX_POSITION 256
54#define AD5255_MAX_POSITION 512
55
56#define AD525X_RDAC0 0
57#define AD525X_RDAC1 1
58#define AD525X_RDAC2 2
59#define AD525X_RDAC3 3
60
61#define AD525X_REG_TOL 0x18
62#define AD525X_TOL_RDAC0 (AD525X_REG_TOL | AD525X_RDAC0)
63#define AD525X_TOL_RDAC1 (AD525X_REG_TOL | AD525X_RDAC1)
64#define AD525X_TOL_RDAC2 (AD525X_REG_TOL | AD525X_RDAC2)
65#define AD525X_TOL_RDAC3 (AD525X_REG_TOL | AD525X_RDAC3)
66
67/* RDAC-to-EEPROM Interface Commands */
68#define AD525X_I2C_RDAC (0x00 << 5)
69#define AD525X_I2C_EEPROM (0x01 << 5)
70#define AD525X_I2C_CMD (0x80)
71
72#define AD525X_DEC_ALL_6DB (AD525X_I2C_CMD | (0x4 << 3))
73#define AD525X_INC_ALL_6DB (AD525X_I2C_CMD | (0x9 << 3))
74#define AD525X_DEC_ALL (AD525X_I2C_CMD | (0x6 << 3))
75#define AD525X_INC_ALL (AD525X_I2C_CMD | (0xB << 3))
76
77static s32 ad525x_read(struct i2c_client *client, u8 reg);
78static s32 ad525x_write(struct i2c_client *client, u8 reg, u8 value);
79 78
80/* 79/*
81 * Client data (each client gets its own) 80 * Client data (each client gets its own)
82 */ 81 */
83 82
84struct dpot_data { 83struct dpot_data {
84 struct ad_dpot_bus_data bdata;
85 struct mutex update_lock; 85 struct mutex update_lock;
86 unsigned rdac_mask; 86 unsigned rdac_mask;
87 unsigned max_pos; 87 unsigned max_pos;
88 unsigned devid; 88 unsigned long devid;
89 unsigned uid;
90 unsigned feat;
91 unsigned wipers;
92 u16 rdac_cache[MAX_RDACS];
93 DECLARE_BITMAP(otp_en_mask, MAX_RDACS);
89}; 94};
90 95
96static inline int dpot_read_d8(struct dpot_data *dpot)
97{
98 return dpot->bdata.bops->read_d8(dpot->bdata.client);
99}
100
101static inline int dpot_read_r8d8(struct dpot_data *dpot, u8 reg)
102{
103 return dpot->bdata.bops->read_r8d8(dpot->bdata.client, reg);
104}
105
106static inline int dpot_read_r8d16(struct dpot_data *dpot, u8 reg)
107{
108 return dpot->bdata.bops->read_r8d16(dpot->bdata.client, reg);
109}
110
111static inline int dpot_write_d8(struct dpot_data *dpot, u8 val)
112{
113 return dpot->bdata.bops->write_d8(dpot->bdata.client, val);
114}
115
116static inline int dpot_write_r8d8(struct dpot_data *dpot, u8 reg, u16 val)
117{
118 return dpot->bdata.bops->write_r8d8(dpot->bdata.client, reg, val);
119}
120
121static inline int dpot_write_r8d16(struct dpot_data *dpot, u8 reg, u16 val)
122{
123 return dpot->bdata.bops->write_r8d16(dpot->bdata.client, reg, val);
124}
125
126static s32 dpot_read_spi(struct dpot_data *dpot, u8 reg)
127{
128 unsigned ctrl = 0;
129
130 if (!(reg & (DPOT_ADDR_EEPROM | DPOT_ADDR_CMD))) {
131
132 if (dpot->feat & F_RDACS_WONLY)
133 return dpot->rdac_cache[reg & DPOT_RDAC_MASK];
134
135 if (dpot->uid == DPOT_UID(AD5291_ID) ||
136 dpot->uid == DPOT_UID(AD5292_ID) ||
137 dpot->uid == DPOT_UID(AD5293_ID))
138 return dpot_read_r8d8(dpot,
139 DPOT_AD5291_READ_RDAC << 2);
140
141 ctrl = DPOT_SPI_READ_RDAC;
142 } else if (reg & DPOT_ADDR_EEPROM) {
143 ctrl = DPOT_SPI_READ_EEPROM;
144 }
145
146 if (dpot->feat & F_SPI_16BIT)
147 return dpot_read_r8d8(dpot, ctrl);
148 else if (dpot->feat & F_SPI_24BIT)
149 return dpot_read_r8d16(dpot, ctrl);
150
151 return -EFAULT;
152}
153
154static s32 dpot_read_i2c(struct dpot_data *dpot, u8 reg)
155{
156 unsigned ctrl = 0;
157 switch (dpot->uid) {
158 case DPOT_UID(AD5246_ID):
159 case DPOT_UID(AD5247_ID):
160 return dpot_read_d8(dpot);
161 case DPOT_UID(AD5245_ID):
162 case DPOT_UID(AD5241_ID):
163 case DPOT_UID(AD5242_ID):
164 case DPOT_UID(AD5243_ID):
165 case DPOT_UID(AD5248_ID):
166 case DPOT_UID(AD5280_ID):
167 case DPOT_UID(AD5282_ID):
168 ctrl = ((reg & DPOT_RDAC_MASK) == DPOT_RDAC0) ?
169 0 : DPOT_AD5291_RDAC_AB;
170 return dpot_read_r8d8(dpot, ctrl);
171 case DPOT_UID(AD5170_ID):
172 case DPOT_UID(AD5171_ID):
173 case DPOT_UID(AD5273_ID):
174 return dpot_read_d8(dpot);
175 case DPOT_UID(AD5172_ID):
176 case DPOT_UID(AD5173_ID):
177 ctrl = ((reg & DPOT_RDAC_MASK) == DPOT_RDAC0) ?
178 0 : DPOT_AD5272_3_A0;
179 return dpot_read_r8d8(dpot, ctrl);
180 default:
181 if ((reg & DPOT_REG_TOL) || (dpot->max_pos > 256))
182 return dpot_read_r8d16(dpot, (reg & 0xF8) |
183 ((reg & 0x7) << 1));
184 else
185 return dpot_read_r8d8(dpot, reg);
186 }
187}
188
189static s32 dpot_read(struct dpot_data *dpot, u8 reg)
190{
191 if (dpot->feat & F_SPI)
192 return dpot_read_spi(dpot, reg);
193 else
194 return dpot_read_i2c(dpot, reg);
195}
196
197static s32 dpot_write_spi(struct dpot_data *dpot, u8 reg, u16 value)
198{
199 unsigned val = 0;
200
201 if (!(reg & (DPOT_ADDR_EEPROM | DPOT_ADDR_CMD))) {
202 if (dpot->feat & F_RDACS_WONLY)
203 dpot->rdac_cache[reg & DPOT_RDAC_MASK] = value;
204
205 if (dpot->feat & F_AD_APPDATA) {
206 if (dpot->feat & F_SPI_8BIT) {
207 val = ((reg & DPOT_RDAC_MASK) <<
208 DPOT_MAX_POS(dpot->devid)) |
209 value;
210 return dpot_write_d8(dpot, val);
211 } else if (dpot->feat & F_SPI_16BIT) {
212 val = ((reg & DPOT_RDAC_MASK) <<
213 DPOT_MAX_POS(dpot->devid)) |
214 value;
215 return dpot_write_r8d8(dpot, val >> 8,
216 val & 0xFF);
217 } else
218 BUG();
219 } else {
220 if (dpot->uid == DPOT_UID(AD5291_ID) ||
221 dpot->uid == DPOT_UID(AD5292_ID) ||
222 dpot->uid == DPOT_UID(AD5293_ID))
223 return dpot_write_r8d8(dpot,
224 (DPOT_AD5291_RDAC << 2) |
225 (value >> 8), value & 0xFF);
226
227 val = DPOT_SPI_RDAC | (reg & DPOT_RDAC_MASK);
228 }
229 } else if (reg & DPOT_ADDR_EEPROM) {
230 val = DPOT_SPI_EEPROM | (reg & DPOT_RDAC_MASK);
231 } else if (reg & DPOT_ADDR_CMD) {
232 switch (reg) {
233 case DPOT_DEC_ALL_6DB:
234 val = DPOT_SPI_DEC_ALL_6DB;
235 break;
236 case DPOT_INC_ALL_6DB:
237 val = DPOT_SPI_INC_ALL_6DB;
238 break;
239 case DPOT_DEC_ALL:
240 val = DPOT_SPI_DEC_ALL;
241 break;
242 case DPOT_INC_ALL:
243 val = DPOT_SPI_INC_ALL;
244 break;
245 }
246 } else
247 BUG();
248
249 if (dpot->feat & F_SPI_16BIT)
250 return dpot_write_r8d8(dpot, val, value);
251 else if (dpot->feat & F_SPI_24BIT)
252 return dpot_write_r8d16(dpot, val, value);
253
254 return -EFAULT;
255}
256
257static s32 dpot_write_i2c(struct dpot_data *dpot, u8 reg, u16 value)
258{
259 /* Only write the instruction byte for certain commands */
260 unsigned tmp = 0, ctrl = 0;
261
262 switch (dpot->uid) {
263 case DPOT_UID(AD5246_ID):
264 case DPOT_UID(AD5247_ID):
265 return dpot_write_d8(dpot, value);
266 break;
267
268 case DPOT_UID(AD5245_ID):
269 case DPOT_UID(AD5241_ID):
270 case DPOT_UID(AD5242_ID):
271 case DPOT_UID(AD5243_ID):
272 case DPOT_UID(AD5248_ID):
273 case DPOT_UID(AD5280_ID):
274 case DPOT_UID(AD5282_ID):
275 ctrl = ((reg & DPOT_RDAC_MASK) == DPOT_RDAC0) ?
276 0 : DPOT_AD5291_RDAC_AB;
277 return dpot_write_r8d8(dpot, ctrl, value);
278 break;
279 case DPOT_UID(AD5171_ID):
280 case DPOT_UID(AD5273_ID):
281 if (reg & DPOT_ADDR_OTP) {
282 tmp = dpot_read_d8(dpot);
283 if (tmp >> 6) /* Ready to Program? */
284 return -EFAULT;
285 ctrl = DPOT_AD5273_FUSE;
286 }
287 return dpot_write_r8d8(dpot, ctrl, value);
288 break;
289 case DPOT_UID(AD5172_ID):
290 case DPOT_UID(AD5173_ID):
291 ctrl = ((reg & DPOT_RDAC_MASK) == DPOT_RDAC0) ?
292 0 : DPOT_AD5272_3_A0;
293 if (reg & DPOT_ADDR_OTP) {
294 tmp = dpot_read_r8d16(dpot, ctrl);
295 if (tmp >> 14) /* Ready to Program? */
296 return -EFAULT;
297 ctrl |= DPOT_AD5270_2_3_FUSE;
298 }
299 return dpot_write_r8d8(dpot, ctrl, value);
300 break;
301 case DPOT_UID(AD5170_ID):
302 if (reg & DPOT_ADDR_OTP) {
303 tmp = dpot_read_r8d16(dpot, tmp);
304 if (tmp >> 14) /* Ready to Program? */
305 return -EFAULT;
306 ctrl = DPOT_AD5270_2_3_FUSE;
307 }
308 return dpot_write_r8d8(dpot, ctrl, value);
309 break;
310 default:
311 if (reg & DPOT_ADDR_CMD)
312 return dpot_write_d8(dpot, reg);
313
314 if (dpot->max_pos > 256)
315 return dpot_write_r8d16(dpot, (reg & 0xF8) |
316 ((reg & 0x7) << 1), value);
317 else
318 /* All other registers require instruction + data bytes */
319 return dpot_write_r8d8(dpot, reg, value);
320 }
321}
322
323
324static s32 dpot_write(struct dpot_data *dpot, u8 reg, u16 value)
325{
326 if (dpot->feat & F_SPI)
327 return dpot_write_spi(dpot, reg, value);
328 else
329 return dpot_write_i2c(dpot, reg, value);
330}
331
91/* sysfs functions */ 332/* sysfs functions */
92 333
93static ssize_t sysfs_show_reg(struct device *dev, 334static ssize_t sysfs_show_reg(struct device *dev,
94 struct device_attribute *attr, char *buf, u32 reg) 335 struct device_attribute *attr,
336 char *buf, u32 reg)
95{ 337{
96 struct i2c_client *client = to_i2c_client(dev); 338 struct dpot_data *data = dev_get_drvdata(dev);
97 struct dpot_data *data = i2c_get_clientdata(client);
98 s32 value; 339 s32 value;
99 340
341 if (reg & DPOT_ADDR_OTP_EN)
342 return sprintf(buf, "%s\n",
343 test_bit(DPOT_RDAC_MASK & reg, data->otp_en_mask) ?
344 "enabled" : "disabled");
345
346
100 mutex_lock(&data->update_lock); 347 mutex_lock(&data->update_lock);
101 value = ad525x_read(client, reg); 348 value = dpot_read(data, reg);
102 mutex_unlock(&data->update_lock); 349 mutex_unlock(&data->update_lock);
103 350
104 if (value < 0) 351 if (value < 0)
@@ -111,7 +358,7 @@ static ssize_t sysfs_show_reg(struct device *dev,
111 * datasheet (Rev. A) for more details. 358 * datasheet (Rev. A) for more details.
112 */ 359 */
113 360
114 if (reg & AD525X_REG_TOL) 361 if (reg & DPOT_REG_TOL)
115 return sprintf(buf, "0x%04x\n", value & 0xFFFF); 362 return sprintf(buf, "0x%04x\n", value & 0xFFFF);
116 else 363 else
117 return sprintf(buf, "%u\n", value & data->rdac_mask); 364 return sprintf(buf, "%u\n", value & data->rdac_mask);
@@ -121,11 +368,23 @@ static ssize_t sysfs_set_reg(struct device *dev,
121 struct device_attribute *attr, 368 struct device_attribute *attr,
122 const char *buf, size_t count, u32 reg) 369 const char *buf, size_t count, u32 reg)
123{ 370{
124 struct i2c_client *client = to_i2c_client(dev); 371 struct dpot_data *data = dev_get_drvdata(dev);
125 struct dpot_data *data = i2c_get_clientdata(client);
126 unsigned long value; 372 unsigned long value;
127 int err; 373 int err;
128 374
375 if (reg & DPOT_ADDR_OTP_EN) {
376 if (!strncmp(buf, "enabled", sizeof("enabled")))
377 set_bit(DPOT_RDAC_MASK & reg, data->otp_en_mask);
378 else
379 clear_bit(DPOT_RDAC_MASK & reg, data->otp_en_mask);
380
381 return count;
382 }
383
384 if ((reg & DPOT_ADDR_OTP) &&
385 !test_bit(DPOT_RDAC_MASK & reg, data->otp_en_mask))
386 return -EPERM;
387
129 err = strict_strtoul(buf, 10, &value); 388 err = strict_strtoul(buf, 10, &value);
130 if (err) 389 if (err)
131 return err; 390 return err;
@@ -134,9 +393,11 @@ static ssize_t sysfs_set_reg(struct device *dev,
134 value = data->rdac_mask; 393 value = data->rdac_mask;
135 394
136 mutex_lock(&data->update_lock); 395 mutex_lock(&data->update_lock);
137 ad525x_write(client, reg, value); 396 dpot_write(data, reg, value);
138 if (reg & AD525X_I2C_EEPROM) 397 if (reg & DPOT_ADDR_EEPROM)
139 msleep(26); /* Sleep while the EEPROM updates */ 398 msleep(26); /* Sleep while the EEPROM updates */
399 else if (reg & DPOT_ADDR_OTP)
400 msleep(400); /* Sleep while the OTP updates */
140 mutex_unlock(&data->update_lock); 401 mutex_unlock(&data->update_lock);
141 402
142 return count; 403 return count;
@@ -146,11 +407,10 @@ static ssize_t sysfs_do_cmd(struct device *dev,
146 struct device_attribute *attr, 407 struct device_attribute *attr,
147 const char *buf, size_t count, u32 reg) 408 const char *buf, size_t count, u32 reg)
148{ 409{
149 struct i2c_client *client = to_i2c_client(dev); 410 struct dpot_data *data = dev_get_drvdata(dev);
150 struct dpot_data *data = i2c_get_clientdata(client);
151 411
152 mutex_lock(&data->update_lock); 412 mutex_lock(&data->update_lock);
153 ad525x_write(client, reg, 0); 413 dpot_write(data, reg, 0);
154 mutex_unlock(&data->update_lock); 414 mutex_unlock(&data->update_lock);
155 415
156 return count; 416 return count;
@@ -158,244 +418,131 @@ static ssize_t sysfs_do_cmd(struct device *dev,
158 418
159/* ------------------------------------------------------------------------- */ 419/* ------------------------------------------------------------------------- */
160 420
161static ssize_t show_rdac0(struct device *dev, 421#define DPOT_DEVICE_SHOW(_name, _reg) static ssize_t \
162 struct device_attribute *attr, char *buf) 422show_##_name(struct device *dev, \
163{ 423 struct device_attribute *attr, char *buf) \
164 return sysfs_show_reg(dev, attr, buf, AD525X_I2C_RDAC | AD525X_RDAC0); 424{ \
165} 425 return sysfs_show_reg(dev, attr, buf, _reg); \
166 426}
167static ssize_t set_rdac0(struct device *dev, 427
168 struct device_attribute *attr, 428#define DPOT_DEVICE_SET(_name, _reg) static ssize_t \
169 const char *buf, size_t count) 429set_##_name(struct device *dev, \
170{ 430 struct device_attribute *attr, \
171 return sysfs_set_reg(dev, attr, buf, count, 431 const char *buf, size_t count) \
172 AD525X_I2C_RDAC | AD525X_RDAC0); 432{ \
173} 433 return sysfs_set_reg(dev, attr, buf, count, _reg); \
174 434}
175static DEVICE_ATTR(rdac0, S_IWUSR | S_IRUGO, show_rdac0, set_rdac0); 435
176 436#define DPOT_DEVICE_SHOW_SET(name, reg) \
177static ssize_t show_eeprom0(struct device *dev, 437DPOT_DEVICE_SHOW(name, reg) \
178 struct device_attribute *attr, char *buf) 438DPOT_DEVICE_SET(name, reg) \
179{ 439static DEVICE_ATTR(name, S_IWUSR | S_IRUGO, show_##name, set_##name);
180 return sysfs_show_reg(dev, attr, buf, AD525X_I2C_EEPROM | AD525X_RDAC0); 440
181} 441#define DPOT_DEVICE_SHOW_ONLY(name, reg) \
182 442DPOT_DEVICE_SHOW(name, reg) \
183static ssize_t set_eeprom0(struct device *dev, 443static DEVICE_ATTR(name, S_IWUSR | S_IRUGO, show_##name, NULL);
184 struct device_attribute *attr, 444
185 const char *buf, size_t count) 445DPOT_DEVICE_SHOW_SET(rdac0, DPOT_ADDR_RDAC | DPOT_RDAC0);
186{ 446DPOT_DEVICE_SHOW_SET(eeprom0, DPOT_ADDR_EEPROM | DPOT_RDAC0);
187 return sysfs_set_reg(dev, attr, buf, count, 447DPOT_DEVICE_SHOW_ONLY(tolerance0, DPOT_ADDR_EEPROM | DPOT_TOL_RDAC0);
188 AD525X_I2C_EEPROM | AD525X_RDAC0); 448DPOT_DEVICE_SHOW_SET(otp0, DPOT_ADDR_OTP | DPOT_RDAC0);
189} 449DPOT_DEVICE_SHOW_SET(otp0en, DPOT_ADDR_OTP_EN | DPOT_RDAC0);
190 450
191static DEVICE_ATTR(eeprom0, S_IWUSR | S_IRUGO, show_eeprom0, set_eeprom0); 451DPOT_DEVICE_SHOW_SET(rdac1, DPOT_ADDR_RDAC | DPOT_RDAC1);
192 452DPOT_DEVICE_SHOW_SET(eeprom1, DPOT_ADDR_EEPROM | DPOT_RDAC1);
193static ssize_t show_tolerance0(struct device *dev, 453DPOT_DEVICE_SHOW_ONLY(tolerance1, DPOT_ADDR_EEPROM | DPOT_TOL_RDAC1);
194 struct device_attribute *attr, char *buf) 454DPOT_DEVICE_SHOW_SET(otp1, DPOT_ADDR_OTP | DPOT_RDAC1);
195{ 455DPOT_DEVICE_SHOW_SET(otp1en, DPOT_ADDR_OTP_EN | DPOT_RDAC1);
196 return sysfs_show_reg(dev, attr, buf, 456
197 AD525X_I2C_EEPROM | AD525X_TOL_RDAC0); 457DPOT_DEVICE_SHOW_SET(rdac2, DPOT_ADDR_RDAC | DPOT_RDAC2);
198} 458DPOT_DEVICE_SHOW_SET(eeprom2, DPOT_ADDR_EEPROM | DPOT_RDAC2);
199 459DPOT_DEVICE_SHOW_ONLY(tolerance2, DPOT_ADDR_EEPROM | DPOT_TOL_RDAC2);
200static DEVICE_ATTR(tolerance0, S_IRUGO, show_tolerance0, NULL); 460DPOT_DEVICE_SHOW_SET(otp2, DPOT_ADDR_OTP | DPOT_RDAC2);
201 461DPOT_DEVICE_SHOW_SET(otp2en, DPOT_ADDR_OTP_EN | DPOT_RDAC2);
202/* ------------------------------------------------------------------------- */ 462
203 463DPOT_DEVICE_SHOW_SET(rdac3, DPOT_ADDR_RDAC | DPOT_RDAC3);
204static ssize_t show_rdac1(struct device *dev, 464DPOT_DEVICE_SHOW_SET(eeprom3, DPOT_ADDR_EEPROM | DPOT_RDAC3);
205 struct device_attribute *attr, char *buf) 465DPOT_DEVICE_SHOW_ONLY(tolerance3, DPOT_ADDR_EEPROM | DPOT_TOL_RDAC3);
206{ 466DPOT_DEVICE_SHOW_SET(otp3, DPOT_ADDR_OTP | DPOT_RDAC3);
207 return sysfs_show_reg(dev, attr, buf, AD525X_I2C_RDAC | AD525X_RDAC1); 467DPOT_DEVICE_SHOW_SET(otp3en, DPOT_ADDR_OTP_EN | DPOT_RDAC3);
208} 468
209 469DPOT_DEVICE_SHOW_SET(rdac4, DPOT_ADDR_RDAC | DPOT_RDAC4);
210static ssize_t set_rdac1(struct device *dev, 470DPOT_DEVICE_SHOW_SET(eeprom4, DPOT_ADDR_EEPROM | DPOT_RDAC4);
211 struct device_attribute *attr, 471DPOT_DEVICE_SHOW_ONLY(tolerance4, DPOT_ADDR_EEPROM | DPOT_TOL_RDAC4);
212 const char *buf, size_t count) 472DPOT_DEVICE_SHOW_SET(otp4, DPOT_ADDR_OTP | DPOT_RDAC4);
213{ 473DPOT_DEVICE_SHOW_SET(otp4en, DPOT_ADDR_OTP_EN | DPOT_RDAC4);
214 return sysfs_set_reg(dev, attr, buf, count, 474
215 AD525X_I2C_RDAC | AD525X_RDAC1); 475DPOT_DEVICE_SHOW_SET(rdac5, DPOT_ADDR_RDAC | DPOT_RDAC5);
216} 476DPOT_DEVICE_SHOW_SET(eeprom5, DPOT_ADDR_EEPROM | DPOT_RDAC5);
217 477DPOT_DEVICE_SHOW_ONLY(tolerance5, DPOT_ADDR_EEPROM | DPOT_TOL_RDAC5);
218static DEVICE_ATTR(rdac1, S_IWUSR | S_IRUGO, show_rdac1, set_rdac1); 478DPOT_DEVICE_SHOW_SET(otp5, DPOT_ADDR_OTP | DPOT_RDAC5);
219 479DPOT_DEVICE_SHOW_SET(otp5en, DPOT_ADDR_OTP_EN | DPOT_RDAC5);
220static ssize_t show_eeprom1(struct device *dev, 480
221 struct device_attribute *attr, char *buf) 481static const struct attribute *dpot_attrib_wipers[] = {
222{ 482 &dev_attr_rdac0.attr,
223 return sysfs_show_reg(dev, attr, buf, AD525X_I2C_EEPROM | AD525X_RDAC1); 483 &dev_attr_rdac1.attr,
224} 484 &dev_attr_rdac2.attr,
225 485 &dev_attr_rdac3.attr,
226static ssize_t set_eeprom1(struct device *dev, 486 &dev_attr_rdac4.attr,
227 struct device_attribute *attr, 487 &dev_attr_rdac5.attr,
228 const char *buf, size_t count) 488 NULL
229{ 489};
230 return sysfs_set_reg(dev, attr, buf, count,
231 AD525X_I2C_EEPROM | AD525X_RDAC1);
232}
233
234static DEVICE_ATTR(eeprom1, S_IWUSR | S_IRUGO, show_eeprom1, set_eeprom1);
235
236static ssize_t show_tolerance1(struct device *dev,
237 struct device_attribute *attr, char *buf)
238{
239 return sysfs_show_reg(dev, attr, buf,
240 AD525X_I2C_EEPROM | AD525X_TOL_RDAC1);
241}
242
243static DEVICE_ATTR(tolerance1, S_IRUGO, show_tolerance1, NULL);
244
245/* ------------------------------------------------------------------------- */
246
247static ssize_t show_rdac2(struct device *dev,
248 struct device_attribute *attr, char *buf)
249{
250 return sysfs_show_reg(dev, attr, buf, AD525X_I2C_RDAC | AD525X_RDAC2);
251}
252
253static ssize_t set_rdac2(struct device *dev,
254 struct device_attribute *attr,
255 const char *buf, size_t count)
256{
257 return sysfs_set_reg(dev, attr, buf, count,
258 AD525X_I2C_RDAC | AD525X_RDAC2);
259}
260
261static DEVICE_ATTR(rdac2, S_IWUSR | S_IRUGO, show_rdac2, set_rdac2);
262
263static ssize_t show_eeprom2(struct device *dev,
264 struct device_attribute *attr, char *buf)
265{
266 return sysfs_show_reg(dev, attr, buf, AD525X_I2C_EEPROM | AD525X_RDAC2);
267}
268
269static ssize_t set_eeprom2(struct device *dev,
270 struct device_attribute *attr,
271 const char *buf, size_t count)
272{
273 return sysfs_set_reg(dev, attr, buf, count,
274 AD525X_I2C_EEPROM | AD525X_RDAC2);
275}
276
277static DEVICE_ATTR(eeprom2, S_IWUSR | S_IRUGO, show_eeprom2, set_eeprom2);
278
279static ssize_t show_tolerance2(struct device *dev,
280 struct device_attribute *attr, char *buf)
281{
282 return sysfs_show_reg(dev, attr, buf,
283 AD525X_I2C_EEPROM | AD525X_TOL_RDAC2);
284}
285
286static DEVICE_ATTR(tolerance2, S_IRUGO, show_tolerance2, NULL);
287
288/* ------------------------------------------------------------------------- */
289
290static ssize_t show_rdac3(struct device *dev,
291 struct device_attribute *attr, char *buf)
292{
293 return sysfs_show_reg(dev, attr, buf, AD525X_I2C_RDAC | AD525X_RDAC3);
294}
295
296static ssize_t set_rdac3(struct device *dev,
297 struct device_attribute *attr,
298 const char *buf, size_t count)
299{
300 return sysfs_set_reg(dev, attr, buf, count,
301 AD525X_I2C_RDAC | AD525X_RDAC3);
302}
303
304static DEVICE_ATTR(rdac3, S_IWUSR | S_IRUGO, show_rdac3, set_rdac3);
305
306static ssize_t show_eeprom3(struct device *dev,
307 struct device_attribute *attr, char *buf)
308{
309 return sysfs_show_reg(dev, attr, buf, AD525X_I2C_EEPROM | AD525X_RDAC3);
310}
311
312static ssize_t set_eeprom3(struct device *dev,
313 struct device_attribute *attr,
314 const char *buf, size_t count)
315{
316 return sysfs_set_reg(dev, attr, buf, count,
317 AD525X_I2C_EEPROM | AD525X_RDAC3);
318}
319 490
320static DEVICE_ATTR(eeprom3, S_IWUSR | S_IRUGO, show_eeprom3, set_eeprom3); 491static const struct attribute *dpot_attrib_eeprom[] = {
492 &dev_attr_eeprom0.attr,
493 &dev_attr_eeprom1.attr,
494 &dev_attr_eeprom2.attr,
495 &dev_attr_eeprom3.attr,
496 &dev_attr_eeprom4.attr,
497 &dev_attr_eeprom5.attr,
498 NULL
499};
321 500
322static ssize_t show_tolerance3(struct device *dev, 501static const struct attribute *dpot_attrib_otp[] = {
323 struct device_attribute *attr, char *buf) 502 &dev_attr_otp0.attr,
324{ 503 &dev_attr_otp1.attr,
325 return sysfs_show_reg(dev, attr, buf, 504 &dev_attr_otp2.attr,
326 AD525X_I2C_EEPROM | AD525X_TOL_RDAC3); 505 &dev_attr_otp3.attr,
327} 506 &dev_attr_otp4.attr,
507 &dev_attr_otp5.attr,
508 NULL
509};
328 510
329static DEVICE_ATTR(tolerance3, S_IRUGO, show_tolerance3, NULL); 511static const struct attribute *dpot_attrib_otp_en[] = {
330 512 &dev_attr_otp0en.attr,
331static struct attribute *ad525x_attributes_wipers[4][4] = { 513 &dev_attr_otp1en.attr,
332 { 514 &dev_attr_otp2en.attr,
333 &dev_attr_rdac0.attr, 515 &dev_attr_otp3en.attr,
334 &dev_attr_eeprom0.attr, 516 &dev_attr_otp4en.attr,
335 &dev_attr_tolerance0.attr, 517 &dev_attr_otp5en.attr,
336 NULL 518 NULL
337 }, {
338 &dev_attr_rdac1.attr,
339 &dev_attr_eeprom1.attr,
340 &dev_attr_tolerance1.attr,
341 NULL
342 }, {
343 &dev_attr_rdac2.attr,
344 &dev_attr_eeprom2.attr,
345 &dev_attr_tolerance2.attr,
346 NULL
347 }, {
348 &dev_attr_rdac3.attr,
349 &dev_attr_eeprom3.attr,
350 &dev_attr_tolerance3.attr,
351 NULL
352 }
353}; 519};
354 520
355static const struct attribute_group ad525x_group_wipers[] = { 521static const struct attribute *dpot_attrib_tolerance[] = {
356 {.attrs = ad525x_attributes_wipers[AD525X_RDAC0]}, 522 &dev_attr_tolerance0.attr,
357 {.attrs = ad525x_attributes_wipers[AD525X_RDAC1]}, 523 &dev_attr_tolerance1.attr,
358 {.attrs = ad525x_attributes_wipers[AD525X_RDAC2]}, 524 &dev_attr_tolerance2.attr,
359 {.attrs = ad525x_attributes_wipers[AD525X_RDAC3]}, 525 &dev_attr_tolerance3.attr,
526 &dev_attr_tolerance4.attr,
527 &dev_attr_tolerance5.attr,
528 NULL
360}; 529};
361 530
362/* ------------------------------------------------------------------------- */ 531/* ------------------------------------------------------------------------- */
363 532
364static ssize_t set_inc_all(struct device *dev, 533#define DPOT_DEVICE_DO_CMD(_name, _cmd) static ssize_t \
365 struct device_attribute *attr, 534set_##_name(struct device *dev, \
366 const char *buf, size_t count) 535 struct device_attribute *attr, \
367{ 536 const char *buf, size_t count) \
368 return sysfs_do_cmd(dev, attr, buf, count, AD525X_INC_ALL); 537{ \
369} 538 return sysfs_do_cmd(dev, attr, buf, count, _cmd); \
539} \
540static DEVICE_ATTR(_name, S_IWUSR | S_IRUGO, NULL, set_##_name);
370 541
371static DEVICE_ATTR(inc_all, S_IWUSR, NULL, set_inc_all); 542DPOT_DEVICE_DO_CMD(inc_all, DPOT_INC_ALL);
372 543DPOT_DEVICE_DO_CMD(dec_all, DPOT_DEC_ALL);
373static ssize_t set_dec_all(struct device *dev, 544DPOT_DEVICE_DO_CMD(inc_all_6db, DPOT_INC_ALL_6DB);
374 struct device_attribute *attr, 545DPOT_DEVICE_DO_CMD(dec_all_6db, DPOT_DEC_ALL_6DB);
375 const char *buf, size_t count)
376{
377 return sysfs_do_cmd(dev, attr, buf, count, AD525X_DEC_ALL);
378}
379
380static DEVICE_ATTR(dec_all, S_IWUSR, NULL, set_dec_all);
381
382static ssize_t set_inc_all_6db(struct device *dev,
383 struct device_attribute *attr,
384 const char *buf, size_t count)
385{
386 return sysfs_do_cmd(dev, attr, buf, count, AD525X_INC_ALL_6DB);
387}
388
389static DEVICE_ATTR(inc_all_6db, S_IWUSR, NULL, set_inc_all_6db);
390
391static ssize_t set_dec_all_6db(struct device *dev,
392 struct device_attribute *attr,
393 const char *buf, size_t count)
394{
395 return sysfs_do_cmd(dev, attr, buf, count, AD525X_DEC_ALL_6DB);
396}
397
398static DEVICE_ATTR(dec_all_6db, S_IWUSR, NULL, set_dec_all_6db);
399 546
400static struct attribute *ad525x_attributes_commands[] = { 547static struct attribute *ad525x_attributes_commands[] = {
401 &dev_attr_inc_all.attr, 548 &dev_attr_inc_all.attr,
@@ -409,74 +556,56 @@ static const struct attribute_group ad525x_group_commands = {
409 .attrs = ad525x_attributes_commands, 556 .attrs = ad525x_attributes_commands,
410}; 557};
411 558
412/* ------------------------------------------------------------------------- */ 559__devinit int ad_dpot_add_files(struct device *dev,
413 560 unsigned features, unsigned rdac)
414/* i2c device functions */ 561{
562 int err = sysfs_create_file(&dev->kobj,
563 dpot_attrib_wipers[rdac]);
564 if (features & F_CMD_EEP)
565 err |= sysfs_create_file(&dev->kobj,
566 dpot_attrib_eeprom[rdac]);
567 if (features & F_CMD_TOL)
568 err |= sysfs_create_file(&dev->kobj,
569 dpot_attrib_tolerance[rdac]);
570 if (features & F_CMD_OTP) {
571 err |= sysfs_create_file(&dev->kobj,
572 dpot_attrib_otp_en[rdac]);
573 err |= sysfs_create_file(&dev->kobj,
574 dpot_attrib_otp[rdac]);
575 }
415 576
416/** 577 if (err)
417 * ad525x_read - return the value contained in the specified register 578 dev_err(dev, "failed to register sysfs hooks for RDAC%d\n",
418 * on the AD5258 device. 579 rdac);
419 * @client: value returned from i2c_new_device()
420 * @reg: the register to read
421 *
422 * If the tolerance register is specified, 2 bytes are returned.
423 * Otherwise, 1 byte is returned. A negative value indicates an error
424 * occurred while reading the register.
425 */
426static s32 ad525x_read(struct i2c_client *client, u8 reg)
427{
428 struct dpot_data *data = i2c_get_clientdata(client);
429 580
430 if ((reg & AD525X_REG_TOL) || (data->max_pos > 256)) 581 return err;
431 return i2c_smbus_read_word_data(client, (reg & 0xF8) |
432 ((reg & 0x7) << 1));
433 else
434 return i2c_smbus_read_byte_data(client, reg);
435} 582}
436 583
437/** 584inline void ad_dpot_remove_files(struct device *dev,
438 * ad525x_write - store the given value in the specified register on 585 unsigned features, unsigned rdac)
439 * the AD5258 device. 586{
440 * @client: value returned from i2c_new_device() 587 sysfs_remove_file(&dev->kobj,
441 * @reg: the register to write 588 dpot_attrib_wipers[rdac]);
442 * @value: the byte to store in the register 589 if (features & F_CMD_EEP)
443 * 590 sysfs_remove_file(&dev->kobj,
444 * For certain instructions that do not require a data byte, "NULL" 591 dpot_attrib_eeprom[rdac]);
445 * should be specified for the "value" parameter. These instructions 592 if (features & F_CMD_TOL)
446 * include NOP, RESTORE_FROM_EEPROM, and STORE_TO_EEPROM. 593 sysfs_remove_file(&dev->kobj,
447 * 594 dpot_attrib_tolerance[rdac]);
448 * A negative return value indicates an error occurred while reading 595 if (features & F_CMD_OTP) {
449 * the register. 596 sysfs_remove_file(&dev->kobj,
450 */ 597 dpot_attrib_otp_en[rdac]);
451static s32 ad525x_write(struct i2c_client *client, u8 reg, u8 value) 598 sysfs_remove_file(&dev->kobj,
452{ 599 dpot_attrib_otp[rdac]);
453 struct dpot_data *data = i2c_get_clientdata(client); 600 }
454
455 /* Only write the instruction byte for certain commands */
456 if (reg & AD525X_I2C_CMD)
457 return i2c_smbus_write_byte(client, reg);
458
459 if (data->max_pos > 256)
460 return i2c_smbus_write_word_data(client, (reg & 0xF8) |
461 ((reg & 0x7) << 1), value);
462 else
463 /* All other registers require instruction + data bytes */
464 return i2c_smbus_write_byte_data(client, reg, value);
465} 601}
466 602
467static int ad525x_probe(struct i2c_client *client, 603__devinit int ad_dpot_probe(struct device *dev,
468 const struct i2c_device_id *id) 604 struct ad_dpot_bus_data *bdata, const struct ad_dpot_id *id)
469{ 605{
470 struct device *dev = &client->dev;
471 struct dpot_data *data;
472 int err = 0;
473 606
474 dev_dbg(dev, "%s\n", __func__); 607 struct dpot_data *data;
475 608 int i, err = 0;
476 if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE)) {
477 dev_err(dev, "missing I2C functionality for this driver\n");
478 goto exit;
479 }
480 609
481 data = kzalloc(sizeof(struct dpot_data), GFP_KERNEL); 610 data = kzalloc(sizeof(struct dpot_data), GFP_KERNEL);
482 if (!data) { 611 if (!data) {
@@ -484,183 +613,74 @@ static int ad525x_probe(struct i2c_client *client,
484 goto exit; 613 goto exit;
485 } 614 }
486 615
487 i2c_set_clientdata(client, data); 616 dev_set_drvdata(dev, data);
488 mutex_init(&data->update_lock); 617 mutex_init(&data->update_lock);
489 618
490 switch (id->driver_data) { 619 data->bdata = *bdata;
491 case AD5258_ID: 620 data->devid = id->devid;
492 data->max_pos = AD5258_MAX_POSITION; 621
493 err = sysfs_create_group(&dev->kobj, 622 data->max_pos = 1 << DPOT_MAX_POS(data->devid);
494 &ad525x_group_wipers[AD525X_RDAC0]); 623 data->rdac_mask = data->max_pos - 1;
495 break; 624 data->feat = DPOT_FEAT(data->devid);
496 case AD5259_ID: 625 data->uid = DPOT_UID(data->devid);
497 data->max_pos = AD5259_MAX_POSITION; 626 data->wipers = DPOT_WIPERS(data->devid);
498 err = sysfs_create_group(&dev->kobj, 627
499 &ad525x_group_wipers[AD525X_RDAC0]); 628 for (i = DPOT_RDAC0; i < MAX_RDACS; i++)
500 break; 629 if (data->wipers & (1 << i)) {
501 case AD5251_ID: 630 err = ad_dpot_add_files(dev, data->feat, i);
502 data->max_pos = AD5251_MAX_POSITION; 631 if (err)
503 err = sysfs_create_group(&dev->kobj, 632 goto exit_remove_files;
504 &ad525x_group_wipers[AD525X_RDAC1]); 633 /* power-up midscale */
505 err |= sysfs_create_group(&dev->kobj, 634 if (data->feat & F_RDACS_WONLY)
506 &ad525x_group_wipers[AD525X_RDAC3]); 635 data->rdac_cache[i] = data->max_pos / 2;
507 err |= sysfs_create_group(&dev->kobj, &ad525x_group_commands); 636 }
508 break; 637
509 case AD5252_ID: 638 if (data->feat & F_CMD_INC)
510 data->max_pos = AD5252_MAX_POSITION; 639 err = sysfs_create_group(&dev->kobj, &ad525x_group_commands);
511 err = sysfs_create_group(&dev->kobj,
512 &ad525x_group_wipers[AD525X_RDAC1]);
513 err |= sysfs_create_group(&dev->kobj,
514 &ad525x_group_wipers[AD525X_RDAC3]);
515 err |= sysfs_create_group(&dev->kobj, &ad525x_group_commands);
516 break;
517 case AD5253_ID:
518 data->max_pos = AD5253_MAX_POSITION;
519 err = sysfs_create_group(&dev->kobj,
520 &ad525x_group_wipers[AD525X_RDAC0]);
521 err |= sysfs_create_group(&dev->kobj,
522 &ad525x_group_wipers[AD525X_RDAC1]);
523 err |= sysfs_create_group(&dev->kobj,
524 &ad525x_group_wipers[AD525X_RDAC2]);
525 err |= sysfs_create_group(&dev->kobj,
526 &ad525x_group_wipers[AD525X_RDAC3]);
527 err |= sysfs_create_group(&dev->kobj, &ad525x_group_commands);
528 break;
529 case AD5254_ID:
530 data->max_pos = AD5254_MAX_POSITION;
531 err = sysfs_create_group(&dev->kobj,
532 &ad525x_group_wipers[AD525X_RDAC0]);
533 err |= sysfs_create_group(&dev->kobj,
534 &ad525x_group_wipers[AD525X_RDAC1]);
535 err |= sysfs_create_group(&dev->kobj,
536 &ad525x_group_wipers[AD525X_RDAC2]);
537 err |= sysfs_create_group(&dev->kobj,
538 &ad525x_group_wipers[AD525X_RDAC3]);
539 err |= sysfs_create_group(&dev->kobj, &ad525x_group_commands);
540 break;
541 case AD5255_ID:
542 data->max_pos = AD5255_MAX_POSITION;
543 err = sysfs_create_group(&dev->kobj,
544 &ad525x_group_wipers[AD525X_RDAC0]);
545 err |= sysfs_create_group(&dev->kobj,
546 &ad525x_group_wipers[AD525X_RDAC1]);
547 err |= sysfs_create_group(&dev->kobj,
548 &ad525x_group_wipers[AD525X_RDAC2]);
549 err |= sysfs_create_group(&dev->kobj, &ad525x_group_commands);
550 break;
551 default:
552 err = -ENODEV;
553 goto exit_free;
554 }
555 640
556 if (err) { 641 if (err) {
557 dev_err(dev, "failed to register sysfs hooks\n"); 642 dev_err(dev, "failed to register sysfs hooks\n");
558 goto exit_free; 643 goto exit_free;
559 } 644 }
560 645
561 data->devid = id->driver_data;
562 data->rdac_mask = data->max_pos - 1;
563
564 dev_info(dev, "%s %d-Position Digital Potentiometer registered\n", 646 dev_info(dev, "%s %d-Position Digital Potentiometer registered\n",
565 id->name, data->max_pos); 647 id->name, data->max_pos);
566 648
567 return 0; 649 return 0;
568 650
651exit_remove_files:
652 for (i = DPOT_RDAC0; i < MAX_RDACS; i++)
653 if (data->wipers & (1 << i))
654 ad_dpot_remove_files(dev, data->feat, i);
655
569exit_free: 656exit_free:
570 kfree(data); 657 kfree(data);
571 i2c_set_clientdata(client, NULL); 658 dev_set_drvdata(dev, NULL);
572exit: 659exit:
573 dev_err(dev, "failed to create client\n"); 660 dev_err(dev, "failed to create client for %s ID 0x%lX\n",
661 id->name, id->devid);
574 return err; 662 return err;
575} 663}
664EXPORT_SYMBOL(ad_dpot_probe);
576 665
577static int __devexit ad525x_remove(struct i2c_client *client) 666__devexit int ad_dpot_remove(struct device *dev)
578{ 667{
579 struct dpot_data *data = i2c_get_clientdata(client); 668 struct dpot_data *data = dev_get_drvdata(dev);
580 struct device *dev = &client->dev; 669 int i;
581 670
582 switch (data->devid) { 671 for (i = DPOT_RDAC0; i < MAX_RDACS; i++)
583 case AD5258_ID: 672 if (data->wipers & (1 << i))
584 case AD5259_ID: 673 ad_dpot_remove_files(dev, data->feat, i);
585 sysfs_remove_group(&dev->kobj,
586 &ad525x_group_wipers[AD525X_RDAC0]);
587 break;
588 case AD5251_ID:
589 case AD5252_ID:
590 sysfs_remove_group(&dev->kobj,
591 &ad525x_group_wipers[AD525X_RDAC1]);
592 sysfs_remove_group(&dev->kobj,
593 &ad525x_group_wipers[AD525X_RDAC3]);
594 sysfs_remove_group(&dev->kobj, &ad525x_group_commands);
595 break;
596 case AD5253_ID:
597 case AD5254_ID:
598 sysfs_remove_group(&dev->kobj,
599 &ad525x_group_wipers[AD525X_RDAC0]);
600 sysfs_remove_group(&dev->kobj,
601 &ad525x_group_wipers[AD525X_RDAC1]);
602 sysfs_remove_group(&dev->kobj,
603 &ad525x_group_wipers[AD525X_RDAC2]);
604 sysfs_remove_group(&dev->kobj,
605 &ad525x_group_wipers[AD525X_RDAC3]);
606 sysfs_remove_group(&dev->kobj, &ad525x_group_commands);
607 break;
608 case AD5255_ID:
609 sysfs_remove_group(&dev->kobj,
610 &ad525x_group_wipers[AD525X_RDAC0]);
611 sysfs_remove_group(&dev->kobj,
612 &ad525x_group_wipers[AD525X_RDAC1]);
613 sysfs_remove_group(&dev->kobj,
614 &ad525x_group_wipers[AD525X_RDAC2]);
615 sysfs_remove_group(&dev->kobj, &ad525x_group_commands);
616 break;
617 }
618 674
619 i2c_set_clientdata(client, NULL);
620 kfree(data); 675 kfree(data);
621 676
622 return 0; 677 return 0;
623} 678}
679EXPORT_SYMBOL(ad_dpot_remove);
624 680
625static const struct i2c_device_id ad525x_idtable[] = {
626 {"ad5258", AD5258_ID},
627 {"ad5259", AD5259_ID},
628 {"ad5251", AD5251_ID},
629 {"ad5252", AD5252_ID},
630 {"ad5253", AD5253_ID},
631 {"ad5254", AD5254_ID},
632 {"ad5255", AD5255_ID},
633 {}
634};
635
636MODULE_DEVICE_TABLE(i2c, ad525x_idtable);
637
638static struct i2c_driver ad525x_driver = {
639 .driver = {
640 .owner = THIS_MODULE,
641 .name = DRIVER_NAME,
642 },
643 .id_table = ad525x_idtable,
644 .probe = ad525x_probe,
645 .remove = __devexit_p(ad525x_remove),
646};
647
648static int __init ad525x_init(void)
649{
650 return i2c_add_driver(&ad525x_driver);
651}
652
653module_init(ad525x_init);
654
655static void __exit ad525x_exit(void)
656{
657 i2c_del_driver(&ad525x_driver);
658}
659
660module_exit(ad525x_exit);
661 681
662MODULE_AUTHOR("Chris Verges <chrisv@cyberswitching.com>, " 682MODULE_AUTHOR("Chris Verges <chrisv@cyberswitching.com>, "
663 "Michael Hennerich <hennerich@blackfin.uclinux.org>, "); 683 "Michael Hennerich <hennerich@blackfin.uclinux.org>");
664MODULE_DESCRIPTION("AD5258/9 digital potentiometer driver"); 684MODULE_DESCRIPTION("Digital potentiometer driver");
665MODULE_LICENSE("GPL"); 685MODULE_LICENSE("GPL");
666MODULE_VERSION(DRIVER_VERSION); 686MODULE_VERSION(DRIVER_VERSION);
diff --git a/drivers/misc/ad525x_dpot.h b/drivers/misc/ad525x_dpot.h
new file mode 100644
index 000000000000..78b89fd2e2fd
--- /dev/null
+++ b/drivers/misc/ad525x_dpot.h
@@ -0,0 +1,202 @@
1/*
2 * Driver for the Analog Devices digital potentiometers
3 *
4 * Copyright (C) 2010 Michael Hennerich, Analog Devices Inc.
5 *
6 * Licensed under the GPL-2 or later.
7 */
8
9#ifndef _AD_DPOT_H_
10#define _AD_DPOT_H_
11
12#include <linux/types.h>
13
14#define DPOT_CONF(features, wipers, max_pos, uid) \
15 (((features) << 18) | (((wipers) & 0xFF) << 10) | \
16 ((max_pos & 0xF) << 6) | (uid & 0x3F))
17
18#define DPOT_UID(conf) (conf & 0x3F)
19#define DPOT_MAX_POS(conf) ((conf >> 6) & 0xF)
20#define DPOT_WIPERS(conf) ((conf >> 10) & 0xFF)
21#define DPOT_FEAT(conf) (conf >> 18)
22
23#define BRDAC0 (1 << 0)
24#define BRDAC1 (1 << 1)
25#define BRDAC2 (1 << 2)
26#define BRDAC3 (1 << 3)
27#define BRDAC4 (1 << 4)
28#define BRDAC5 (1 << 5)
29#define MAX_RDACS 6
30
31#define F_CMD_INC (1 << 0) /* Features INC/DEC ALL, 6dB */
32#define F_CMD_EEP (1 << 1) /* Features EEPROM */
33#define F_CMD_OTP (1 << 2) /* Features OTP */
34#define F_CMD_TOL (1 << 3) /* RDACS feature Tolerance REG */
35#define F_RDACS_RW (1 << 4) /* RDACS are Read/Write */
36#define F_RDACS_WONLY (1 << 5) /* RDACS are Write only */
37#define F_AD_APPDATA (1 << 6) /* RDAC Address append to data */
38#define F_SPI_8BIT (1 << 7) /* All SPI XFERS are 8-bit */
39#define F_SPI_16BIT (1 << 8) /* All SPI XFERS are 16-bit */
40#define F_SPI_24BIT (1 << 9) /* All SPI XFERS are 24-bit */
41
42#define F_RDACS_RW_TOL (F_RDACS_RW | F_CMD_EEP | F_CMD_TOL)
43#define F_RDACS_RW_EEP (F_RDACS_RW | F_CMD_EEP)
44#define F_SPI (F_SPI_8BIT | F_SPI_16BIT | F_SPI_24BIT)
45
46enum dpot_devid {
47 AD5258_ID = DPOT_CONF(F_RDACS_RW_TOL, BRDAC0, 6, 0), /* I2C */
48 AD5259_ID = DPOT_CONF(F_RDACS_RW_TOL, BRDAC0, 8, 1),
49 AD5251_ID = DPOT_CONF(F_RDACS_RW_TOL | F_CMD_INC,
50 BRDAC0 | BRDAC3, 6, 2),
51 AD5252_ID = DPOT_CONF(F_RDACS_RW_TOL | F_CMD_INC,
52 BRDAC0 | BRDAC3, 8, 3),
53 AD5253_ID = DPOT_CONF(F_RDACS_RW_TOL | F_CMD_INC,
54 BRDAC0 | BRDAC1 | BRDAC2 | BRDAC3, 6, 4),
55 AD5254_ID = DPOT_CONF(F_RDACS_RW_TOL | F_CMD_INC,
56 BRDAC0 | BRDAC1 | BRDAC2 | BRDAC3, 8, 5),
57 AD5255_ID = DPOT_CONF(F_RDACS_RW_TOL | F_CMD_INC,
58 BRDAC0 | BRDAC1 | BRDAC2, 9, 6),
59 AD5160_ID = DPOT_CONF(F_RDACS_WONLY | F_AD_APPDATA | F_SPI_8BIT,
60 BRDAC0, 8, 7), /* SPI */
61 AD5161_ID = DPOT_CONF(F_RDACS_WONLY | F_AD_APPDATA | F_SPI_8BIT,
62 BRDAC0, 8, 8),
63 AD5162_ID = DPOT_CONF(F_RDACS_WONLY | F_AD_APPDATA | F_SPI_16BIT,
64 BRDAC0 | BRDAC1, 8, 9),
65 AD5165_ID = DPOT_CONF(F_RDACS_WONLY | F_AD_APPDATA | F_SPI_8BIT,
66 BRDAC0, 8, 10),
67 AD5200_ID = DPOT_CONF(F_RDACS_WONLY | F_AD_APPDATA | F_SPI_8BIT,
68 BRDAC0, 8, 11),
69 AD5201_ID = DPOT_CONF(F_RDACS_WONLY | F_AD_APPDATA | F_SPI_8BIT,
70 BRDAC0, 5, 12),
71 AD5203_ID = DPOT_CONF(F_RDACS_WONLY | F_AD_APPDATA | F_SPI_8BIT,
72 BRDAC0 | BRDAC1 | BRDAC2 | BRDAC3, 6, 13),
73 AD5204_ID = DPOT_CONF(F_RDACS_WONLY | F_AD_APPDATA | F_SPI_16BIT,
74 BRDAC0 | BRDAC1 | BRDAC2 | BRDAC3, 8, 14),
75 AD5206_ID = DPOT_CONF(F_RDACS_WONLY | F_AD_APPDATA | F_SPI_16BIT,
76 BRDAC0 | BRDAC1 | BRDAC2 | BRDAC3 | BRDAC4 | BRDAC5,
77 8, 15),
78 AD5207_ID = DPOT_CONF(F_RDACS_WONLY | F_AD_APPDATA | F_SPI_16BIT,
79 BRDAC0 | BRDAC1, 8, 16),
80 AD5231_ID = DPOT_CONF(F_RDACS_RW_EEP | F_CMD_INC | F_SPI_24BIT,
81 BRDAC0, 10, 17),
82 AD5232_ID = DPOT_CONF(F_RDACS_RW_EEP | F_CMD_INC | F_SPI_16BIT,
83 BRDAC0 | BRDAC1, 8, 18),
84 AD5233_ID = DPOT_CONF(F_RDACS_RW_EEP | F_CMD_INC | F_SPI_16BIT,
85 BRDAC0 | BRDAC1 | BRDAC2 | BRDAC3, 6, 19),
86 AD5235_ID = DPOT_CONF(F_RDACS_RW_EEP | F_CMD_INC | F_SPI_24BIT,
87 BRDAC0 | BRDAC1, 10, 20),
88 AD5260_ID = DPOT_CONF(F_RDACS_WONLY | F_AD_APPDATA | F_SPI_8BIT,
89 BRDAC0, 8, 21),
90 AD5262_ID = DPOT_CONF(F_RDACS_WONLY | F_AD_APPDATA | F_SPI_16BIT,
91 BRDAC0 | BRDAC1, 8, 22),
92 AD5263_ID = DPOT_CONF(F_RDACS_WONLY | F_AD_APPDATA | F_SPI_16BIT,
93 BRDAC0 | BRDAC1 | BRDAC2 | BRDAC3, 8, 23),
94 AD5290_ID = DPOT_CONF(F_RDACS_WONLY | F_AD_APPDATA | F_SPI_8BIT,
95 BRDAC0, 8, 24),
96 AD5291_ID = DPOT_CONF(F_RDACS_RW | F_SPI_16BIT, BRDAC0, 8, 25),
97 AD5292_ID = DPOT_CONF(F_RDACS_RW | F_SPI_16BIT, BRDAC0, 10, 26),
98 AD5293_ID = DPOT_CONF(F_RDACS_RW | F_SPI_16BIT, BRDAC0, 10, 27),
99 AD7376_ID = DPOT_CONF(F_RDACS_WONLY | F_AD_APPDATA | F_SPI_8BIT,
100 BRDAC0, 7, 28),
101 AD8400_ID = DPOT_CONF(F_RDACS_WONLY | F_AD_APPDATA | F_SPI_8BIT,
102 BRDAC0, 8, 29),
103 AD8402_ID = DPOT_CONF(F_RDACS_WONLY | F_AD_APPDATA | F_SPI_16BIT,
104 BRDAC0 | BRDAC1, 8, 30),
105 AD8403_ID = DPOT_CONF(F_RDACS_WONLY | F_AD_APPDATA | F_SPI_16BIT,
106 BRDAC0 | BRDAC1 | BRDAC2, 8, 31),
107 ADN2850_ID = DPOT_CONF(F_RDACS_RW_EEP | F_CMD_INC | F_SPI_24BIT,
108 BRDAC0 | BRDAC1, 10, 32),
109 AD5241_ID = DPOT_CONF(F_RDACS_RW, BRDAC0, 8, 33),
110 AD5242_ID = DPOT_CONF(F_RDACS_RW, BRDAC0 | BRDAC1, 8, 34),
111 AD5243_ID = DPOT_CONF(F_RDACS_RW, BRDAC0 | BRDAC1, 8, 35),
112 AD5245_ID = DPOT_CONF(F_RDACS_RW, BRDAC0, 8, 36),
113 AD5246_ID = DPOT_CONF(F_RDACS_RW, BRDAC0, 7, 37),
114 AD5247_ID = DPOT_CONF(F_RDACS_RW, BRDAC0, 7, 38),
115 AD5248_ID = DPOT_CONF(F_RDACS_RW, BRDAC0 | BRDAC1, 8, 39),
116 AD5280_ID = DPOT_CONF(F_RDACS_RW, BRDAC0, 8, 40),
117 AD5282_ID = DPOT_CONF(F_RDACS_RW, BRDAC0 | BRDAC1, 8, 41),
118 ADN2860_ID = DPOT_CONF(F_RDACS_RW_TOL | F_CMD_INC,
119 BRDAC0 | BRDAC1 | BRDAC2, 9, 42),
120 AD5273_ID = DPOT_CONF(F_RDACS_RW | F_CMD_OTP, BRDAC0, 6, 43),
121 AD5171_ID = DPOT_CONF(F_RDACS_RW | F_CMD_OTP, BRDAC0, 6, 44),
122 AD5170_ID = DPOT_CONF(F_RDACS_RW | F_CMD_OTP, BRDAC0, 8, 45),
123 AD5172_ID = DPOT_CONF(F_RDACS_RW | F_CMD_OTP, BRDAC0 | BRDAC1, 8, 46),
124 AD5173_ID = DPOT_CONF(F_RDACS_RW | F_CMD_OTP, BRDAC0 | BRDAC1, 8, 47),
125};
126
127#define DPOT_RDAC0 0
128#define DPOT_RDAC1 1
129#define DPOT_RDAC2 2
130#define DPOT_RDAC3 3
131#define DPOT_RDAC4 4
132#define DPOT_RDAC5 5
133
134#define DPOT_RDAC_MASK 0x1F
135
136#define DPOT_REG_TOL 0x18
137#define DPOT_TOL_RDAC0 (DPOT_REG_TOL | DPOT_RDAC0)
138#define DPOT_TOL_RDAC1 (DPOT_REG_TOL | DPOT_RDAC1)
139#define DPOT_TOL_RDAC2 (DPOT_REG_TOL | DPOT_RDAC2)
140#define DPOT_TOL_RDAC3 (DPOT_REG_TOL | DPOT_RDAC3)
141#define DPOT_TOL_RDAC4 (DPOT_REG_TOL | DPOT_RDAC4)
142#define DPOT_TOL_RDAC5 (DPOT_REG_TOL | DPOT_RDAC5)
143
144/* RDAC-to-EEPROM Interface Commands */
145#define DPOT_ADDR_RDAC (0x0 << 5)
146#define DPOT_ADDR_EEPROM (0x1 << 5)
147#define DPOT_ADDR_OTP (0x1 << 6)
148#define DPOT_ADDR_CMD (0x1 << 7)
149#define DPOT_ADDR_OTP_EN (0x1 << 9)
150
151#define DPOT_DEC_ALL_6DB (DPOT_ADDR_CMD | (0x4 << 3))
152#define DPOT_INC_ALL_6DB (DPOT_ADDR_CMD | (0x9 << 3))
153#define DPOT_DEC_ALL (DPOT_ADDR_CMD | (0x6 << 3))
154#define DPOT_INC_ALL (DPOT_ADDR_CMD | (0xB << 3))
155
156#define DPOT_SPI_RDAC 0xB0
157#define DPOT_SPI_EEPROM 0x30
158#define DPOT_SPI_READ_RDAC 0xA0
159#define DPOT_SPI_READ_EEPROM 0x90
160#define DPOT_SPI_DEC_ALL_6DB 0x50
161#define DPOT_SPI_INC_ALL_6DB 0xD0
162#define DPOT_SPI_DEC_ALL 0x70
163#define DPOT_SPI_INC_ALL 0xF0
164
165/* AD5291/2/3 use special commands */
166#define DPOT_AD5291_RDAC 0x01
167#define DPOT_AD5291_READ_RDAC 0x02
168
169/* AD524x use special commands */
170#define DPOT_AD5291_RDAC_AB 0x80
171
172#define DPOT_AD5273_FUSE 0x80
173#define DPOT_AD5270_2_3_FUSE 0x20
174#define DPOT_AD5270_2_3_OW 0x08
175#define DPOT_AD5272_3_A0 0x08
176#define DPOT_AD5270_2FUSE 0x80
177
178struct dpot_data;
179
180struct ad_dpot_bus_ops {
181 int (*read_d8) (void *client);
182 int (*read_r8d8) (void *client, u8 reg);
183 int (*read_r8d16) (void *client, u8 reg);
184 int (*write_d8) (void *client, u8 val);
185 int (*write_r8d8) (void *client, u8 reg, u8 val);
186 int (*write_r8d16) (void *client, u8 reg, u16 val);
187};
188
189struct ad_dpot_bus_data {
190 void *client;
191 const struct ad_dpot_bus_ops *bops;
192};
193
194struct ad_dpot_id {
195 char *name;
196 unsigned long devid;
197};
198
199int ad_dpot_probe(struct device *dev, struct ad_dpot_bus_data *bdata, const struct ad_dpot_id *id);
200int ad_dpot_remove(struct device *dev);
201
202#endif
diff --git a/drivers/misc/c2port/core.c b/drivers/misc/c2port/core.c
index ed090e77c9cd..19fc7c1cb428 100644
--- a/drivers/misc/c2port/core.c
+++ b/drivers/misc/c2port/core.c
@@ -707,7 +707,7 @@ static ssize_t __c2port_read_flash_data(struct c2port_device *dev,
707 return nread; 707 return nread;
708} 708}
709 709
710static ssize_t c2port_read_flash_data(struct kobject *kobj, 710static ssize_t c2port_read_flash_data(struct file *filp, struct kobject *kobj,
711 struct bin_attribute *attr, 711 struct bin_attribute *attr,
712 char *buffer, loff_t offset, size_t count) 712 char *buffer, loff_t offset, size_t count)
713{ 713{
@@ -824,7 +824,7 @@ static ssize_t __c2port_write_flash_data(struct c2port_device *dev,
824 return nwrite; 824 return nwrite;
825} 825}
826 826
827static ssize_t c2port_write_flash_data(struct kobject *kobj, 827static ssize_t c2port_write_flash_data(struct file *filp, struct kobject *kobj,
828 struct bin_attribute *attr, 828 struct bin_attribute *attr,
829 char *buffer, loff_t offset, size_t count) 829 char *buffer, loff_t offset, size_t count)
830{ 830{
diff --git a/drivers/misc/ds1682.c b/drivers/misc/ds1682.c
index 9197cfc55015..a513f0aa6432 100644
--- a/drivers/misc/ds1682.c
+++ b/drivers/misc/ds1682.c
@@ -140,7 +140,8 @@ static const struct attribute_group ds1682_group = {
140/* 140/*
141 * User data attribute 141 * User data attribute
142 */ 142 */
143static ssize_t ds1682_eeprom_read(struct kobject *kobj, struct bin_attribute *attr, 143static ssize_t ds1682_eeprom_read(struct file *filp, struct kobject *kobj,
144 struct bin_attribute *attr,
144 char *buf, loff_t off, size_t count) 145 char *buf, loff_t off, size_t count)
145{ 146{
146 struct i2c_client *client = kobj_to_i2c_client(kobj); 147 struct i2c_client *client = kobj_to_i2c_client(kobj);
@@ -163,7 +164,8 @@ static ssize_t ds1682_eeprom_read(struct kobject *kobj, struct bin_attribute *at
163 return count; 164 return count;
164} 165}
165 166
166static ssize_t ds1682_eeprom_write(struct kobject *kobj, struct bin_attribute *attr, 167static ssize_t ds1682_eeprom_write(struct file *filp, struct kobject *kobj,
168 struct bin_attribute *attr,
167 char *buf, loff_t off, size_t count) 169 char *buf, loff_t off, size_t count)
168{ 170{
169 struct i2c_client *client = kobj_to_i2c_client(kobj); 171 struct i2c_client *client = kobj_to_i2c_client(kobj);
diff --git a/drivers/misc/eeprom/at24.c b/drivers/misc/eeprom/at24.c
index db7d0f21b65d..f7ca3a42b490 100644
--- a/drivers/misc/eeprom/at24.c
+++ b/drivers/misc/eeprom/at24.c
@@ -54,7 +54,7 @@
54struct at24_data { 54struct at24_data {
55 struct at24_platform_data chip; 55 struct at24_platform_data chip;
56 struct memory_accessor macc; 56 struct memory_accessor macc;
57 bool use_smbus; 57 int use_smbus;
58 58
59 /* 59 /*
60 * Lock protects against activities from other Linux tasks, 60 * Lock protects against activities from other Linux tasks,
@@ -184,11 +184,19 @@ static ssize_t at24_eeprom_read(struct at24_data *at24, char *buf,
184 if (count > io_limit) 184 if (count > io_limit)
185 count = io_limit; 185 count = io_limit;
186 186
187 if (at24->use_smbus) { 187 switch (at24->use_smbus) {
188 case I2C_SMBUS_I2C_BLOCK_DATA:
188 /* Smaller eeproms can work given some SMBus extension calls */ 189 /* Smaller eeproms can work given some SMBus extension calls */
189 if (count > I2C_SMBUS_BLOCK_MAX) 190 if (count > I2C_SMBUS_BLOCK_MAX)
190 count = I2C_SMBUS_BLOCK_MAX; 191 count = I2C_SMBUS_BLOCK_MAX;
191 } else { 192 break;
193 case I2C_SMBUS_WORD_DATA:
194 count = 2;
195 break;
196 case I2C_SMBUS_BYTE_DATA:
197 count = 1;
198 break;
199 default:
192 /* 200 /*
193 * When we have a better choice than SMBus calls, use a 201 * When we have a better choice than SMBus calls, use a
194 * combined I2C message. Write address; then read up to 202 * combined I2C message. Write address; then read up to
@@ -219,10 +227,27 @@ static ssize_t at24_eeprom_read(struct at24_data *at24, char *buf,
219 timeout = jiffies + msecs_to_jiffies(write_timeout); 227 timeout = jiffies + msecs_to_jiffies(write_timeout);
220 do { 228 do {
221 read_time = jiffies; 229 read_time = jiffies;
222 if (at24->use_smbus) { 230 switch (at24->use_smbus) {
231 case I2C_SMBUS_I2C_BLOCK_DATA:
223 status = i2c_smbus_read_i2c_block_data(client, offset, 232 status = i2c_smbus_read_i2c_block_data(client, offset,
224 count, buf); 233 count, buf);
225 } else { 234 break;
235 case I2C_SMBUS_WORD_DATA:
236 status = i2c_smbus_read_word_data(client, offset);
237 if (status >= 0) {
238 buf[0] = status & 0xff;
239 buf[1] = status >> 8;
240 status = count;
241 }
242 break;
243 case I2C_SMBUS_BYTE_DATA:
244 status = i2c_smbus_read_byte_data(client, offset);
245 if (status >= 0) {
246 buf[0] = status;
247 status = count;
248 }
249 break;
250 default:
226 status = i2c_transfer(client->adapter, msg, 2); 251 status = i2c_transfer(client->adapter, msg, 2);
227 if (status == 2) 252 if (status == 2)
228 status = count; 253 status = count;
@@ -274,7 +299,8 @@ static ssize_t at24_read(struct at24_data *at24,
274 return retval; 299 return retval;
275} 300}
276 301
277static ssize_t at24_bin_read(struct kobject *kobj, struct bin_attribute *attr, 302static ssize_t at24_bin_read(struct file *filp, struct kobject *kobj,
303 struct bin_attribute *attr,
278 char *buf, loff_t off, size_t count) 304 char *buf, loff_t off, size_t count)
279{ 305{
280 struct at24_data *at24; 306 struct at24_data *at24;
@@ -395,7 +421,8 @@ static ssize_t at24_write(struct at24_data *at24, const char *buf, loff_t off,
395 return retval; 421 return retval;
396} 422}
397 423
398static ssize_t at24_bin_write(struct kobject *kobj, struct bin_attribute *attr, 424static ssize_t at24_bin_write(struct file *filp, struct kobject *kobj,
425 struct bin_attribute *attr,
399 char *buf, loff_t off, size_t count) 426 char *buf, loff_t off, size_t count)
400{ 427{
401 struct at24_data *at24; 428 struct at24_data *at24;
@@ -434,7 +461,7 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id)
434{ 461{
435 struct at24_platform_data chip; 462 struct at24_platform_data chip;
436 bool writable; 463 bool writable;
437 bool use_smbus = false; 464 int use_smbus = 0;
438 struct at24_data *at24; 465 struct at24_data *at24;
439 int err; 466 int err;
440 unsigned i, num_addresses; 467 unsigned i, num_addresses;
@@ -475,12 +502,19 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id)
475 err = -EPFNOSUPPORT; 502 err = -EPFNOSUPPORT;
476 goto err_out; 503 goto err_out;
477 } 504 }
478 if (!i2c_check_functionality(client->adapter, 505 if (i2c_check_functionality(client->adapter,
479 I2C_FUNC_SMBUS_READ_I2C_BLOCK)) { 506 I2C_FUNC_SMBUS_READ_I2C_BLOCK)) {
507 use_smbus = I2C_SMBUS_I2C_BLOCK_DATA;
508 } else if (i2c_check_functionality(client->adapter,
509 I2C_FUNC_SMBUS_READ_WORD_DATA)) {
510 use_smbus = I2C_SMBUS_WORD_DATA;
511 } else if (i2c_check_functionality(client->adapter,
512 I2C_FUNC_SMBUS_READ_BYTE_DATA)) {
513 use_smbus = I2C_SMBUS_BYTE_DATA;
514 } else {
480 err = -EPFNOSUPPORT; 515 err = -EPFNOSUPPORT;
481 goto err_out; 516 goto err_out;
482 } 517 }
483 use_smbus = true;
484 } 518 }
485 519
486 if (chip.flags & AT24_FLAG_TAKE8ADDR) 520 if (chip.flags & AT24_FLAG_TAKE8ADDR)
@@ -566,11 +600,16 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id)
566 dev_info(&client->dev, "%zu byte %s EEPROM %s\n", 600 dev_info(&client->dev, "%zu byte %s EEPROM %s\n",
567 at24->bin.size, client->name, 601 at24->bin.size, client->name,
568 writable ? "(writable)" : "(read-only)"); 602 writable ? "(writable)" : "(read-only)");
603 if (use_smbus == I2C_SMBUS_WORD_DATA ||
604 use_smbus == I2C_SMBUS_BYTE_DATA) {
605 dev_notice(&client->dev, "Falling back to %s reads, "
606 "performance will suffer\n", use_smbus ==
607 I2C_SMBUS_WORD_DATA ? "word" : "byte");
608 }
569 dev_dbg(&client->dev, 609 dev_dbg(&client->dev,
570 "page_size %d, num_addresses %d, write_max %d%s\n", 610 "page_size %d, num_addresses %d, write_max %d, use_smbus %d\n",
571 chip.page_size, num_addresses, 611 chip.page_size, num_addresses,
572 at24->write_max, 612 at24->write_max, use_smbus);
573 use_smbus ? ", use_smbus" : "");
574 613
575 /* export data to kernel code */ 614 /* export data to kernel code */
576 if (chip.setup) 615 if (chip.setup)
diff --git a/drivers/misc/eeprom/at25.c b/drivers/misc/eeprom/at25.c
index d194212a41f6..c627e4174ccd 100644
--- a/drivers/misc/eeprom/at25.c
+++ b/drivers/misc/eeprom/at25.c
@@ -126,7 +126,8 @@ at25_ee_read(
126} 126}
127 127
128static ssize_t 128static ssize_t
129at25_bin_read(struct kobject *kobj, struct bin_attribute *bin_attr, 129at25_bin_read(struct file *filp, struct kobject *kobj,
130 struct bin_attribute *bin_attr,
130 char *buf, loff_t off, size_t count) 131 char *buf, loff_t off, size_t count)
131{ 132{
132 struct device *dev; 133 struct device *dev;
@@ -253,7 +254,8 @@ at25_ee_write(struct at25_data *at25, const char *buf, loff_t off,
253} 254}
254 255
255static ssize_t 256static ssize_t
256at25_bin_write(struct kobject *kobj, struct bin_attribute *bin_attr, 257at25_bin_write(struct file *filp, struct kobject *kobj,
258 struct bin_attribute *bin_attr,
257 char *buf, loff_t off, size_t count) 259 char *buf, loff_t off, size_t count)
258{ 260{
259 struct device *dev; 261 struct device *dev;
diff --git a/drivers/misc/eeprom/eeprom.c b/drivers/misc/eeprom/eeprom.c
index e306a8cd2f96..45060ddc4e59 100644
--- a/drivers/misc/eeprom/eeprom.c
+++ b/drivers/misc/eeprom/eeprom.c
@@ -81,7 +81,8 @@ exit:
81 mutex_unlock(&data->update_lock); 81 mutex_unlock(&data->update_lock);
82} 82}
83 83
84static ssize_t eeprom_read(struct kobject *kobj, struct bin_attribute *bin_attr, 84static ssize_t eeprom_read(struct file *filp, struct kobject *kobj,
85 struct bin_attribute *bin_attr,
85 char *buf, loff_t off, size_t count) 86 char *buf, loff_t off, size_t count)
86{ 87{
87 struct i2c_client *client = to_i2c_client(container_of(kobj, struct device, kobj)); 88 struct i2c_client *client = to_i2c_client(container_of(kobj, struct device, kobj));
diff --git a/drivers/misc/eeprom/max6875.c b/drivers/misc/eeprom/max6875.c
index fe2909278507..5653a3ce0517 100644
--- a/drivers/misc/eeprom/max6875.c
+++ b/drivers/misc/eeprom/max6875.c
@@ -107,7 +107,7 @@ exit_up:
107 mutex_unlock(&data->update_lock); 107 mutex_unlock(&data->update_lock);
108} 108}
109 109
110static ssize_t max6875_read(struct kobject *kobj, 110static ssize_t max6875_read(struct file *filp, struct kobject *kobj,
111 struct bin_attribute *bin_attr, 111 struct bin_attribute *bin_attr,
112 char *buf, loff_t off, size_t count) 112 char *buf, loff_t off, size_t count)
113{ 113{
diff --git a/drivers/misc/hdpuftrs/Makefile b/drivers/misc/hdpuftrs/Makefile
deleted file mode 100644
index ac74ae679230..000000000000
--- a/drivers/misc/hdpuftrs/Makefile
+++ /dev/null
@@ -1 +0,0 @@
1obj-$(CONFIG_HDPU_FEATURES) := hdpu_cpustate.o hdpu_nexus.o
diff --git a/drivers/misc/hdpuftrs/hdpu_cpustate.c b/drivers/misc/hdpuftrs/hdpu_cpustate.c
deleted file mode 100644
index 176fe4e09d3f..000000000000
--- a/drivers/misc/hdpuftrs/hdpu_cpustate.c
+++ /dev/null
@@ -1,256 +0,0 @@
1/*
2 * Sky CPU State Driver
3 *
4 * Copyright (C) 2002 Brian Waite
5 *
6 * This driver allows use of the CPU state bits
7 * It exports the /dev/sky_cpustate and also
8 * /proc/sky_cpustate pseudo-file for status information.
9 *
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version
13 * 2 of the License, or (at your option) any later version.
14 *
15 */
16
17#include <linux/module.h>
18#include <linux/kernel.h>
19#include <linux/spinlock.h>
20#include <linux/smp_lock.h>
21#include <linux/miscdevice.h>
22#include <linux/proc_fs.h>
23#include <linux/hdpu_features.h>
24#include <linux/platform_device.h>
25#include <asm/uaccess.h>
26#include <linux/seq_file.h>
27#include <asm/io.h>
28
29#define SKY_CPUSTATE_VERSION "1.1"
30
31static int hdpu_cpustate_probe(struct platform_device *pdev);
32static int hdpu_cpustate_remove(struct platform_device *pdev);
33
34static unsigned char cpustate_get_state(void);
35static int cpustate_proc_open(struct inode *inode, struct file *file);
36static int cpustate_proc_read(struct seq_file *seq, void *offset);
37
38static struct cpustate_t cpustate;
39
40static const struct file_operations proc_cpustate = {
41 .open = cpustate_proc_open,
42 .read = seq_read,
43 .llseek = seq_lseek,
44 .release = single_release,
45 .owner = THIS_MODULE,
46};
47
48static int cpustate_proc_open(struct inode *inode, struct file *file)
49{
50 return single_open(file, cpustate_proc_read, NULL);
51}
52
53static int cpustate_proc_read(struct seq_file *seq, void *offset)
54{
55 seq_printf(seq, "CPU State: %04x\n", cpustate_get_state());
56 return 0;
57}
58
59static int cpustate_get_ref(int excl)
60{
61
62 int retval = -EBUSY;
63
64 spin_lock(&cpustate.lock);
65
66 if (cpustate.excl)
67 goto out_busy;
68
69 if (excl) {
70 if (cpustate.open_count)
71 goto out_busy;
72 cpustate.excl = 1;
73 }
74
75 cpustate.open_count++;
76 retval = 0;
77
78 out_busy:
79 spin_unlock(&cpustate.lock);
80 return retval;
81}
82
83static int cpustate_free_ref(void)
84{
85
86 spin_lock(&cpustate.lock);
87
88 cpustate.excl = 0;
89 cpustate.open_count--;
90
91 spin_unlock(&cpustate.lock);
92 return 0;
93}
94
95static unsigned char cpustate_get_state(void)
96{
97
98 return cpustate.cached_val;
99}
100
101static void cpustate_set_state(unsigned char new_state)
102{
103 unsigned int state = (new_state << 21);
104
105#ifdef DEBUG_CPUSTATE
106 printk("CPUSTATE -> 0x%x\n", new_state);
107#endif
108 spin_lock(&cpustate.lock);
109 cpustate.cached_val = new_state;
110 writel((0xff << 21), cpustate.clr_addr);
111 writel(state, cpustate.set_addr);
112 spin_unlock(&cpustate.lock);
113}
114
115/*
116 * Now all the various file operations that we export.
117 */
118
119static ssize_t cpustate_read(struct file *file, char *buf,
120 size_t count, loff_t * ppos)
121{
122 unsigned char data;
123
124 if (count < 0)
125 return -EFAULT;
126 if (count == 0)
127 return 0;
128
129 data = cpustate_get_state();
130 if (copy_to_user(buf, &data, sizeof(unsigned char)))
131 return -EFAULT;
132 return sizeof(unsigned char);
133}
134
135static ssize_t cpustate_write(struct file *file, const char *buf,
136 size_t count, loff_t * ppos)
137{
138 unsigned char data;
139
140 if (count < 0)
141 return -EFAULT;
142
143 if (count == 0)
144 return 0;
145
146 if (copy_from_user((unsigned char *)&data, buf, sizeof(unsigned char)))
147 return -EFAULT;
148
149 cpustate_set_state(data);
150 return sizeof(unsigned char);
151}
152
153static int cpustate_open(struct inode *inode, struct file *file)
154{
155 int ret;
156
157 lock_kernel();
158 ret = cpustate_get_ref((file->f_flags & O_EXCL));
159 unlock_kernel();
160
161 return ret;
162}
163
164static int cpustate_release(struct inode *inode, struct file *file)
165{
166 return cpustate_free_ref();
167}
168
169static struct platform_driver hdpu_cpustate_driver = {
170 .probe = hdpu_cpustate_probe,
171 .remove = hdpu_cpustate_remove,
172 .driver = {
173 .name = HDPU_CPUSTATE_NAME,
174 .owner = THIS_MODULE,
175 },
176};
177
178/*
179 * The various file operations we support.
180 */
181static const struct file_operations cpustate_fops = {
182 .owner = THIS_MODULE,
183 .open = cpustate_open,
184 .release = cpustate_release,
185 .read = cpustate_read,
186 .write = cpustate_write,
187 .llseek = no_llseek,
188};
189
190static struct miscdevice cpustate_dev = {
191 .minor = MISC_DYNAMIC_MINOR,
192 .name = "sky_cpustate",
193 .fops = &cpustate_fops,
194};
195
196static int hdpu_cpustate_probe(struct platform_device *pdev)
197{
198 struct resource *res;
199 struct proc_dir_entry *proc_de;
200 int ret;
201
202 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
203 if (!res) {
204 printk(KERN_ERR "sky_cpustate: "
205 "Invalid memory resource.\n");
206 return -EINVAL;
207 }
208 cpustate.set_addr = (unsigned long *)res->start;
209 cpustate.clr_addr = (unsigned long *)res->end - 1;
210
211 ret = misc_register(&cpustate_dev);
212 if (ret) {
213 printk(KERN_WARNING "sky_cpustate: "
214 "Unable to register misc device.\n");
215 cpustate.set_addr = NULL;
216 cpustate.clr_addr = NULL;
217 return ret;
218 }
219
220 proc_de = proc_create("sky_cpustate", 0666, NULL, &proc_cpustate);
221 if (!proc_de) {
222 printk(KERN_WARNING "sky_cpustate: "
223 "Unable to create proc entry\n");
224 }
225
226 printk(KERN_INFO "Sky CPU State Driver v" SKY_CPUSTATE_VERSION "\n");
227 return 0;
228}
229
230static int hdpu_cpustate_remove(struct platform_device *pdev)
231{
232 cpustate.set_addr = NULL;
233 cpustate.clr_addr = NULL;
234
235 remove_proc_entry("sky_cpustate", NULL);
236 misc_deregister(&cpustate_dev);
237
238 return 0;
239}
240
241static int __init cpustate_init(void)
242{
243 return platform_driver_register(&hdpu_cpustate_driver);
244}
245
246static void __exit cpustate_exit(void)
247{
248 platform_driver_unregister(&hdpu_cpustate_driver);
249}
250
251module_init(cpustate_init);
252module_exit(cpustate_exit);
253
254MODULE_AUTHOR("Brian Waite");
255MODULE_LICENSE("GPL");
256MODULE_ALIAS("platform:" HDPU_CPUSTATE_NAME);
diff --git a/drivers/misc/hdpuftrs/hdpu_nexus.c b/drivers/misc/hdpuftrs/hdpu_nexus.c
deleted file mode 100644
index ce39fa54949b..000000000000
--- a/drivers/misc/hdpuftrs/hdpu_nexus.c
+++ /dev/null
@@ -1,149 +0,0 @@
1/*
2 * Sky Nexus Register Driver
3 *
4 * Copyright (C) 2002 Brian Waite
5 *
6 * This driver allows reading the Nexus register
7 * It exports the /proc/sky_chassis_id and also
8 * /proc/sky_slot_id pseudo-file for status information.
9 *
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version
13 * 2 of the License, or (at your option) any later version.
14 *
15 */
16
17#include <linux/module.h>
18#include <linux/kernel.h>
19#include <linux/proc_fs.h>
20#include <linux/hdpu_features.h>
21#include <linux/platform_device.h>
22#include <linux/seq_file.h>
23#include <asm/io.h>
24
25static int hdpu_nexus_probe(struct platform_device *pdev);
26static int hdpu_nexus_remove(struct platform_device *pdev);
27static int hdpu_slot_id_open(struct inode *inode, struct file *file);
28static int hdpu_slot_id_read(struct seq_file *seq, void *offset);
29static int hdpu_chassis_id_open(struct inode *inode, struct file *file);
30static int hdpu_chassis_id_read(struct seq_file *seq, void *offset);
31
32static struct proc_dir_entry *hdpu_slot_id;
33static struct proc_dir_entry *hdpu_chassis_id;
34static int slot_id = -1;
35static int chassis_id = -1;
36
37static const struct file_operations proc_slot_id = {
38 .open = hdpu_slot_id_open,
39 .read = seq_read,
40 .llseek = seq_lseek,
41 .release = single_release,
42 .owner = THIS_MODULE,
43};
44
45static const struct file_operations proc_chassis_id = {
46 .open = hdpu_chassis_id_open,
47 .read = seq_read,
48 .llseek = seq_lseek,
49 .release = single_release,
50 .owner = THIS_MODULE,
51};
52
53static struct platform_driver hdpu_nexus_driver = {
54 .probe = hdpu_nexus_probe,
55 .remove = hdpu_nexus_remove,
56 .driver = {
57 .name = HDPU_NEXUS_NAME,
58 .owner = THIS_MODULE,
59 },
60};
61
62static int hdpu_slot_id_open(struct inode *inode, struct file *file)
63{
64 return single_open(file, hdpu_slot_id_read, NULL);
65}
66
67static int hdpu_slot_id_read(struct seq_file *seq, void *offset)
68{
69 seq_printf(seq, "%d\n", slot_id);
70 return 0;
71}
72
73static int hdpu_chassis_id_open(struct inode *inode, struct file *file)
74{
75 return single_open(file, hdpu_chassis_id_read, NULL);
76}
77
78static int hdpu_chassis_id_read(struct seq_file *seq, void *offset)
79{
80 seq_printf(seq, "%d\n", chassis_id);
81 return 0;
82}
83
84static int hdpu_nexus_probe(struct platform_device *pdev)
85{
86 struct resource *res;
87 int *nexus_id_addr;
88
89 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
90 if (!res) {
91 printk(KERN_ERR "sky_nexus: "
92 "Invalid memory resource.\n");
93 return -EINVAL;
94 }
95 nexus_id_addr = ioremap(res->start,
96 (unsigned long)(res->end - res->start));
97 if (nexus_id_addr) {
98 slot_id = (*nexus_id_addr >> 8) & 0x1f;
99 chassis_id = *nexus_id_addr & 0xff;
100 iounmap(nexus_id_addr);
101 } else {
102 printk(KERN_ERR "sky_nexus: Could not map slot id\n");
103 }
104
105 hdpu_slot_id = proc_create("sky_slot_id", 0666, NULL, &proc_slot_id);
106 if (!hdpu_slot_id) {
107 printk(KERN_WARNING "sky_nexus: "
108 "Unable to create proc dir entry: sky_slot_id\n");
109 }
110
111 hdpu_chassis_id = proc_create("sky_chassis_id", 0666, NULL,
112 &proc_chassis_id);
113 if (!hdpu_chassis_id)
114 printk(KERN_WARNING "sky_nexus: "
115 "Unable to create proc dir entry: sky_chassis_id\n");
116
117 return 0;
118}
119
120static int hdpu_nexus_remove(struct platform_device *pdev)
121{
122 slot_id = -1;
123 chassis_id = -1;
124
125 remove_proc_entry("sky_slot_id", NULL);
126 remove_proc_entry("sky_chassis_id", NULL);
127
128 hdpu_slot_id = 0;
129 hdpu_chassis_id = 0;
130
131 return 0;
132}
133
134static int __init nexus_init(void)
135{
136 return platform_driver_register(&hdpu_nexus_driver);
137}
138
139static void __exit nexus_exit(void)
140{
141 platform_driver_unregister(&hdpu_nexus_driver);
142}
143
144module_init(nexus_init);
145module_exit(nexus_exit);
146
147MODULE_AUTHOR("Brian Waite");
148MODULE_LICENSE("GPL");
149MODULE_ALIAS("platform:" HDPU_NEXUS_NAME);
diff --git a/drivers/misc/lkdtm.c b/drivers/misc/lkdtm.c
index 31a991161f0a..5bfb2a2041b8 100644
--- a/drivers/misc/lkdtm.c
+++ b/drivers/misc/lkdtm.c
@@ -75,6 +75,9 @@ enum ctype {
75 UNALIGNED_LOAD_STORE_WRITE, 75 UNALIGNED_LOAD_STORE_WRITE,
76 OVERWRITE_ALLOCATION, 76 OVERWRITE_ALLOCATION,
77 WRITE_AFTER_FREE, 77 WRITE_AFTER_FREE,
78 SOFTLOCKUP,
79 HARDLOCKUP,
80 HUNG_TASK,
78}; 81};
79 82
80static char* cp_name[] = { 83static char* cp_name[] = {
@@ -99,6 +102,9 @@ static char* cp_type[] = {
99 "UNALIGNED_LOAD_STORE_WRITE", 102 "UNALIGNED_LOAD_STORE_WRITE",
100 "OVERWRITE_ALLOCATION", 103 "OVERWRITE_ALLOCATION",
101 "WRITE_AFTER_FREE", 104 "WRITE_AFTER_FREE",
105 "SOFTLOCKUP",
106 "HARDLOCKUP",
107 "HUNG_TASK",
102}; 108};
103 109
104static struct jprobe lkdtm; 110static struct jprobe lkdtm;
@@ -320,6 +326,20 @@ static void lkdtm_do_action(enum ctype which)
320 memset(data, 0x78, len); 326 memset(data, 0x78, len);
321 break; 327 break;
322 } 328 }
329 case SOFTLOCKUP:
330 preempt_disable();
331 for (;;)
332 cpu_relax();
333 break;
334 case HARDLOCKUP:
335 local_irq_disable();
336 for (;;)
337 cpu_relax();
338 break;
339 case HUNG_TASK:
340 set_current_state(TASK_UNINTERRUPTIBLE);
341 schedule();
342 break;
323 case NONE: 343 case NONE:
324 default: 344 default:
325 break; 345 break;