Date: Mon, 15 Feb 1999 07:58:35 +0100 From: Matthias Apitz <guru@Sisis.de> To: Steve Emmert <steve@emmert.com> Cc: freebsd-mobile@FreeBSD.ORG, Nate Williams <nate@mt.sri.com> Subject: Re: O2 Micro OZ6832/6833 pci-cardbus controller Message-ID: <19990215075835.40475@sisis.de> In-Reply-To: <Pine.BSF.4.05.9902130836190.376-100000@free.emmert.com>; from Steve Emmert on Sat, Feb 13, 1999 at 10:48:37AM -0800 References: <Pine.BSF.4.05.9902130836190.376-100000@free.emmert.com>
next in thread | previous in thread | raw e-mail | index | archive | help
--FCuugMFkClbJLl1L Content-Type: text/plain; charset=us-ascii On Sat, Feb 13, 1999 at 10:48:37AM -0800, Steve Emmert wrote: > I have recently purchased an IBM Thinkpad that has a O2 Micro- > OZ6832/6833 pci-cardbus controller. I see from the list archives > that there is a patch out there to get this controller working. > Could some kind person E-mail me the patch or direct me to a > site where i could download it. My Thinkpad is running 3.1- > BETA if that makes a difference. Hi Steve, attached below is my patch for O2Micro's OZ6832 CardBus controller. The diff is against 2.2.7 and I don't know if this will work with 3.1 and your 6833 too. Please check it out and let me and the list know. There is also a trick or hack used to identify the chip. Check the comments for details and it may occur that this test will fail for your chip anyway -- so play with it / change it. A better solution should be worked out... Hope it helps. matthias -- firm: matthias.apitz@sisis.de [voc:+49 89 61308 351, fax: +49 89 61308 188] priv: guru@thias.muc.de WWW: http://www.sisis.de/~guru/ Give me UNIX or give me a typewriter. --FCuugMFkClbJLl1L Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="OZ6832.diff" *** pci/pcic_p.h.orig Sat Feb 7 21:38:58 1998 --- pci/pcic_p.h Thu Apr 16 08:00:14 1998 *************** *** 35,40 **** --- 35,41 ---- #define PCI_DEVICE_ID_PCIC_O2MICRO 0x673A1217ul #define PCI_DEVICE_ID_PCIC_TI1130 0xAC12104Cul #define PCI_DEVICE_ID_PCIC_TI1131 0xAC15104Cul + #define PCI_DEVICE_ID_PCIC_OZ6832 0x68321217ul /* CL-PD6832 CardBus defines */ #define CLPD6832_IO_BASE0 0x002c *************** *** 52,54 **** --- 53,73 ---- #define CLPD6832_NUM_REGS 2 /* End of CL-PD6832 defines */ + + /* O2Micro OZ6832 CardBus defines */ + /* matthias.apitz@sisis.de */ + + #define OZ6832_IO_BASE0 0x002c + #define OZ6832_IO_LIMIT0 0x0030 + #define OZ6832_IO_BASE1 0x0034 + #define OZ6832_IO_LIMIT1 0x0038 + #define OZ6832_BRIDGE_CONTROL 0x003c + #define OZ6832_LEGACY_16BIT_IOADDR 0x0044 + + /* O2Micro OZ6832 Configuration constants */ + #define OZ6832_BCR_ISA_IRQ 0x00800000 + #define OZ6832_COMMAND_DEFAULTS 0x00000007 + + #define OZ6832_NUM_REGS 2 + + /* End of O2Micro OZ6832 CardBus defines */ *** pci/pcic_p.c.orig Sat Feb 7 21:42:29 1998 --- pci/pcic_p.c Fri Apr 17 07:47:37 1998 *************** *** 29,34 **** --- 29,40 ---- * $Id: pcic_p.c,v 1.4.2.2 1998/02/07 20:42:29 nate Exp $ */ + /* + * modified for O2Micro's OZ6832 PCI to CardBus controller + * by Matthias Apitz <matthias.apitz@sisis.de> + * April, 1998 + */ + #include "pci.h" #if NPCI > 0 *************** *** 48,53 **** --- 54,61 ---- static void pcic_pci_attach(pcici_t, int); static void pd6832_legacy_init(pcici_t tag, int unit); + static void oz6832_legacy_init(pcici_t tag, int unit); + static void pcic_pci_printConfig(pcici_t tag, char *s); static struct pci_device pcic_pci_driver = { "pcic", *************** *** 66,71 **** --- 74,80 ---- static char * pcic_pci_probe(pcici_t tag, pcidi_t type) { + switch (type) { case PCI_DEVICE_ID_PCIC_CLPD6729: return ("Cirrus Logic PD6729/6730 PC-Card Controller"); *************** *** 75,80 **** --- 84,91 ---- return ("TI 1130 PCMCIA/CardBus Bridge"); case PCI_DEVICE_ID_PCIC_TI1131: return ("TI 1131 PCI to PCMCIA/CardBus bridge"); + case PCI_DEVICE_ID_PCIC_OZ6832: + return ("O2Micro OZ6832 CardBus bridge"); default: break; } *************** *** 84,90 **** /* * General PCI based card dispatch routine. Right now ! * it only understands the CL-PD6832. */ static void pcic_pci_attach(pcici_t config_id, int unit) --- 95,103 ---- /* * General PCI based card dispatch routine. Right now ! * it only understands the follwoing chips: ! * Cirrus Logic PD6832 ! * O2Micro OZ6832 */ static void pcic_pci_attach(pcici_t config_id, int unit) *************** *** 97,102 **** --- 110,124 ---- case PCI_DEVICE_ID_PCIC_CLPD6832: pd6832_legacy_init(config_id, unit); break; + case PCI_DEVICE_ID_PCIC_OZ6832: + oz6832_legacy_init(config_id, unit); + /* + * no way to print the CardBus soccket regs and + * ExCA regs here for the moment -- we skip the rest + * of the function; + */ + return; + break; } if (bootverbose) { *************** *** 192,196 **** --- 214,306 ---- if (bootverbose) printf("CardBus: Legacy PC-card 16bit I/O address [0x%x]\n", io_port); + } + + /* + * Set up the O2Mirco OZ6832 to look like a ISA based PCMCIA chip (a + * PD672X). This routine is called once per PCMCIA socket. + */ + static void + oz6832_legacy_init(pcici_t tag, int unit) + { + u_long bcr; /* to set interrupts */ + u_short io_port; /* the io_port to map this slot on */ + static int num6832 = 0; /* The number of 6832s initialized */ + + /* + * Some BIOS leave the legacy address uninitialized. This + * insures that the PD6832 puts itself where the driver will + * look. We assume that multiple 6832's should be laid out + * sequentially. We only initialize the first socket's legacy port, + * the other is a dummy. + */ + if (bootverbose) + pcic_pci_printConfig(tag, "as got from BIOS"); + + io_port = PCIC_INDEX_0 + num6832 * OZ6832_NUM_REGS; + if (unit == 0) { + pci_conf_write(tag, OZ6832_LEGACY_16BIT_IOADDR, + io_port & ~PCI_MAP_IO); + } + + /* + * I think this should be a call to pci_map_port, but that + * routine won't map regiaters above 0x28, and the register we + * need to map is 0x44. + */ + + io_port = pci_conf_read(tag, OZ6832_LEGACY_16BIT_IOADDR) + & ~PCI_MAP_IO; + + /* + * Set default operating mode (I/O port space) and allocate + * this socket to the current unit. + */ + + pci_conf_write(tag, PCI_COMMAND_STATUS_REG, OZ6832_COMMAND_DEFAULTS); + + /* + * Set up the card inserted/card removed interrupts to come + * through the isa IRQ. + */ + bcr = pci_conf_read(tag, OZ6832_BRIDGE_CONTROL); + bcr |= OZ6832_BCR_ISA_IRQ; + pci_conf_write(tag, OZ6832_BRIDGE_CONTROL, bcr); + + /* After initializing 2 sockets, the chip is fully configured */ + if (unit == 1) + num6832++; + + if (bootverbose) { + pcic_pci_printConfig(tag, "after oz6832_legacy_init"); + printf("CardBus: Legacy PC-card 16bit I/O address [0x%x]\n", + io_port); + } + } + + /* + * Dump the PCI Config Space + */ + static void + pcic_pci_printConfig(pcici_t config_id, char *s) + { + int i, j; + u_char *p; + u_long *pl; + + printf("PCI Config space %s:\n", s); + for (j = 0; j < 0x98; j += 16) { + printf("%02x: ", j); + for (i = 0; i < 16; i += 4) + printf(" %08x", pci_conf_read(config_id, i+j)); + printf("\n"); + } + /* + * the rest of the function is nonsense at the moment + * because we have no idea how to access the + * Cardbus Socket regs because the addr in 0x10 is NULL + */ + printf("Cardbus Socket registers not available.\n"); + } #endif /* NPCI > 0 */ *** pccard/i82365.h.orig Thu Oct 23 20:44:06 1997 --- pccard/i82365.h Fri Apr 17 17:00:17 1998 *************** *** 45,50 **** --- 45,51 ---- #define PCIC_IBM_KING 9 /* IBM KING PCMCIA Controller */ #define PCIC_PC98 10 /* NEC PC98 PCMCIA Controller */ #define PCIC_TI1130 11 /* TI PCI1130 CardBus */ + #define PCIC_OZ6832 12 /* O2Micro 6832 CardBus */ /* * Address of the controllers. Each controller can manage *************** *** 87,92 **** --- 88,95 ---- #define PCIC_TIME_CMD1 0x3e #define PCIC_TIME_RECOV1 0x3f + #define PCIC_O2MICRO_MCTRL_B 0x39 /* O2Micro Mode Control Register B */ + #define PCIC_SLOT_SIZE 0x40 /* Size of register set for one slot */ /* Now register bits, ordered by reg # */ *************** *** 94,99 **** --- 97,103 ---- /* For Identification and Revision (PCIC_ID_REV) */ #define PCIC_INTEL0 0x82 /* Intel 82365SL Rev. 0; Both Memory and I/O */ #define PCIC_INTEL1 0x83 /* Intel 82365SL Rev. 1; Both Memory and I/O */ + #define PCIC_O2MICRO 0x87 /* O2Micro OZ6832; Both Memory and I/O */ #define PCIC_IBM1 0x88 /* IBM PCIC clone; Both Memory and I/O */ #define PCIC_IBM2 0x89 /* IBM PCIC clone; Both Memory and I/O */ #define PCIC_IBM3 0x8a /* IBM KING PCIC clone; Both Memory and I/O */ *** pccard/pcic.c.orig Sat Nov 15 15:11:34 1997 --- pccard/pcic.c Sat Apr 18 07:58:27 1998 *************** *** 33,38 **** --- 33,45 ---- * by Noriyuki Hosobuchi <yj8n-hsbc@asahi-net.or.jp> */ + /* + * modified for O2Micro's OZ6832 PCI to CardBus controller + * by Matthias Apitz <matthias.apitz@sisis.de> + * April, 1998 + */ + + #include <sys/param.h> #include <sys/systm.h> #include <sys/kernel.h> *************** *** 90,95 **** --- 97,103 ---- static unsigned pcic_imask; static struct slot_ctrl cinfo; + static void dump_register_table(struct pcic_slot *sp, char *s); /* * Internal inline functions for accessing the PCIC. *************** *** 538,543 **** --- 546,562 ---- * of slot 1. Assume it's the only PCIC whose vendor ID is 0x84, * contact Nate Williams <nate@FreeBSD.org> if incorrect. */ + + /* + * O2Micro's OZ6832 comes along with a vendor ID 0x82 and + * mostly works like an Intel clone. You may detect it as + * an OZ6832 by switching on the O2Micro-mode (see below) + * and see if the vendor ID changes to 0x87, contact Matthias + * Apitz <guru@sisis.de> if this doesn't work for you. The + * PCIC can't steer out interupts for card status changes, only + * for I/O the steering does work and this also stops to + * work if you enable irq steering for status changes. sigh. + */ int pcic_probe(void) { *************** *** 546,551 **** --- 565,572 ---- struct slot *slt; struct pcic_slot *sp; unsigned char c; + unsigned char o2mode; + unsigned char save; static int maybe_vlsi = 0; /* Determine the list of free interrupts */ *************** *** 610,616 **** --- 631,668 ---- * 82365 or clones. */ case 0x82: + /* + * first let's look for an O2Micro OZ6832 CardBus + * controller... + * + * setting the two bits [1:0] in the register + * "O2Micro control B" at offset 39h to the value + * 0x02 should switch the PCIC_ID_REV from 0x82 + * to 0x87 (PCIC_O2MICRO) + */ + #ifdef PCIC_DEBUG + dump_register_table(sp, "pcic_probe() for O2Micro"); + #endif + save = sp->getb(sp, PCIC_O2MICRO_MCTRL_B); + clrb(sp, PCIC_O2MICRO_MCTRL_B, 0x01); + setb(sp, PCIC_O2MICRO_MCTRL_B, 0x02); + o2mode = sp->getb(sp, PCIC_ID_REV); + /* restore the old value and see what o2mode has ... */ + sp->putb(sp, PCIC_O2MICRO_MCTRL_B, save); + if(o2mode == PCIC_O2MICRO) { + printf("pcic: found an O2Micro OZ6832 CardBus controller\n"); + printf("pcic: PCIC_ID_REV was switchable to 0x%x\n", o2mode); + sp->controller = PCIC_OZ6832; + sp->revision = c & 1; + break; + } + /* + * ... fall through if not an OZ6832 + */ case 0x83: + #ifdef PCIC_DEBUG + dump_register_table(sp, "pcic_probe() for 82365 clone"); + #endif sp->controller = PCIC_I82365; sp->revision = c & 1; /* *************** *** 670,675 **** --- 722,730 ---- } } switch(sp->controller) { + case PCIC_OZ6832: + cinfo.name = "O2Micro OZ6832"; + break; case PCIC_I82365: cinfo.name = "Intel 82365"; break; *************** *** 703,712 **** } #ifndef PCIC_NOCLRREGS /* ! * clear out the registers. */ ! for (i = 2; i < 0x40; i++) ! sp->putb(sp, i, 0); #endif /* PCIC_NOCLRREGS */ /* * OK it seems we have a PCIC or lookalike. --- 758,770 ---- } #ifndef PCIC_NOCLRREGS /* ! * clear out the registers if no O2Micro chip */ ! if(sp->controller != PCIC_OZ6832) { ! printf("pcic: zero out for all ExCA regs\n"); ! for (i = 2; i < 0x40; i++) ! sp->putb(sp, i, 0); ! } #endif /* PCIC_NOCLRREGS */ /* * OK it seems we have a PCIC or lookalike. *************** *** 754,763 **** pccard_event(sp->slt, card_inserted); } /* ! * Assign IRQ for slot changes */ ! if (pcic_irq > 0) ! sp->putb(sp, PCIC_STAT_INT, (pcic_irq << 4) | 0xF); } #ifdef PC98 if (validslots == 0) { --- 812,838 ---- pccard_event(sp->slt, card_inserted); } /* ! * Assign IRQ for slot changes ! * ! * the folks @ o2micro.com say: we can't generate ! * ISA IRQ's for status changes in OZ6832 ... ! * for the moment we simple set PCIC_STAT_INT to 0xf ! * and rely on the polling in the driver; */ ! if (pcic_irq > 0) { ! if(sp->controller == PCIC_OZ6832) { ! printf("pcic: OZ6832 can't steer irqs for slot changes -- irq unused\n"); ! sp->putb(sp, PCIC_STAT_INT, 0x0f); ! } ! else ! sp->putb(sp, PCIC_STAT_INT, (pcic_irq << 4) | 0xF); ! } ! /* ! * Dump the ExCA after IRQ for slot changes ! */ ! #ifdef PCIC_DEBUG ! dump_register_table(sp, "set PCIC_STAT_INT"); ! #endif } #ifdef PC98 if (validslots == 0) { *************** *** 972,982 **** return; } #endif if (irq == 0) clrb(sp, PCIC_INT_GEN, 0xF); ! else sp->putb(sp, PCIC_INT_GEN, ! (sp->getb(sp, PCIC_INT_GEN) & 0xF0) | irq); } /* --- 1047,1065 ---- return; } #endif + #ifdef PCIC_DEBUG + printf("pcic: irq=%d mapped.\n", irq); + #endif if (irq == 0) clrb(sp, PCIC_INT_GEN, 0xF); ! else { sp->putb(sp, PCIC_INT_GEN, ! (sp->getb(sp, PCIC_INT_GEN) & 0xF0) | irq ); ! } ! #ifdef PCIC_DEBUG ! dump_register_table(sp, "pcic_mapirq()"); ! #endif ! } /* *************** *** 1051,1056 **** --- 1134,1140 ---- /* * PCIC timer, it seems that we lose interrupts sometimes + * and we don't get interrupts for the OZ6832 at all ... * so poll just in case... */ static void *************** *** 1073,1078 **** --- 1157,1163 ---- unsigned char chg; struct pcic_slot *sp = pcic_slots; + #ifdef PC98 if (sp->controller == PCIC_PC98) { slot = 0; *************** *** 1112,1121 **** pcic_resume(struct slot *slt) { struct pcic_slot *sp = slt->cdata; if (pcic_irq > 0) ! sp->putb(sp, PCIC_STAT_INT, (pcic_irq << 4) | 0xF); if (sp->controller == PCIC_PD672X) { setb(sp, PCIC_MISC1, PCIC_SPKR_EN); setb(sp, PCIC_MISC2, PCIC_LPDM_EN); } } --- 1197,1234 ---- pcic_resume(struct slot *slt) { struct pcic_slot *sp = slt->cdata; + if (pcic_irq > 0) ! if(sp->controller == PCIC_OZ6832) { ! printf("pcic: OZ6832 can't steer irqs for slot changes -- irq unused\n"); ! sp->putb(sp, PCIC_STAT_INT, 0x0f); ! } ! else ! sp->putb(sp, PCIC_STAT_INT, (pcic_irq << 4) | 0xF); ! if (sp->controller == PCIC_PD672X) { setb(sp, PCIC_MISC1, PCIC_SPKR_EN); setb(sp, PCIC_MISC2, PCIC_LPDM_EN); + } + } + + + /* + * dump all ExCA registers from 800h to 83Fh + */ + void dump_register_table(struct pcic_slot *sp, char *s) + { + unsigned char c; + unsigned char *p; + unsigned char regs[16]; + int i, j; + + printf("\nExCA registers in %s:\n", s); + + for (i = 0; i < 0x40; i += 16) { + for(j=0; j < 16; j++) + regs[j] = sp->getb(sp, i+j); + p = regs; + printf("%02x: %16D\n", i, p, " "); } } --FCuugMFkClbJLl1L-- To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-mobile" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?19990215075835.40475>