root/lm-sensors/trunk/prog/hotplug/m7101.c

Revision 3025, 9.7 kB (checked in by khali, 3 years ago)

Strip useless whitespace before new line at end of string.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1 /*
2  * m7101.c
3  *
4  * Initialize the M7101 device on ALi M15x3 Chipsets
5  */
6 /*
7     Copyright (c) 2000 Burkhard Kohl <buk@buks.ipn.de>,
8     Frank Bauer <frank.bauer@nikocity.de>, and
9     Mark D. Studebaker <mdsxyz123@yahoo.com>
10
11     This program is free software; you can redistribute it and/or modify
12     it under the terms of the GNU General Public License as published by
13     the Free Software Foundation; either version 2 of the License, or
14     (at your option) any later version.
15
16     This program is distributed in the hope that it will be useful,
17     but WITHOUT ANY WARRANTY; without even the implied warranty of
18     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19     GNU General Public License for more details.
20
21     You should have received a copy of the GNU General Public License
22     along with this program; if not, write to the Free Software
23     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24  */
25 /* CHANGES:
26  * 030799 FB: created this file
27  * frank.bauer@nikocity.de
28  *
29  * 110799 BK: messed it up to insert the M7101 dev after boot
30  * buk@buks.ipn.de
31  *
32  * 160799 BK: grouped portions of the code into functions
33  *
34  * June 21, 2000 MDS: Add Copyright and GPL comments,
35  *                    distribute as release 0.1.
36  *
37  * Sept 21, 2000 MDS: Rewrite to use kernel hotplug facility,
38  *                    (similar to drivers/pcmcia/cardbus.c),
39  *                    fix makefile so it will compile,
40  *                    distribute as release 0.2.
41  *
42  * This code is absolutely experimental - use it at your own
43  * risk.
44  *
45  * Warning, this module will work only with 2.4.x kernels.
46  * If it works with earlier kernels then it is by luck.
47  *
48  * Warning, this module does not work with egcs < 2.95.2, use
49  * gcc > 2.7.2 or egcs >= 2.95.2.
50  *
51  */
52
53
54 #ifdef M7101_DEBUG
55 #define DBG(x...) printk(x)
56 #else
57 #define DBG(x...)
58 #endif
59
60 #ifndef TRUE
61 #define TRUE 1
62 #define FALSE !TRUE
63 #endif
64
65 #include <linux/config.h>
66 #ifndef CONFIG_HOTPLUG
67 #error ERROR - You must have 'Support for hot-pluggable devices' enabled in your kernel (under 'general setup')!!
68 #endif
69
70 /* Deal with CONFIG_MODVERSIONS */
71 #ifdef CONFIG_MODVERSIONS
72 #define MODVERSIONS
73 #include <linux/modversions.h>
74 #endif
75
76 #include <linux/module.h>
77 #include <linux/kernel.h>
78 #include <linux/pci.h>
79 #include <linux/stddef.h>
80 #include <linux/ioport.h>
81 #include <linux/errno.h>
82 #include <linux/slab.h>
83 #include <asm/types.h>
84
85 /*
86     from lm_sensors-2.3.3:
87  */
88 #define SMBHSTCFG 0x0E0
89 /* PCI Address Constants */
90 #define SMBATPC   0x05B         /* used to unlock xxxBA registers */
91 /* ALI15X3 address lock bits */
92 #define ALI15X3_LOCK    0x06
93
94 /*
95    addresses the i/o space gets mapped to,
96    for M1543C, Bits 16-31 are supposed to be zero       
97  */
98 #define ACPI_IO_SIZE 0x40
99 #define SMB_IO_SIZE  0x20
100 #define ACPI_BASE 0x0
101 #define SMB_BASE 0x1
102 static u32 acpi_io = 0xEC00;    /* Set I/O Base defaults here */
103 static u32 smb_io  = 0xE800;
104 MODULE_PARM(acpi_io, "l");
105 MODULE_PARM(smb_io, "l");
106 #ifdef M7101_DEBUG
107 static int debug = 0;
108 MODULE_PARM(debug, "i");
109 #endif
110
111 /* status, used to indicate that io space needs to be freed */
112 static struct pci_dev *m7101 = NULL;
113 static int m7101_inserted = FALSE;
114 extern void cleanup_module();
115  
116 static rwlock_t m7101_lock = RW_LOCK_UNLOCKED;
117 static unsigned long m7101_lock_flags = 0;
118
119
120 #ifdef M7101_DEBUG
121 static void
122 dump_dev_data(struct pci_dev *dev, int address_data)
123 {
124     if (dev != NULL) {
125                 printk("m7101: devfn:  0x%4x   class:  0x%4x\n",
126                                 dev->devfn, dev->class);
127                 printk("m7101: vendor: 0x%4x   device: 0x%4x\n",
128                                 dev->vendor, dev->device);
129
130                 if (address_data) {
131                         printk("m7101: resource[0]: 0x%08lx   resource[1]: 0x%08lx\n",
132                                         dev->resource[0].start, dev->resource[1].start);
133                         printk("m7101: resource[2]: 0x%08lx   resource[3]: 0x%08lx\n",
134                                         dev->resource[2].start, dev->resource[3].start);
135                         printk("m7101: resource[4]: 0x%08lx   resource[5]: 0x%08lx\n",
136                                         dev->resource[4].start, dev->resource[5].start);
137                         printk("m7101: rom_address:     0x%08lx\n",
138                                         dev->resource[PCI_ROM_RESOURCE].start);
139                 }
140         }
141 }
142 #endif
143
144 /*
145  * Checks whether PMU and SMB are enabled and turns them on in case they are not.
146  * It's done by clearing Bit 2 in M1533 config space 5Fh.
147  * I/O
148  */
149 static int
150 m7101_enable(struct pci_dev *dev){
151         u8  val   = 0;
152
153         pci_read_config_byte(dev, 0x5F, &val);
154         DBG("m7101: M7101 config byte reading 0x%X.\n", val);
155         if (val & 0x4) {
156                 pci_write_config_byte(dev, 0x5F, val & 0xFB);
157                 pci_read_config_byte(dev, 0x5F, &val);
158                 if(val & 0x4) {
159                         DBG("m7101: Can't enable PMU/SMB, config byte locked:-(\n");
160                         return -EIO;
161                 }
162         }
163         return 0;
164
165 }
166
167 /*
168  * Builds the basic pci_dev for the M7101
169  */
170 static int
171 m7101_build(struct pci_dev **m7101, struct pci_bus *bus)
172 {
173         u32 devfn;
174         u16 id = 0;
175         u16 vid = 0;
176         int ret;
177
178         DBG("m7101: requesting kernel space for the m7101 entry.\n");
179         *m7101 = kmalloc(sizeof(**m7101), GFP_ATOMIC);
180         if(NULL == *m7101) {
181                 printk("m7101: out of memory.\n");
182                 return -ENOMEM;
183         }
184
185         /* minimally fill in structure for search */
186         /* The device should be on the same bus as the M1533. */
187         memset(*m7101, 0, sizeof(**m7101));
188         (*m7101)->bus    = bus;
189         (*m7101)->sysdata = bus->sysdata;
190         (*m7101)->hdr_type = PCI_HEADER_TYPE_NORMAL;
191
192         DBG("m7101: now looking for M7101.\n");
193         for  (id = 0, devfn = 0; devfn < 0xFF; devfn++) {
194                 (*m7101)->devfn = devfn;
195                 ret = pci_read_config_word(*m7101, PCI_DEVICE_ID, &id);
196                 if (ret == 0 && PCI_DEVICE_ID_AL_M7101 == id) {
197                         pci_read_config_word(*m7101, PCI_VENDOR_ID, &vid);
198                         if(vid == PCI_VENDOR_ID_AL)
199                                 break;
200                 }
201         }
202         if (PCI_DEVICE_ID_AL_M7101 != id) {     
203                 DBG("m7101: M7101 not found although M1533 present - strange.\n");
204                 return -EACCES;
205         } else {
206                 DBG("m7101: M7101 found and enabled. Devfn: 0x%X.\n", devfn);
207         }
208         /* We now have the devfn and bus of the M7101 device.
209          * let's put the rest of the device data together.
210          */
211
212         (*m7101)->vendor = PCI_VENDOR_ID_AL;
213         (*m7101)->hdr_type = PCI_HEADER_TYPE_NORMAL;
214         (*m7101)->device = PCI_DEVICE_ID_AL_M7101;
215         return(pci_setup_device(*m7101));
216 }
217
218 /*
219  * unlock the address registers if necessary
220  */
221 static int
222 m7101_unlock_registers(struct pci_dev *m7101)
223 {
224         u8 val = 0;
225
226         if (pci_read_config_byte(m7101, SMBATPC, &val))  {
227                 DBG("m7101: failed to read SMBATPC\n");
228                 return -EIO;
229         } else {
230                 if(val & ALI15X3_LOCK) {
231                         DBG("m7101: need to unlock the address registers\n");
232                         val &= ~ALI15X3_LOCK;
233                         if (pci_write_config_byte(m7101, SMBATPC, val)) {
234                                 DBG("m7101: failed to write SMBATPC\n");
235                                 return -EIO;
236                         }
237                 }
238         }
239
240         return 0;
241 }
242
243
244 static int
245 m7101_set_io_address(struct pci_dev *m7101, u32 addr, int base_idx, int size)
246 {
247         if (!addr) {
248                 printk("m7101: Sorry - cannot assign address 0 to region.\n");
249                 return -EINVAL;
250         }
251         if (check_region(addr, size)) {
252                 printk("m7101: Requested IO-region 0x%x already in use.\n", addr);
253                 return -EBUSY;
254         } else {
255                 m7101->resource[base_idx].start = addr;
256         }
257        
258         return 0;
259 }
260
261
262 /* Initialize the module */
263 int init_module(void)
264 {
265         struct pci_bus *bus = NULL;
266         struct pci_dev *dev = NULL;
267         u32 acpi_addr = 0, smb_addr = 0;
268         int ret = 0;
269
270         DBG("m7101: init_module().\n");
271
272         /* Are we on a PCI-Board? */
273         if (!pci_present()) {
274                 printk("m7101: No PCI bus found - sorry.\n");
275                 return -ENODEV;
276         }
277
278         /* We want to be sure that the M7101 is not present yet. */
279         dev = pci_find_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101, NULL);
280         if (dev) {
281                 printk("m7101: M7101 already present, no need to run this module.\n");
282 #ifdef M7101_DEBUG
283                 if(debug)
284                 {
285                         printk("m7101: removing device for testing\n");
286                         pci_remove_device(dev);
287                         m7101_inserted = 0;
288                         return 0;
289                 }
290                 else
291 #endif
292                         return -EPERM;
293         }
294        
295         /* Are we operating a M15x3 chipset */
296         dev = pci_find_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, NULL);
297         if (NULL == dev) {
298                 printk("m7101: ALi M15xx chipset not found.\n");
299                 return -ENODEV ;
300         }
301         /* we need the bus pointer later */
302         bus = dev->bus;
303
304         if ( (ret = m7101_enable(dev)) ) {
305                 printk("m7101: Unable to turn on M7101 device - sorry!\n");
306                 return ret;
307         }
308
309         if ( (ret = m7101_build(&m7101, bus)) ){
310                 return ret;
311         }
312
313         /* thus, now we have a rudimentary dev for M7101 ... */
314         /* check wether register need to be unlocked. */
315         if ( (ret = m7101_unlock_registers(m7101)) ){
316                 return ret;
317         }
318
319         /*
320          * Handle address assignment for ACPI_IO
321          * If address is already assigned do nothing.
322          */
323         acpi_addr = m7101->resource[ACPI_BASE].start;
324         if (!acpi_addr) {
325                 acpi_io |= PCI_BASE_ADDRESS_SPACE_IO;
326                 ret = m7101_set_io_address(m7101, acpi_io,ACPI_BASE, ACPI_IO_SIZE);
327                 if (ret)
328                         return ret;
329                 acpi_addr = acpi_io;
330         }
331
332         /*
333          * Handle address assignment for SMB_IO
334          * If address is already assigned then do nothing.
335          */
336         smb_addr = m7101->resource[SMB_BASE].start;
337         if (!smb_addr) {
338                 smb_io |= PCI_BASE_ADDRESS_SPACE_IO;
339                 ret = m7101_set_io_address(m7101, smb_io, SMB_BASE, SMB_IO_SIZE);
340                 if (ret)
341                         return ret;
342                 smb_addr = smb_io;
343         }
344
345 #ifdef M7101_DEBUG
346         dump_dev_data(m7101, 1);
347 #endif
348
349
350         if ( (ret = pci_enable_device(m7101)) ) {
351                 printk("m7101: Unable to pci_enable M7101 device!\n");
352                 return ret;
353         }
354
355         DBG("m7101: now inserting.\n");
356         pci_insert_device(m7101, m7101->bus);
357         printk("m7101: Enabled with ACPI I/O address 0x%04X and SMB I/O address 0x%04X\n",
358                 acpi_addr, smb_addr);
359         m7101_inserted = TRUE;
360
361         return 0;
362 }
363
364
365 void cleanup_module()
366 {
367         write_lock_irqsave(m7101_lock, m7101_lock_flags);
368         if (m7101_inserted) {
369                 pci_remove_device(m7101);
370                 m7101_inserted = FALSE;
371         }
372         write_unlock_irqrestore(m7101_lock, m7101_lock_flags);
373
374         if (NULL != m7101)
375                 kfree(m7101);
376
377         printk("m7101: bye bye\n");
378 }
379
380 EXPORT_NO_SYMBOLS;
381
382 #ifdef MODULE
383 #ifdef MODULE_LICENSE
384 MODULE_LICENSE("GPL");
385 #endif
386 MODULE_AUTHOR("Burkhard Kohl <bku@buks.ipn.de>, "
387               "Frank Bauer <frank.bauer@nikocity.de>, "
388               "and Mark Studebaker <mdsxyz123@yahoo.com>");
389 MODULE_DESCRIPTION("M7101 PCI Inserter");
390
391 #endif                          /* MODULE */
Note: See TracBrowser for help on using the browser.