aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/irda/smsc-ircc2.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/irda/smsc-ircc2.c')
-rw-r--r--drivers/net/irda/smsc-ircc2.c311
1 files changed, 311 insertions, 0 deletions
diff --git a/drivers/net/irda/smsc-ircc2.c b/drivers/net/irda/smsc-ircc2.c
index ec94ecdb103d..bbcfc8ec35a1 100644
--- a/drivers/net/irda/smsc-ircc2.c
+++ b/drivers/net/irda/smsc-ircc2.c
@@ -11,6 +11,7 @@
11 * Copyright (c) 2002 Daniele Peri 11 * Copyright (c) 2002 Daniele Peri
12 * All Rights Reserved. 12 * All Rights Reserved.
13 * Copyright (c) 2002 Jean Tourrilhes 13 * Copyright (c) 2002 Jean Tourrilhes
14 * Copyright (c) 2006 Linus Walleij
14 * 15 *
15 * 16 *
16 * Based on smc-ircc.c: 17 * Based on smc-ircc.c:
@@ -61,6 +62,9 @@
61 62
62#include <linux/spinlock.h> 63#include <linux/spinlock.h>
63#include <linux/pm.h> 64#include <linux/pm.h>
65#ifdef CONFIG_PCI
66#include <linux/pci.h>
67#endif
64 68
65#include <net/irda/wrapper.h> 69#include <net/irda/wrapper.h>
66#include <net/irda/irda.h> 70#include <net/irda/irda.h>
@@ -100,6 +104,22 @@ MODULE_PARM_DESC(ircc_transceiver, "Transceiver type");
100 104
101/* Types */ 105/* Types */
102 106
107#ifdef CONFIG_PCI
108struct smsc_ircc_subsystem_configuration {
109 unsigned short vendor; /* PCI vendor ID */
110 unsigned short device; /* PCI vendor ID */
111 unsigned short subvendor; /* PCI subsystem vendor ID */
112 unsigned short subdevice; /* PCI sybsystem device ID */
113 unsigned short sir_io; /* I/O port for SIR */
114 unsigned short fir_io; /* I/O port for FIR */
115 unsigned char fir_irq; /* FIR IRQ */
116 unsigned char fir_dma; /* FIR DMA */
117 unsigned short cfg_base; /* I/O port for chip configuration */
118 int (*preconfigure)(struct pci_dev *dev, struct smsc_ircc_subsystem_configuration *conf); /* Preconfig function */
119 const char *name; /* name shown as info */
120};
121#endif
122
103struct smsc_transceiver { 123struct smsc_transceiver {
104 char *name; 124 char *name;
105 void (*set_for_speed)(int fir_base, u32 speed); 125 void (*set_for_speed)(int fir_base, u32 speed);
@@ -202,6 +222,16 @@ static int __init smsc_superio_flat(const struct smsc_chip *chips, unsigned shor
202static int __init smsc_superio_paged(const struct smsc_chip *chips, unsigned short cfg_base, char *type); 222static int __init smsc_superio_paged(const struct smsc_chip *chips, unsigned short cfg_base, char *type);
203static int __init smsc_superio_fdc(unsigned short cfg_base); 223static int __init smsc_superio_fdc(unsigned short cfg_base);
204static int __init smsc_superio_lpc(unsigned short cfg_base); 224static int __init smsc_superio_lpc(unsigned short cfg_base);
225#ifdef CONFIG_PCI
226static int __init preconfigure_smsc_chip(struct smsc_ircc_subsystem_configuration *conf);
227static int __init preconfigure_through_82801(struct pci_dev *dev, struct smsc_ircc_subsystem_configuration *conf);
228static int __init preconfigure_through_ali(struct pci_dev *dev, struct smsc_ircc_subsystem_configuration *conf);
229static int __init smsc_ircc_preconfigure_subsystems(unsigned short ircc_cfg,
230 unsigned short ircc_fir,
231 unsigned short ircc_sir,
232 unsigned char ircc_dma,
233 unsigned char ircc_irq);
234#endif
205 235
206/* Transceivers specific functions */ 236/* Transceivers specific functions */
207 237
@@ -353,6 +383,13 @@ static int __init smsc_ircc_init(void)
353 return ret; 383 return ret;
354 } 384 }
355 385
386#ifdef CONFIG_PCI
387 if (smsc_ircc_preconfigure_subsystems(ircc_cfg, ircc_fir, ircc_sir, ircc_dma, ircc_irq) < 0) {
388 /* Ignore errors from preconfiguration */
389 IRDA_ERROR("%s, Preconfiguration failed !\n", driver_name);
390 }
391#endif
392
356 dev_count = 0; 393 dev_count = 0;
357 394
358 if (ircc_fir > 0 && ircc_sir > 0) { 395 if (ircc_fir > 0 && ircc_sir > 0) {
@@ -2285,6 +2322,280 @@ static int __init smsc_superio_lpc(unsigned short cfg_base)
2285 return ret; 2322 return ret;
2286} 2323}
2287 2324
2325/*
2326 * Look for some specific subsystem setups that need
2327 * pre-configuration not properly done by the BIOS (especially laptops)
2328 * This code is based in part on smcinit.c, tosh1800-smcinit.c
2329 * and tosh2450-smcinit.c. The table lists the device entries
2330 * for ISA bridges with an LPC (Local Peripheral Configurator)
2331 * that are in turn used to configure the SMSC device with default
2332 * SIR and FIR I/O ports, DMA and IRQ.
2333 */
2334#ifdef CONFIG_PCI
2335#define PCIID_VENDOR_INTEL 0x8086
2336#define PCIID_VENDOR_ALI 0x10b9
2337static struct smsc_ircc_subsystem_configuration subsystem_configurations[] __devinitdata = {
2338 {
2339 .vendor = PCIID_VENDOR_INTEL, /* Intel 82801DBM LPC bridge */
2340 .device = 0x24cc,
2341 .subvendor = 0x103c,
2342 .subdevice = 0x088c,
2343 .sir_io = 0x02f8, /* Quite certain these are the same for nc8000 as for nc6000 */
2344 .fir_io = 0x0130,
2345 .fir_irq = 0x09,
2346 .fir_dma = 0x03,
2347 .cfg_base = 0x004e,
2348 .preconfigure = preconfigure_through_82801,
2349 .name = "HP nc8000",
2350 },
2351 {
2352 .vendor = PCIID_VENDOR_INTEL, /* Intel 82801DBM LPC bridge */
2353 .device = 0x24cc,
2354 .subvendor = 0x103c,
2355 .subdevice = 0x0890,
2356 .sir_io = 0x02f8,
2357 .fir_io = 0x0130,
2358 .fir_irq = 0x09,
2359 .fir_dma = 0x03,
2360 .cfg_base = 0x004e,
2361 .preconfigure = preconfigure_through_82801,
2362 .name = "HP nc6000",
2363 },
2364 {
2365 .vendor = PCIID_VENDOR_INTEL, /* Intel 82801DB/DBL (ICH4/ICH4-L) LPC Interface Bridge */
2366 .device = 0x24c0,
2367 .subvendor = 0x1179,
2368 .subdevice = 0xffff, /* 0xffff is "any", Not sure, 0x0001 or 0x0002 */
2369 .sir_io = 0x03f8,
2370 .fir_io = 0x0130,
2371 .fir_irq = 0x07,
2372 .fir_dma = 0x01,
2373 .cfg_base = 0x002e,
2374 .preconfigure = preconfigure_through_82801,
2375 .name = "Toshiba Satellite 2450",
2376 },
2377 {
2378 .vendor = PCIID_VENDOR_INTEL, /* Intel 82801CAM ISA bridge */
2379 .device = 0x248c, /* Some use 24cc? */
2380 .subvendor = 0x1179,
2381 .subdevice = 0xffff, /* 0xffff is "any", Not sure, 0x0001 or 0x0002 */
2382 .sir_io = 0x03f8,
2383 .fir_io = 0x0130,
2384 .fir_irq = 0x03,
2385 .fir_dma = 0x03,
2386 .cfg_base = 0x002e,
2387 .preconfigure = preconfigure_through_82801,
2388 .name = "Toshiba Satellite 5100/5200, Tecra 9100",
2389 },
2390 {
2391 .vendor = PCIID_VENDOR_ALI, /* ALi M1533/M1535 PCI to ISA Bridge [Aladdin IV/V/V+] */
2392 .device = 0x1533,
2393 .subvendor = 0x1179,
2394 .subdevice = 0xffff, /* 0xffff is "any", Not sure, 0x0001 or 0x0002 */
2395 .sir_io = 0x02e8,
2396 .fir_io = 0x02f8,
2397 .fir_irq = 0x07,
2398 .fir_dma = 0x03,
2399 .cfg_base = 0x002e,
2400 .preconfigure = preconfigure_through_ali,
2401 .name = "Toshiba Satellite 1800",
2402 },
2403 { } // Terminator
2404};
2405
2406
2407/*
2408 * This sets up the basic SMSC parameters (FIR port, SIR port, FIR DMA, FIR IRQ)
2409 * through the chip configuration port.
2410 */
2411static int __init preconfigure_smsc_chip(struct smsc_ircc_subsystem_configuration *conf)
2412{
2413 unsigned short iobase = conf->cfg_base;
2414 unsigned char tmpbyte;
2415
2416 outb(LPC47N227_CFGACCESSKEY, iobase); // enter configuration state
2417 outb(SMSCSIOFLAT_DEVICEID_REG, iobase); // set for device ID
2418 tmpbyte = inb(iobase +1); // Read device ID
2419 IRDA_DEBUG(0, "Detected Chip id: 0x%02x, setting up registers...\n",tmpbyte);
2420
2421 /* Disable UART1 and set up SIR I/O port */
2422 outb(0x24, iobase); // select CR24 - UART1 base addr
2423 outb(0x00, iobase + 1); // disable UART1
2424 outb(SMSCSIOFLAT_UART2BASEADDR_REG, iobase); // select CR25 - UART2 base addr
2425 outb( (conf->sir_io >> 2), iobase + 1); // bits 2-9 of 0x3f8
2426 tmpbyte = inb(iobase + 1);
2427 if (tmpbyte != (conf->sir_io >> 2) ) {
2428 IRDA_WARNING("ERROR: could not configure SIR ioport.\n");
2429 return -ENXIO;
2430 }
2431
2432 /* Set up FIR IRQ channel for UART2 */
2433 outb(SMSCSIOFLAT_UARTIRQSELECT_REG, iobase); // select CR28 - UART1,2 IRQ select
2434 tmpbyte = inb(iobase + 1);
2435 tmpbyte &= SMSCSIOFLAT_UART1IRQSELECT_MASK; // Do not touch the UART1 portion
2436 tmpbyte |= (conf->fir_irq & SMSCSIOFLAT_UART2IRQSELECT_MASK);
2437 outb(tmpbyte, iobase + 1);
2438 tmpbyte = inb(iobase + 1) & SMSCSIOFLAT_UART2IRQSELECT_MASK;
2439 if (tmpbyte != conf->fir_irq) {
2440 IRDA_WARNING("ERROR: could not configure FIR IRQ channel.\n");
2441 return -ENXIO;
2442 }
2443
2444 /* Set up FIR I/O port */
2445 outb(SMSCSIOFLAT_FIRBASEADDR_REG, iobase); // CR2B - SCE (FIR) base addr
2446 outb((conf->fir_io >> 3), iobase + 1);
2447 tmpbyte = inb(iobase + 1);
2448 if (tmpbyte != (conf->fir_io >> 3) ) {
2449 IRDA_WARNING("ERROR: could not configure FIR I/O port.\n");
2450 return -ENXIO;
2451 }
2452
2453 /* Set up FIR DMA channel */
2454 outb(SMSCSIOFLAT_FIRDMASELECT_REG, iobase); // CR2C - SCE (FIR) DMA select
2455 outb((conf->fir_dma & LPC47N227_FIRDMASELECT_MASK), iobase + 1); // DMA
2456 tmpbyte = inb(iobase + 1) & LPC47N227_FIRDMASELECT_MASK;
2457 if (tmpbyte != (conf->fir_dma & LPC47N227_FIRDMASELECT_MASK)) {
2458 IRDA_WARNING("ERROR: could not configure FIR DMA channel.\n");
2459 return -ENXIO;
2460 }
2461
2462 outb(SMSCSIOFLAT_UARTMODE0C_REG, iobase); // CR0C - UART mode
2463 tmpbyte = inb(iobase + 1);
2464 tmpbyte &= ~SMSCSIOFLAT_UART2MODE_MASK | SMSCSIOFLAT_UART2MODE_VAL_IRDA;
2465 outb(tmpbyte, iobase + 1); // enable IrDA (HPSIR) mode, high speed
2466
2467 outb(LPC47N227_APMBOOTDRIVE_REG, iobase); // CR07 - Auto Pwr Mgt/boot drive sel
2468 tmpbyte = inb(iobase + 1);
2469 outb(tmpbyte | LPC47N227_UART2AUTOPWRDOWN_MASK, iobase + 1); // enable UART2 autopower down
2470
2471 /* This one was not part of tosh1800 */
2472 outb(0x0a, iobase); // CR0a - ecp fifo / ir mux
2473 tmpbyte = inb(iobase + 1);
2474 outb(tmpbyte | 0x40, iobase + 1); // send active device to ir port
2475
2476 outb(LPC47N227_UART12POWER_REG, iobase); // CR02 - UART 1,2 power
2477 tmpbyte = inb(iobase + 1);
2478 outb(tmpbyte | LPC47N227_UART2POWERDOWN_MASK, iobase + 1); // UART2 power up mode, UART1 power down
2479
2480 outb(LPC47N227_FDCPOWERVALIDCONF_REG, iobase); // CR00 - FDC Power/valid config cycle
2481 tmpbyte = inb(iobase + 1);
2482 outb(tmpbyte | LPC47N227_VALID_MASK, iobase + 1); // valid config cycle done
2483
2484 outb(LPC47N227_CFGEXITKEY, iobase); // Exit configuration
2485
2486 return 0;
2487}
2488
2489/* 82801CAM registers */
2490#define VID 0x00
2491#define DID 0x02
2492#define PIRQA_ROUT 0x60
2493#define PCI_DMA_C 0x90
2494#define COM_DEC 0xe0
2495#define LPC_EN 0xe6
2496#define GEN2_DEC 0xec
2497/*
2498 * Sets up the I/O range using the 82801CAM ISA bridge, 82801DBM LPC bridge or
2499 * Intel 82801DB/DBL (ICH4/ICH4-L) LPC Interface Bridge. They all work the same way!
2500 */
2501static int __init preconfigure_through_82801(struct pci_dev *dev,
2502 struct smsc_ircc_subsystem_configuration *conf)
2503{
2504 unsigned short tmpword;
2505 int ret;
2506
2507 IRDA_MESSAGE("Setting up the SMSC device via the 82801 controller.\n");
2508 pci_write_config_byte(dev, COM_DEC, 0x10);
2509
2510 /* Enable LPC */
2511 pci_read_config_word(dev, LPC_EN, &tmpword); /* LPC_EN register */
2512 tmpword &= 0xfffd; /* mask bit 1 */
2513 tmpword |= 0x0001; /* set bit 0 : COMA addr range enable */
2514 pci_write_config_word(dev, LPC_EN, tmpword);
2515
2516 /* Setup DMA */
2517 pci_write_config_word(dev, PCI_DMA_C, 0xc0c0); /* LPC I/F DMA on, channel 3 -- rtm (?? PCI DMA ?) */
2518 pci_write_config_word(dev, GEN2_DEC, 0x131); /* LPC I/F 2nd decode range */
2519
2520 /* Pre-configure chip */
2521 ret = preconfigure_smsc_chip(conf);
2522
2523 /* Disable LPC */
2524 pci_read_config_word(dev, LPC_EN, &tmpword); /* LPC_EN register */
2525 tmpword &= 0xfffc; /* mask bit 1 and bit 0, COMA addr range disable */
2526 pci_write_config_word(dev, LPC_EN, tmpword);
2527 return ret;
2528}
2529
2530static int __init preconfigure_through_ali(struct pci_dev *dev,
2531 struct smsc_ircc_subsystem_configuration *conf)
2532{
2533 /* TODO: put in ALi 1533 configuration here. */
2534 IRDA_MESSAGE("SORRY: %s has an unsupported bridge controller (ALi): not pre-configured.\n", conf->name);
2535 return -ENODEV;
2536}
2537
2538static int __init smsc_ircc_preconfigure_subsystems(unsigned short ircc_cfg,
2539 unsigned short ircc_fir,
2540 unsigned short ircc_sir,
2541 unsigned char ircc_dma,
2542 unsigned char ircc_irq)
2543{
2544 struct pci_dev *dev = NULL;
2545 unsigned short ss_vendor = 0x0000;
2546 unsigned short ss_device = 0x0000;
2547 int ret = 0;
2548
2549 dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev);
2550
2551 while (dev != NULL) {
2552 struct smsc_ircc_subsystem_configuration *conf;
2553
2554 /*
2555 * Cache the subsystem vendor/device: some manufacturers fail to set
2556 * this for all components, so we save it in case there is just
2557 * 0x0000 0x0000 on the device we want to check.
2558 */
2559 if (dev->subsystem_vendor != 0x0000U) {
2560 ss_vendor = dev->subsystem_vendor;
2561 ss_device = dev->subsystem_device;
2562 }
2563 conf = subsystem_configurations;
2564 for( ; conf->subvendor; conf++) {
2565 if(conf->vendor == dev->vendor &&
2566 conf->device == dev->device &&
2567 conf->subvendor == ss_vendor && /* Sometimes these are cached values */
2568 (conf->subdevice == ss_device || conf->subdevice == 0xffff)) {
2569 struct smsc_ircc_subsystem_configuration tmpconf;
2570
2571 memcpy(&tmpconf, conf, sizeof(struct smsc_ircc_subsystem_configuration));
2572
2573 /* Override the default values with anything passed in as parameter */
2574 if (ircc_cfg != 0)
2575 tmpconf.cfg_base = ircc_cfg;
2576 if (ircc_fir != 0)
2577 tmpconf.fir_io = ircc_fir;
2578 if (ircc_sir != 0)
2579 tmpconf.sir_io = ircc_sir;
2580 if (ircc_dma != 0xff)
2581 tmpconf.fir_dma = ircc_dma;
2582 if (ircc_irq != 0xff)
2583 tmpconf.fir_irq = ircc_irq;
2584
2585 IRDA_MESSAGE("Detected unconfigured %s SMSC IrDA chip, pre-configuring device.\n", conf->name);
2586 if (conf->preconfigure)
2587 ret = conf->preconfigure(dev, &tmpconf);
2588 else
2589 ret = -ENODEV;
2590 }
2591 }
2592 dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev);
2593 }
2594
2595 return ret;
2596}
2597#endif // CONFIG_PCI
2598
2288/************************************************ 2599/************************************************
2289 * 2600 *
2290 * Transceivers specific functions 2601 * Transceivers specific functions