ti1225.c

Go to the documentation of this file.
00001 /*
00002 ti1225.c
00003 
00004 Created:        Dec 2005 by Philip Homburg
00005 */
00006 
00007 #include "../drivers.h"
00008 #include <ibm/pci.h>
00009 #include <sys/vm.h>
00010 
00011 #include "ti1225.h"
00012 #include "i82365.h"
00013 
00014 /* The use of interrupts is not yet ready for prime time */
00015 #define USE_INTS        0
00016 
00017 #define MICROS_TO_TICKS(m)  (((m)*HZ/1000000)+1)
00018 
00019 #define NR_PORTS 2
00020 
00021 PRIVATE struct port
00022 {
00023         unsigned p_flags;
00024         int p_devind;
00025         u8_t p_cb_busnr;
00026         u16_t p_exca_port;
00027 #if USE_INTS
00028         int p_irq;
00029         int p_hook;
00030 #endif
00031         char *base_ptr;
00032         volatile struct csr *csr_ptr;
00033 
00034         char buffer[2*PAGE_SIZE];
00035 } ports[NR_PORTS];
00036 
00037 #define PF_PRESENT      1
00038 
00039 struct pcitab
00040 {
00041         u16_t vid;
00042         u16_t did;
00043         int checkclass;
00044 };
00045 
00046 PRIVATE struct pcitab pcitab_ti[]=
00047 {
00048         { 0x104C, 0xAC1C, 0 },          /* TI PCI1225 */
00049 
00050         { 0x0000, 0x0000, 0 }
00051 };
00052 PRIVATE char *progname;
00053 PRIVATE int debug;
00054 
00055 FORWARD _PROTOTYPE( void init, (void)                                   );
00056 FORWARD _PROTOTYPE( void hw_init, (struct port *pp)                     );
00057 FORWARD _PROTOTYPE( void map_regs, (struct port *pp, u32_t base)        );
00058 FORWARD _PROTOTYPE( void do_int, (struct port *pp)                      );
00059 FORWARD _PROTOTYPE( u8_t read_exca, (struct port *pp, int socket, int reg) );
00060 FORWARD _PROTOTYPE( void do_outb, (port_t port, u8_t value)             );
00061 FORWARD _PROTOTYPE( u8_t do_inb, (port_t port)                          );
00062 FORWARD _PROTOTYPE( void micro_delay, (unsigned long usecs)             );
00063 
00064 int main(int argc, char *argv[])
00065 {
00066         int c, r;
00067         message m;
00068 
00069         (progname=strrchr(argv[0],'/')) ? progname++ : (progname=argv[0]);
00070 
00071         debug= 0;
00072         while (c= getopt(argc, argv, "d?"), c != -1)
00073         {
00074                 switch(c)
00075                 {
00076                 case '?': panic("ti1225", "Usage: ti1225 [-d]", NO_NUM);
00077                 case 'd': debug++; break;
00078                 default: panic("ti1225", "getopt failed", NO_NUM);
00079                 }
00080         }
00081 
00082         init();
00083 
00084         for (;;)
00085         {
00086                 r= receive(ANY, &m);
00087                 if (r != OK)
00088                         panic("ti1225", "receive failed", r);
00089                 printf("ti1225: got message %u from %d\n",
00090                         m.m_type, m.m_source);
00091         }
00092         return 0;
00093 }
00094 
00095 PRIVATE void init()
00096 {
00097         int i, r, first, devind, port;
00098         u16_t vid, did;
00099 
00100         pci_init1(progname);
00101 
00102         first= 1;
00103         port= 0;
00104         for (;;)
00105         {
00106                 if (first)
00107                 {
00108                         first= 0;
00109                         r= pci_first_dev(&devind, &vid, &did);
00110                 }
00111                 else
00112                         r= pci_next_dev(&devind, &vid, &did);
00113                 if (r != 1)
00114                         break;
00115 
00116                 for (i= 0; pcitab_ti[i].vid != 0; i++)
00117                 {
00118                         if (pcitab_ti[i].vid != vid)
00119                                 continue;
00120                         if (pcitab_ti[i].did != did)
00121                                 continue;
00122                         if (pcitab_ti[i].checkclass)
00123                         {
00124                                 panic("ti1225",
00125                                 "fxp_probe: class check not implemented",
00126                                         NO_NUM);
00127                         }
00128                         break;
00129                 }
00130                 if (pcitab_ti[i].vid == 0)
00131                         continue;
00132 
00133                 pci_reserve(devind);
00134 
00135                 if (debug)
00136                         printf("ti1225: found device %04x/%04x\n", vid, did);
00137                 ports[port].p_devind= devind;
00138                 ports[port].p_flags |= PF_PRESENT;
00139                 port++;
00140                 if (port >= NR_PORTS)
00141                         break;
00142         }
00143 
00144         for (i= 0; i<NR_PORTS; i++)
00145         {
00146                 if (!(ports[i].p_flags & PF_PRESENT))
00147                         continue;
00148                 hw_init(&ports[i]);
00149         }
00150 }
00151 
00152 PRIVATE void hw_init(pp)
00153 struct port *pp;
00154 {
00155         int i, r, devind, irq, socket;
00156         u8_t v8;
00157         u16_t v16;
00158         u32_t v32;
00159 
00160         devind= pp->p_devind;
00161         if (debug)
00162                 printf("hw_init: devind = %d\n", devind);
00163 
00164         if (debug)
00165         {
00166                 v16= pci_attr_r16(devind, PCI_CR);
00167                 printf("ti1225: command register 0x%x\n", v16);
00168         }
00169 
00170         v32= pci_attr_r32(devind, TI_CB_BASEADDR);
00171         if (debug)
00172                 printf("ti1225: Cardbus/ExCA base address 0x%x\n", v32);
00173         map_regs(pp, v32);
00174         pp->csr_ptr= (struct csr *)pp->base_ptr;
00175 
00176         if (debug)
00177         {
00178                 v8= pci_attr_r8(devind, TI_PCI_BUS_NR);
00179                 printf("ti1225: PCI bus number %d\n", v8);
00180         }
00181         v8= pci_attr_r8(devind, TI_CB_BUS_NR);
00182         pp->p_cb_busnr= v8;
00183         if (debug)
00184         {
00185                 printf("ti1225: CardBus bus number %d\n", v8);
00186                 v8= pci_attr_r8(devind, TI_SO_BUS_NR);
00187                 printf("ti1225: Subordinate bus number %d\n", v8);
00188         }
00189 
00190 #if USE_INTS
00191         irq= pci_attr_r8(devind, PCI_ILR);
00192         pp->p_irq= irq;
00193         printf("ti1225 using IRQ %d\n", irq);
00194 #endif
00195 
00196         v32= pci_attr_r32(devind, TI_LEGACY_BA);
00197         v32 &= ~1;
00198         if (debug)
00199         {
00200                 printf("ti1225: PC Card 16-bit legacy-mode base address 0x%x\n",
00201                         v32);
00202         }
00203 
00204         if (v32 == 0)
00205                 panic("ti1225", "bad lagacy-mode base address 0x%x\n", v32);
00206         pp->p_exca_port= v32;
00207 
00208         if (debug)
00209         {
00210                 v32= pci_attr_r32(devind, TI_MF_ROUTE);
00211                 printf("ti1225: Multifunction routing 0x%08x\n", v32);
00212         }
00213 
00214 #if USE_INTS
00215         pp->p_hook = pp->p_irq;
00216         r= sys_irqsetpolicy(pp->p_irq, 0, &pp->p_hook);
00217         if (r != OK)
00218                 panic("ti1225","sys_irqsetpolicy failed", r);
00219 #endif
00220 
00221         /* Clear CBB_BC_INTEXCA */
00222         v16= pci_attr_r16(devind, CBB_BRIDGECTRL);
00223         if (debug)
00224                 printf("ti1225: Bridge control 0x%04x\n", v16);
00225         v16 &= ~CBB_BC_INTEXCA;
00226         pci_attr_w16(devind, CBB_BRIDGECTRL, v16);
00227 
00228         if (debug)
00229         {
00230                 v32= pci_attr_r32(devind, TI_SYSCTRL);
00231                 printf("ti1225: System Control Register 0x%08x\n", v32);
00232 
00233                 v8= pci_attr_r8(devind, TI_CARD_CTRL);
00234                 printf("ti1225: Card Control 0x%02x\n", v8);
00235 
00236                 v8= pci_attr_r8(devind, TI_DEV_CTRL);
00237                 printf("ti1225: Device Control 0x%02x\n", v8);
00238         }
00239 
00240         /* Enable socket interrupts */
00241         pp->csr_ptr->csr_mask |= CM_PWRMASK | CM_CDMASK | CM_CSTSMASK;
00242 
00243         do_int(pp);
00244 
00245 #if USE_INTS
00246         r= sys_irqenable(&pp->p_hook);
00247         if (r != OK)
00248                 panic("ti1225","unable enable interrupts", r);
00249 #endif
00250 }
00251 
00252 PRIVATE void map_regs(pp, base)
00253 struct port *pp;
00254 u32_t base;
00255 {
00256         int r;
00257         vir_bytes buf_base;
00258 
00259         buf_base= (vir_bytes)pp->buffer;
00260         if (buf_base % PAGE_SIZE)
00261                 buf_base += PAGE_SIZE-(buf_base % PAGE_SIZE);
00262         pp->base_ptr= (char *)buf_base;
00263         if (debug)
00264         {
00265                 printf("ti1225: map_regs: using %p for %p\n",
00266                         pp->base_ptr, pp->buffer);
00267         }
00268 
00269         /* Clear low order bits in base */
00270         base &= ~(u32_t)0xF;
00271 
00272         r= sys_vm_map(SELF, 1 /* map */, (vir_bytes)pp->base_ptr,
00273                 PAGE_SIZE, (phys_bytes)base);
00274         if (r != OK)
00275                 panic("ti1225", "map_regs: sys_vm_map failed", r);
00276 }
00277 
00278 PRIVATE void do_int(pp)
00279 struct port *pp;
00280 {
00281         int i, r, devind, vcc_5v, vcc_3v, vcc_Xv, vcc_Yv,
00282                 socket_5v, socket_3v, socket_Xv, socket_Yv;
00283         clock_t t0, t1;
00284         u32_t csr_event, csr_present, csr_control;
00285         u8_t v8;
00286         u16_t v16;
00287 
00288         devind= pp->p_devind;
00289         v8= pci_attr_r8(devind, TI_CARD_CTRL);
00290         if (v8 & TI_CCR_IFG)
00291         {
00292                 printf("ti1225: got functional interrupt\n", v8);
00293                 pci_attr_w8(devind, TI_CARD_CTRL, v8);
00294         }
00295 
00296         if (debug)
00297         {
00298                 printf("Socket event: 0x%x\n", pp->csr_ptr->csr_event);
00299                 printf("Socket mask: 0x%x\n", pp->csr_ptr->csr_mask);
00300         }
00301 
00302         csr_present= pp->csr_ptr->csr_present;
00303         csr_control= pp->csr_ptr->csr_control;
00304 
00305         if ((csr_present & (CP_CDETECT1|CP_CDETECT2)) != 0)
00306         {
00307                 if (debug)
00308                         printf("do_int: no card present\n");
00309                 return;
00310         }
00311         if (csr_present & CP_BADVCCREQ)
00312         {
00313                 printf("do_int: Bad Vcc request\n");
00314                 /* return; */
00315         }
00316         if (csr_present & CP_DATALOST)
00317         {
00318                 /* Do we care? */
00319                 if (debug)
00320                         printf("do_int: Data lost\n");
00321                 /* return; */
00322         }
00323         if (csr_present & CP_NOTACARD)
00324         {
00325                 printf("do_int: Not a card\n");
00326                 return;
00327         }
00328         if (debug)
00329         {
00330                 if (csr_present & CP_CBCARD)
00331                         printf("do_int: Cardbus card detected\n");
00332                 if (csr_present & CP_16BITCARD)
00333                         printf("do_int: 16-bit card detected\n");
00334         }
00335         if (csr_present & CP_PWRCYCLE)
00336         {
00337                 if (debug)
00338                         printf("do_int: powered up\n");
00339                 return;
00340         }
00341         vcc_5v= !!(csr_present & CP_5VCARD);
00342         vcc_3v= !!(csr_present & CP_3VCARD);
00343         vcc_Xv= !!(csr_present & CP_XVCARD);
00344         vcc_Yv= !!(csr_present & CP_YVCARD);
00345         if (debug)
00346         {
00347                 printf("do_int: card supports:%s%s%s%s\n",
00348                         vcc_5v ? " 5V" : "", vcc_3v ? " 3V" : "",
00349                         vcc_Xv ? " X.X V" : "", vcc_Yv ? " Y.Y V" : "");
00350         }
00351         socket_5v= !!(csr_present & CP_5VSOCKET);
00352         socket_3v= !!(csr_present & CP_3VSOCKET);
00353         socket_Xv= !!(csr_present & CP_XVSOCKET);
00354         socket_Yv= !!(csr_present & CP_YVSOCKET);
00355         if (debug)
00356         {
00357                 printf("do_int: socket supports:%s%s%s%s\n",
00358                         socket_5v ? " 5V" : "", socket_3v ? " 3V" : "",
00359                         socket_Xv ? " X.X V" : "", socket_Yv ? " Y.Y V" : "");
00360         }
00361         if (vcc_5v && socket_5v)
00362         {
00363                 csr_control= (csr_control & ~CC_VCCCTRL) | CC_VCC_5V;
00364                 pp->csr_ptr->csr_control= csr_control;
00365                 if (debug)
00366                         printf("do_int: applying 5V\n");
00367         }
00368         else if (vcc_3v && socket_3v)
00369         {
00370                 csr_control= (csr_control & ~CC_VCCCTRL) | CC_VCC_3V;
00371                 pp->csr_ptr->csr_control= csr_control;
00372                 if (debug)
00373                         printf("do_int: applying 3V\n");
00374         }
00375         else if (vcc_Xv && socket_Xv)
00376         {
00377                 csr_control= (csr_control & ~CC_VCCCTRL) | CC_VCC_XV;
00378                 pp->csr_ptr->csr_control= csr_control;
00379                 printf("do_int: applying X.X V\n");
00380         }
00381         else if (vcc_Yv && socket_Yv)
00382         {
00383                 csr_control= (csr_control & ~CC_VCCCTRL) | CC_VCC_YV;
00384                 pp->csr_ptr->csr_control= csr_control;
00385                 printf("do_int: applying Y.Y V\n");
00386         }
00387         else
00388         {
00389                 printf("do_int: socket and card are not compatible\n");
00390                 return;
00391         }
00392 
00393         csr_event= pp->csr_ptr->csr_event;
00394         if (csr_event)
00395         {
00396                 if (debug)
00397                         printf("clearing socket event\n");
00398                 pp->csr_ptr->csr_event= csr_event;
00399                 if (debug)
00400                 {
00401                         printf("Socket event (cleared): 0x%x\n",
00402                                 pp->csr_ptr->csr_event);
00403                 }
00404         }
00405 
00406         devind= pp->p_devind;
00407         v8= pci_attr_r8(devind, TI_CARD_CTRL);
00408         if (v8 & TI_CCR_IFG)
00409         {
00410                 printf("ti1225: got functional interrupt\n", v8);
00411                 pci_attr_w8(devind, TI_CARD_CTRL, v8);
00412         }
00413 
00414         if (debug)
00415         {
00416                 v8= pci_attr_r8(devind, TI_CARD_CTRL);
00417                 printf("TI_CARD_CTRL: 0x%02x\n", v8);
00418         }
00419 
00420         getuptime(&t0);
00421         do {
00422                 csr_present= pp->csr_ptr->csr_present;
00423                 if (csr_present & CP_PWRCYCLE)
00424                         break;
00425         } while (getuptime(&t1)==OK && (t1-t0) < MICROS_TO_TICKS(100000));
00426 
00427         if (!(csr_present & CP_PWRCYCLE))
00428         {
00429                 printf("do_int: not powered up?\n");
00430                 return;
00431         }
00432 
00433         /* Reset device */
00434         v16= pci_attr_r16(devind, CBB_BRIDGECTRL);
00435         v16 |= CBB_BC_CRST;
00436         pci_attr_w16(devind, CBB_BRIDGECTRL, v16);
00437 
00438         /* Wait one microsecond. Is this correct? What are the specs? */
00439         micro_delay(1);
00440 
00441         /* Clear CBB_BC_CRST */
00442         v16= pci_attr_r16(devind, CBB_BRIDGECTRL);
00443         v16 &= ~CBB_BC_CRST;
00444         pci_attr_w16(devind, CBB_BRIDGECTRL, v16);
00445 
00446         /* Wait one microsecond after clearing the reset line. Is this
00447          * correct? What are the specs?
00448          */
00449         micro_delay(1);
00450 
00451         pci_rescan_bus(pp->p_cb_busnr);
00452 
00453 #if USE_INTS
00454         r= sys_irqenable(&pp->p_hook);
00455         if (r != OK)
00456                 panic("ti1225","unable enable interrupts", r);
00457 #endif
00458 
00459 }
00460 
00461 PRIVATE u8_t read_exca(pp, socket, reg)
00462 struct port *pp;
00463 int socket;
00464 int reg;
00465 {
00466         u16_t port;
00467 
00468         port= pp->p_exca_port;
00469         if (port == 0)
00470                 panic("ti1225", "read_exca: bad port", NO_NUM);
00471         do_outb(port, socket * 0x40 + reg);
00472         return do_inb(port+1);
00473 }
00474 
00475 PRIVATE u8_t do_inb(port_t port)
00476 {
00477         int r;
00478         u32_t value;
00479 
00480         r= sys_inb(port, &value);
00481         if (r != OK)
00482                 panic("ti1225","sys_inb failed", r);
00483         return value;
00484 }
00485 
00486 PRIVATE void do_outb(port_t port, u8_t value)
00487 {
00488         int r;
00489 
00490         r= sys_outb(port, value);
00491         if (r != OK)
00492                 panic("ti1225","sys_outb failed", r);
00493 }
00494 
00495 PRIVATE void micro_delay(unsigned long usecs)
00496 {
00497         tickdelay(MICROS_TO_TICKS(usecs));
00498 }
00499 

Generated on Fri Apr 14 22:57:19 2006 for minix by  doxygen 1.4.6