ti113x.h
来自「Linux Kernel 2.6.9 for OMAP1710」· C头文件 代码 · 共 657 行 · 第 1/2 页
H
657 行
{ u32 mfunc, mfunc_old, devctl; u8 gpio3, gpio3_old; int pci_irq_status; mfunc = mfunc_old = config_readl(socket, TI122X_MFUNC); devctl = config_readb(socket, TI113X_DEVICE_CONTROL); printk(KERN_INFO "Yenta TI: socket %s, mfunc 0x%08x, devctl 0x%02x\n", pci_name(socket->dev), mfunc, devctl); /* make sure PCI interrupts are enabled before probing */ ti_init(socket); /* test PCI interrupts first. only try fixing if return value is 0! */ pci_irq_status = yenta_probe_cb_irq(socket); if (pci_irq_status) goto out; /* * We're here which means PCI interrupts are _not_ delivered. try to * find the right setting (all serial or parallel) */ printk(KERN_INFO "Yenta TI: socket %s probing PCI interrupt failed, trying to fix\n", pci_name(socket->dev)); /* for serial PCI make sure MFUNC3 is set to IRQSER */ if ((devctl & TI113X_DCR_IMODE_MASK) == TI12XX_DCR_IMODE_ALL_SERIAL) { switch (socket->dev->device) { case PCI_DEVICE_ID_TI_1250: case PCI_DEVICE_ID_TI_1251A: case PCI_DEVICE_ID_TI_1251B: case PCI_DEVICE_ID_TI_1450: case PCI_DEVICE_ID_TI_1451A: case PCI_DEVICE_ID_TI_4450: case PCI_DEVICE_ID_TI_4451: /* these chips have no IRQSER setting in MFUNC3 */ break; default: mfunc = (mfunc & ~TI122X_MFUNC3_MASK) | TI122X_MFUNC3_IRQSER; /* write down if changed, probe */ if (mfunc != mfunc_old) { config_writel(socket, TI122X_MFUNC, mfunc); pci_irq_status = yenta_probe_cb_irq(socket); if (pci_irq_status == 1) { printk(KERN_INFO "Yenta TI: socket %s all-serial interrupts ok\n", pci_name(socket->dev)); mfunc_old = mfunc; goto out; } /* not working, back to old value */ mfunc = mfunc_old; config_writel(socket, TI122X_MFUNC, mfunc); if (pci_irq_status == -1) goto out; } } /* serial PCI interrupts not working fall back to parallel */ printk(KERN_INFO "Yenta TI: socket %s falling back to parallel PCI interrupts\n", pci_name(socket->dev)); devctl &= ~TI113X_DCR_IMODE_MASK; devctl |= TI113X_DCR_IMODE_SERIAL; /* serial ISA could be right */ config_writeb(socket, TI113X_DEVICE_CONTROL, devctl); } /* parallel PCI interrupts: route INTA */ switch (socket->dev->device) { case PCI_DEVICE_ID_TI_1250: case PCI_DEVICE_ID_TI_1251A: case PCI_DEVICE_ID_TI_1251B: case PCI_DEVICE_ID_TI_1450: /* make sure GPIO3 is set to INTA */ gpio3 = gpio3_old = config_readb(socket, TI1250_GPIO3_CONTROL); gpio3 &= ~TI1250_GPIO_MODE_MASK; if (gpio3 != gpio3_old) config_writeb(socket, TI1250_GPIO3_CONTROL, gpio3); break; default: gpio3 = gpio3_old = 0; mfunc = (mfunc & ~TI122X_MFUNC0_MASK) | TI122X_MFUNC0_INTA; if (mfunc != mfunc_old) config_writel(socket, TI122X_MFUNC, mfunc); } /* time to probe again */ pci_irq_status = yenta_probe_cb_irq(socket); if (pci_irq_status == 1) { mfunc_old = mfunc; printk(KERN_INFO "Yenta TI: socket %s parallel PCI interrupts ok\n", pci_name(socket->dev)); } else { /* not working, back to old value */ mfunc = mfunc_old; config_writel(socket, TI122X_MFUNC, mfunc); if (gpio3 != gpio3_old) config_writeb(socket, TI1250_GPIO3_CONTROL, gpio3_old); }out: if (pci_irq_status < 1) { socket->cb_irq = 0; printk(KERN_INFO "Yenta TI: socket %s no PCI interrupts. Fish. Please report.\n", pci_name(socket->dev)); }}/* * ties INTA and INTB together. also changes the devices irq to that of * the function 0 device. call from func1 only. * returns 1 if INTRTIE changed, 0 otherwise. */static int ti12xx_tie_interrupts(struct yenta_socket *socket, int *old_irq){ struct pci_dev *func0; u32 sysctl; sysctl = config_readl(socket, TI113X_SYSTEM_CONTROL); if (sysctl & TI122X_SCR_INTRTIE) return 0; /* find func0 device */ func0 = pci_get_slot(socket->dev->bus, socket->dev->devfn & ~0x07); if (!func0) return 0; /* change the interrupt to match func0, tie 'em up */ *old_irq = socket->cb_irq; socket->cb_irq = socket->dev->irq = func0->irq; sysctl |= TI122X_SCR_INTRTIE; config_writel(socket, TI113X_SYSTEM_CONTROL, sysctl); pci_dev_put(func0); return 1;}/* undo what ti12xx_tie_interrupts() did */static void ti12xx_untie_interrupts(struct yenta_socket *socket, int old_irq){ u32 sysctl = config_readl(socket, TI113X_SYSTEM_CONTROL); sysctl &= ~TI122X_SCR_INTRTIE; config_writel(socket, TI113X_SYSTEM_CONTROL, sysctl); socket->cb_irq = socket->dev->irq = old_irq;}/* * irqrouting for func1, plays with INTB routing * only touches MFUNC for INTB routing. all other bits are taken * care of in func0 already. */static void ti12xx_irqroute_func1(struct yenta_socket *socket){ u32 mfunc, mfunc_old, devctl; int pci_irq_status; mfunc = mfunc_old = config_readl(socket, TI122X_MFUNC); devctl = config_readb(socket, TI113X_DEVICE_CONTROL); printk(KERN_INFO "Yenta TI: socket %s, mfunc 0x%08x, devctl 0x%02x\n", pci_name(socket->dev), mfunc, devctl); /* make sure PCI interrupts are enabled before probing */ ti_init(socket); /* test PCI interrupts first. only try fixing if return value is 0! */ pci_irq_status = yenta_probe_cb_irq(socket); if (pci_irq_status) goto out; /* * We're here which means PCI interrupts are _not_ delivered. try to * find the right setting */ printk(KERN_INFO "Yenta TI: socket %s probing PCI interrupt failed, trying to fix\n", pci_name(socket->dev)); /* if all serial: set INTRTIE, probe again */ if ((devctl & TI113X_DCR_IMODE_MASK) == TI12XX_DCR_IMODE_ALL_SERIAL) { int old_irq; if (ti12xx_tie_interrupts(socket, &old_irq)) { pci_irq_status = yenta_probe_cb_irq(socket); if (pci_irq_status == 1) { printk(KERN_INFO "Yenta TI: socket %s all-serial interrupts, tied ok\n", pci_name(socket->dev)); goto out; } ti12xx_untie_interrupts(socket, old_irq); } } /* parallel PCI: route INTB, probe again */ else { int old_irq; switch (socket->dev->device) { case PCI_DEVICE_ID_TI_1250: /* the 1250 has one pin for IRQSER/INTB depending on devctl */ break; case PCI_DEVICE_ID_TI_1251A: case PCI_DEVICE_ID_TI_1251B: case PCI_DEVICE_ID_TI_1450: /* * those have a pin for IRQSER/INTB plus INTB in MFUNC0 * we alread probed the shared pin, now go for MFUNC0 */ mfunc = (mfunc & ~TI122X_MFUNC0_MASK) | TI125X_MFUNC0_INTB; break; default: mfunc = (mfunc & ~TI122X_MFUNC1_MASK) | TI122X_MFUNC1_INTB; break; } /* write, probe */ if (mfunc != mfunc_old) { config_writel(socket, TI122X_MFUNC, mfunc); pci_irq_status = yenta_probe_cb_irq(socket); if (pci_irq_status == 1) { printk(KERN_INFO "Yenta TI: socket %s parallel PCI interrupts ok\n", pci_name(socket->dev)); goto out; } mfunc = mfunc_old; config_writel(socket, TI122X_MFUNC, mfunc); if (pci_irq_status == -1) goto out; } /* still nothing: set INTRTIE */ if (ti12xx_tie_interrupts(socket, &old_irq)) { pci_irq_status = yenta_probe_cb_irq(socket); if (pci_irq_status == 1) { printk(KERN_INFO "Yenta TI: socket %s parallel PCI interrupts, tied ok\n", pci_name(socket->dev)); goto out; } ti12xx_untie_interrupts(socket, old_irq); } }out: if (pci_irq_status < 1) { socket->cb_irq = 0; printk(KERN_INFO "Yenta TI: socket %s no PCI interrupts. Fish. Please report.\n", pci_name(socket->dev)); }}static int ti12xx_override(struct yenta_socket *socket){ u32 val; /* make sure that memory burst is active */ val = config_readl(socket, TI113X_SYSTEM_CONTROL); if (!(val & TI122X_SCR_MRBURSTUP)) { printk(KERN_INFO "Yenta: Enabling burst memory read transactions\n"); val |= TI122X_SCR_MRBURSTUP; config_writel(socket, TI113X_SYSTEM_CONTROL, val); } /* * for EnE bridges only: clear testbit TLTEnable. this makes the * RME Hammerfall DSP sound card working. */ if (socket->dev->vendor == PCI_VENDOR_ID_ENE) { u8 test_c9 = config_readb(socket, ENE_TEST_C9); test_c9 &= ~ENE_TEST_C9_TLTENABLE; config_writeb(socket, ENE_TEST_C9, test_c9); } /* * Yenta expects controllers to use CSCINT to route * CSC interrupts to PCI rather than INTVAL. */ val = config_readb(socket, TI1250_DIAGNOSTIC); printk(KERN_INFO "Yenta: Using %s to route CSC interrupts to PCI\n", (val & TI1250_DIAG_PCI_CSC) ? "CSCINT" : "INTVAL"); printk(KERN_INFO "Yenta: Routing CardBus interrupts to %s\n", (val & TI1250_DIAG_PCI_IREQ) ? "PCI" : "ISA"); /* do irqrouting, depending on function */ if (PCI_FUNC(socket->dev->devfn) == 0) ti12xx_irqroute_func0(socket); else ti12xx_irqroute_func1(socket); return ti_override(socket);}static int ti1250_override(struct yenta_socket *socket){ u8 old, diag; old = config_readb(socket, TI1250_DIAGNOSTIC); diag = old & ~(TI1250_DIAG_PCI_CSC | TI1250_DIAG_PCI_IREQ); if (socket->cb_irq) diag |= TI1250_DIAG_PCI_CSC | TI1250_DIAG_PCI_IREQ; if (diag != old) { printk(KERN_INFO "Yenta: adjusting diagnostic: %02x -> %02x\n", old, diag); config_writeb(socket, TI1250_DIAGNOSTIC, diag); } return ti12xx_override(socket);}#endif /* CONFIG_CARDBUS */#endif /* _LINUX_TI113X_H */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?