aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/misc
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/misc')
-rw-r--r--drivers/misc/Kconfig6
-rw-r--r--drivers/misc/Makefile1
-rw-r--r--drivers/misc/asus-laptop.c3
-rw-r--r--drivers/misc/eeprom_93cx6.c241
-rw-r--r--drivers/misc/msi-laptop.c44
5 files changed, 289 insertions, 6 deletions
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 616eee9c04f1..bd601efa7bd1 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -34,6 +34,11 @@ config PHANTOM
34 If you choose to build module, its name will be phantom. If unsure, 34 If you choose to build module, its name will be phantom. If unsure,
35 say N here. 35 say N here.
36 36
37config EEPROM_93CX6
38 tristate "EEPROM 93CX6 support"
39 ---help---
40 This is a driver for the EEPROM chipsets 93c46 and 93c66.
41 The driver supports both read as well as write commands.
37 42
38 If unsure, say N. 43 If unsure, say N.
39 44
@@ -187,5 +192,4 @@ config THINKPAD_ACPI_BAY
187 192
188 If you are not sure, say Y here. 193 If you are not sure, say Y here.
189 194
190
191endmenu 195endmenu
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index 8abbf2f07a65..b5ce0e3dba86 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -14,3 +14,4 @@ obj-$(CONFIG_PHANTOM) += phantom.o
14obj-$(CONFIG_SGI_IOC4) += ioc4.o 14obj-$(CONFIG_SGI_IOC4) += ioc4.o
15obj-$(CONFIG_SONY_LAPTOP) += sony-laptop.o 15obj-$(CONFIG_SONY_LAPTOP) += sony-laptop.o
16obj-$(CONFIG_THINKPAD_ACPI) += thinkpad_acpi.o 16obj-$(CONFIG_THINKPAD_ACPI) += thinkpad_acpi.o
17obj-$(CONFIG_EEPROM_93CX6) += eeprom_93cx6.o
diff --git a/drivers/misc/asus-laptop.c b/drivers/misc/asus-laptop.c
index 4f9060a2a2f2..7798f590e5aa 100644
--- a/drivers/misc/asus-laptop.c
+++ b/drivers/misc/asus-laptop.c
@@ -737,8 +737,7 @@ static void asus_hotk_notify(acpi_handle handle, u32 event, void *data)
737 struct device_attribute dev_attr_##_name = { \ 737 struct device_attribute dev_attr_##_name = { \
738 .attr = { \ 738 .attr = { \
739 .name = __stringify(_name), \ 739 .name = __stringify(_name), \
740 .mode = 0, \ 740 .mode = 0 }, \
741 .owner = THIS_MODULE }, \
742 .show = NULL, \ 741 .show = NULL, \
743 .store = NULL, \ 742 .store = NULL, \
744 } 743 }
diff --git a/drivers/misc/eeprom_93cx6.c b/drivers/misc/eeprom_93cx6.c
new file mode 100644
index 000000000000..ea55654e5948
--- /dev/null
+++ b/drivers/misc/eeprom_93cx6.c
@@ -0,0 +1,241 @@
1/*
2 Copyright (C) 2004 - 2006 rt2x00 SourceForge Project
3 <http://rt2x00.serialmonkey.com>
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the
17 Free Software Foundation, Inc.,
18 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 */
20
21/*
22 Module: eeprom_93cx6
23 Abstract: EEPROM reader routines for 93cx6 chipsets.
24 Supported chipsets: 93c46 & 93c66.
25 */
26
27#include <linux/kernel.h>
28#include <linux/module.h>
29#include <linux/version.h>
30#include <linux/delay.h>
31#include <linux/eeprom_93cx6.h>
32
33MODULE_AUTHOR("http://rt2x00.serialmonkey.com");
34MODULE_VERSION("1.0");
35MODULE_DESCRIPTION("EEPROM 93cx6 chip driver");
36MODULE_LICENSE("GPL");
37
38static inline void eeprom_93cx6_pulse_high(struct eeprom_93cx6 *eeprom)
39{
40 eeprom->reg_data_clock = 1;
41 eeprom->register_write(eeprom);
42
43 /*
44 * Add a short delay for the pulse to work.
45 * According to the specifications the "maximum minimum"
46 * time should be 450ns.
47 */
48 ndelay(450);
49}
50
51static inline void eeprom_93cx6_pulse_low(struct eeprom_93cx6 *eeprom)
52{
53 eeprom->reg_data_clock = 0;
54 eeprom->register_write(eeprom);
55
56 /*
57 * Add a short delay for the pulse to work.
58 * According to the specifications the "maximum minimum"
59 * time should be 450ns.
60 */
61 ndelay(450);
62}
63
64static void eeprom_93cx6_startup(struct eeprom_93cx6 *eeprom)
65{
66 /*
67 * Clear all flags, and enable chip select.
68 */
69 eeprom->register_read(eeprom);
70 eeprom->reg_data_in = 0;
71 eeprom->reg_data_out = 0;
72 eeprom->reg_data_clock = 0;
73 eeprom->reg_chip_select = 1;
74 eeprom->register_write(eeprom);
75
76 /*
77 * kick a pulse.
78 */
79 eeprom_93cx6_pulse_high(eeprom);
80 eeprom_93cx6_pulse_low(eeprom);
81}
82
83static void eeprom_93cx6_cleanup(struct eeprom_93cx6 *eeprom)
84{
85 /*
86 * Clear chip_select and data_in flags.
87 */
88 eeprom->register_read(eeprom);
89 eeprom->reg_data_in = 0;
90 eeprom->reg_chip_select = 0;
91 eeprom->register_write(eeprom);
92
93 /*
94 * kick a pulse.
95 */
96 eeprom_93cx6_pulse_high(eeprom);
97 eeprom_93cx6_pulse_low(eeprom);
98}
99
100static void eeprom_93cx6_write_bits(struct eeprom_93cx6 *eeprom,
101 const u16 data, const u16 count)
102{
103 unsigned int i;
104
105 eeprom->register_read(eeprom);
106
107 /*
108 * Clear data flags.
109 */
110 eeprom->reg_data_in = 0;
111 eeprom->reg_data_out = 0;
112
113 /*
114 * Start writing all bits.
115 */
116 for (i = count; i > 0; i--) {
117 /*
118 * Check if this bit needs to be set.
119 */
120 eeprom->reg_data_in = !!(data & (1 << (i - 1)));
121
122 /*
123 * Write the bit to the eeprom register.
124 */
125 eeprom->register_write(eeprom);
126
127 /*
128 * Kick a pulse.
129 */
130 eeprom_93cx6_pulse_high(eeprom);
131 eeprom_93cx6_pulse_low(eeprom);
132 }
133
134 eeprom->reg_data_in = 0;
135 eeprom->register_write(eeprom);
136}
137
138static void eeprom_93cx6_read_bits(struct eeprom_93cx6 *eeprom,
139 u16 *data, const u16 count)
140{
141 unsigned int i;
142 u16 buf = 0;
143
144 eeprom->register_read(eeprom);
145
146 /*
147 * Clear data flags.
148 */
149 eeprom->reg_data_in = 0;
150 eeprom->reg_data_out = 0;
151
152 /*
153 * Start reading all bits.
154 */
155 for (i = count; i > 0; i--) {
156 eeprom_93cx6_pulse_high(eeprom);
157
158 eeprom->register_read(eeprom);
159
160 /*
161 * Clear data_in flag.
162 */
163 eeprom->reg_data_in = 0;
164
165 /*
166 * Read if the bit has been set.
167 */
168 if (eeprom->reg_data_out)
169 buf |= (1 << (i - 1));
170
171 eeprom_93cx6_pulse_low(eeprom);
172 }
173
174 *data = buf;
175}
176
177/**
178 * eeprom_93cx6_read - Read multiple words from eeprom
179 * @eeprom: Pointer to eeprom structure
180 * @word: Word index from where we should start reading
181 * @data: target pointer where the information will have to be stored
182 *
183 * This function will read the eeprom data as host-endian word
184 * into the given data pointer.
185 */
186void eeprom_93cx6_read(struct eeprom_93cx6 *eeprom, const u8 word,
187 u16 *data)
188{
189 u16 command;
190
191 /*
192 * Initialize the eeprom register
193 */
194 eeprom_93cx6_startup(eeprom);
195
196 /*
197 * Select the read opcode and the word to be read.
198 */
199 command = (PCI_EEPROM_READ_OPCODE << eeprom->width) | word;
200 eeprom_93cx6_write_bits(eeprom, command,
201 PCI_EEPROM_WIDTH_OPCODE + eeprom->width);
202
203 /*
204 * Read the requested 16 bits.
205 */
206 eeprom_93cx6_read_bits(eeprom, data, 16);
207
208 /*
209 * Cleanup eeprom register.
210 */
211 eeprom_93cx6_cleanup(eeprom);
212}
213EXPORT_SYMBOL_GPL(eeprom_93cx6_read);
214
215/**
216 * eeprom_93cx6_multiread - Read multiple words from eeprom
217 * @eeprom: Pointer to eeprom structure
218 * @word: Word index from where we should start reading
219 * @data: target pointer where the information will have to be stored
220 * @words: Number of words that should be read.
221 *
222 * This function will read all requested words from the eeprom,
223 * this is done by calling eeprom_93cx6_read() multiple times.
224 * But with the additional change that while the eeprom_93cx6_read
225 * will return host ordered bytes, this method will return little
226 * endian words.
227 */
228void eeprom_93cx6_multiread(struct eeprom_93cx6 *eeprom, const u8 word,
229 __le16 *data, const u16 words)
230{
231 unsigned int i;
232 u16 tmp;
233
234 for (i = 0; i < words; i++) {
235 tmp = 0;
236 eeprom_93cx6_read(eeprom, word + i, &tmp);
237 data[i] = cpu_to_le16(tmp);
238 }
239}
240EXPORT_SYMBOL_GPL(eeprom_93cx6_multiread);
241
diff --git a/drivers/misc/msi-laptop.c b/drivers/misc/msi-laptop.c
index 41e901f53e7c..932a415197b3 100644
--- a/drivers/misc/msi-laptop.c
+++ b/drivers/misc/msi-laptop.c
@@ -23,6 +23,8 @@
23 * msi-laptop.c - MSI S270 laptop support. This laptop is sold under 23 * msi-laptop.c - MSI S270 laptop support. This laptop is sold under
24 * various brands, including "Cytron/TCM/Medion/Tchibo MD96100". 24 * various brands, including "Cytron/TCM/Medion/Tchibo MD96100".
25 * 25 *
26 * Driver also supports S271, S420 models.
27 *
26 * This driver exports a few files in /sys/devices/platform/msi-laptop-pf/: 28 * This driver exports a few files in /sys/devices/platform/msi-laptop-pf/:
27 * 29 *
28 * lcd_level - Screen brightness: contains a single integer in the 30 * lcd_level - Screen brightness: contains a single integer in the
@@ -281,25 +283,56 @@ static struct platform_device *msipf_device;
281 283
282/* Initialization */ 284/* Initialization */
283 285
286static int dmi_check_cb(struct dmi_system_id *id)
287{
288 printk("msi-laptop: Identified laptop model '%s'.\n", id->ident);
289 return 0;
290}
291
284static struct dmi_system_id __initdata msi_dmi_table[] = { 292static struct dmi_system_id __initdata msi_dmi_table[] = {
285 { 293 {
286 .ident = "MSI S270", 294 .ident = "MSI S270",
287 .matches = { 295 .matches = {
288 DMI_MATCH(DMI_SYS_VENDOR, "MICRO-STAR INT'L CO.,LTD"), 296 DMI_MATCH(DMI_SYS_VENDOR, "MICRO-STAR INT'L CO.,LTD"),
289 DMI_MATCH(DMI_PRODUCT_NAME, "MS-1013"), 297 DMI_MATCH(DMI_PRODUCT_NAME, "MS-1013"),
290 } 298 DMI_MATCH(DMI_PRODUCT_VERSION, "0131"),
299 DMI_MATCH(DMI_CHASSIS_VENDOR, "MICRO-STAR INT'L CO.,LTD")
300 },
301 .callback = dmi_check_cb
302 },
303 {
304 .ident = "MSI S271",
305 .matches = {
306 DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"),
307 DMI_MATCH(DMI_PRODUCT_NAME, "MS-1058"),
308 DMI_MATCH(DMI_PRODUCT_VERSION, "0581"),
309 DMI_MATCH(DMI_BOARD_NAME, "MS-1058")
310 },
311 .callback = dmi_check_cb
312 },
313 {
314 .ident = "MSI S420",
315 .matches = {
316 DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"),
317 DMI_MATCH(DMI_PRODUCT_NAME, "MS-1412"),
318 DMI_MATCH(DMI_BOARD_VENDOR, "MSI"),
319 DMI_MATCH(DMI_BOARD_NAME, "MS-1412")
320 },
321 .callback = dmi_check_cb
291 }, 322 },
292 { 323 {
293 .ident = "Medion MD96100", 324 .ident = "Medion MD96100",
294 .matches = { 325 .matches = {
295 DMI_MATCH(DMI_SYS_VENDOR, "NOTEBOOK"), 326 DMI_MATCH(DMI_SYS_VENDOR, "NOTEBOOK"),
296 DMI_MATCH(DMI_PRODUCT_NAME, "SAM2000"), 327 DMI_MATCH(DMI_PRODUCT_NAME, "SAM2000"),
297 } 328 DMI_MATCH(DMI_PRODUCT_VERSION, "0131"),
329 DMI_MATCH(DMI_CHASSIS_VENDOR, "MICRO-STAR INT'L CO.,LTD")
330 },
331 .callback = dmi_check_cb
298 }, 332 },
299 { } 333 { }
300}; 334};
301 335
302
303static int __init msi_init(void) 336static int __init msi_init(void)
304{ 337{
305 int ret; 338 int ret;
@@ -394,3 +427,8 @@ MODULE_AUTHOR("Lennart Poettering");
394MODULE_DESCRIPTION("MSI Laptop Support"); 427MODULE_DESCRIPTION("MSI Laptop Support");
395MODULE_VERSION(MSI_DRIVER_VERSION); 428MODULE_VERSION(MSI_DRIVER_VERSION);
396MODULE_LICENSE("GPL"); 429MODULE_LICENSE("GPL");
430
431MODULE_ALIAS("dmi:*:svnMICRO-STARINT'LCO.,LTD:pnMS-1013:pvr0131*:cvnMICRO-STARINT'LCO.,LTD:ct10:*");
432MODULE_ALIAS("dmi:*:svnMicro-StarInternational:pnMS-1058:pvr0581:rvnMSI:rnMS-1058:*:ct10:*");
433MODULE_ALIAS("dmi:*:svnMicro-StarInternational:pnMS-1412:*:rvnMSI:rnMS-1412:*:cvnMICRO-STARINT'LCO.,LTD:ct10:*");
434MODULE_ALIAS("dmi:*:svnNOTEBOOK:pnSAM2000:pvr0131*:cvnMICRO-STARINT'LCO.,LTD:ct10:*");