ti113x.h

来自「linux 内核源代码」· C头文件 代码 · 共 944 行 · 第 1/2 页

H
944
字号
static int ti12xx_tie_interrupts(struct yenta_socket *socket, int *old_irq){	u32 sysctl;	int ret;	sysctl = config_readl(socket, TI113X_SYSTEM_CONTROL);	if (sysctl & TI122X_SCR_INTRTIE)		return 0;	/* align */	ret = ti12xx_align_irqs(socket, old_irq);	if (!ret)		return 0;	/* tie */	sysctl |= TI122X_SCR_INTRTIE;	config_writel(socket, TI113X_SYSTEM_CONTROL, sysctl);	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, sysctl;	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);	/* if IRQs are configured as tied, align irq of func1 with func0 */	sysctl = config_readl(socket, TI113X_SYSTEM_CONTROL);	if (sysctl & TI122X_SCR_INTRTIE)		ti12xx_align_irqs(socket, NULL);	/* 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));	}}/* Returns true value if the second slot of a two-slot controller is empty */static int ti12xx_2nd_slot_empty(struct yenta_socket *socket){	struct pci_dev *func;	struct yenta_socket *slot2;	int devfn;	unsigned int state;	int ret = 1;	u32 sysctl;	/* catch the two-slot controllers */	switch (socket->dev->device) {	case PCI_DEVICE_ID_TI_1220:	case PCI_DEVICE_ID_TI_1221:	case PCI_DEVICE_ID_TI_1225:	case PCI_DEVICE_ID_TI_1251A:	case PCI_DEVICE_ID_TI_1251B:	case PCI_DEVICE_ID_TI_1420:	case PCI_DEVICE_ID_TI_1450:	case PCI_DEVICE_ID_TI_1451A:	case PCI_DEVICE_ID_TI_1520:	case PCI_DEVICE_ID_TI_1620:	case PCI_DEVICE_ID_TI_4520:	case PCI_DEVICE_ID_TI_4450:	case PCI_DEVICE_ID_TI_4451:		/*		 * there are way more, but they need to be added in yenta_socket.c		 * and pci_ids.h first anyway.		 */		break;	case PCI_DEVICE_ID_TI_XX12:	case PCI_DEVICE_ID_TI_X515:	case PCI_DEVICE_ID_TI_X420:	case PCI_DEVICE_ID_TI_X620:	case PCI_DEVICE_ID_TI_XX21_XX11:	case PCI_DEVICE_ID_TI_7410:	case PCI_DEVICE_ID_TI_7610:		/*		 * those are either single or dual slot CB with additional functions		 * like 1394, smartcard reader, etc. check the TIEALL flag for them		 * the TIEALL flag binds the IRQ of all functions toghether.		 * we catch the single slot variants later.		 */		sysctl = config_readl(socket, TI113X_SYSTEM_CONTROL);		if (sysctl & TIXX21_SCR_TIEALL)			return 0;		break;	/* single-slot controllers have the 2nd slot empty always :) */	default:		return 1;	}	/* get other slot */	devfn = socket->dev->devfn & ~0x07;	func = pci_get_slot(socket->dev->bus,	                    (socket->dev->devfn & 0x07) ? devfn : devfn | 0x01);	if (!func)		return 1;	/*	 * check that the device id of both slots match. this is needed for the	 * XX21 and the XX11 controller that share the same device id for single	 * and dual slot controllers. return '2nd slot empty'. we already checked	 * if the interrupt is tied to another function.	 */	if (socket->dev->device != func->device)		goto out;	slot2 = pci_get_drvdata(func);	if (!slot2)		goto out;	/* check state */	yenta_get_status(&socket->socket, &state);	if (state & SS_DETECT) {		ret = 0;		goto out;	}out:	pci_dev_put(func);	return ret;}/* * TI specifiy parts for the power hook. * * some TI's with some CB's produces interrupt storm on power on. it has been * seen with atheros wlan cards on TI1225 and TI1410. solution is simply to * disable any CB interrupts during this time. */static int ti12xx_power_hook(struct pcmcia_socket *sock, int operation){	struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket);	u32 mfunc, devctl, sysctl;	u8 gpio3;	/* only POWER_PRE and POWER_POST are interesting */	if ((operation != HOOK_POWER_PRE) && (operation != HOOK_POWER_POST))		return 0;	devctl = config_readb(socket, TI113X_DEVICE_CONTROL);	sysctl = config_readl(socket, TI113X_SYSTEM_CONTROL);	mfunc = config_readl(socket, TI122X_MFUNC);	/*	 * all serial/tied: only disable when modparm set. always doing it	 * would mean a regression for working setups 'cos it disables the	 * interrupts for both both slots on 2-slot controllers	 * (and users of single slot controllers where it's save have to	 * live with setting the modparm, most don't have to anyway)	 */	if (((devctl & TI113X_DCR_IMODE_MASK) == TI12XX_DCR_IMODE_ALL_SERIAL) &&	    (pwr_irqs_off || ti12xx_2nd_slot_empty(socket))) {		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:			if (operation == HOOK_POWER_PRE)				mfunc = (mfunc & ~TI122X_MFUNC3_MASK);			else				mfunc = (mfunc & ~TI122X_MFUNC3_MASK) | TI122X_MFUNC3_IRQSER;		}		return 0;	}	/* do the job differently for func0/1 */	if ((PCI_FUNC(socket->dev->devfn) == 0) ||	    ((sysctl & TI122X_SCR_INTRTIE) &&	     (pwr_irqs_off || ti12xx_2nd_slot_empty(socket)))) {		/* some bridges are different */		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:			/* those oldies use gpio3 for INTA */			gpio3 = config_readb(socket, TI1250_GPIO3_CONTROL);			if (operation == HOOK_POWER_PRE)				gpio3 = (gpio3 & ~TI1250_GPIO_MODE_MASK) | 0x40;			else				gpio3 &= ~TI1250_GPIO_MODE_MASK;			config_writeb(socket, TI1250_GPIO3_CONTROL, gpio3);			break;		default:			/* all new bridges are the same */			if (operation == HOOK_POWER_PRE)				mfunc &= ~TI122X_MFUNC0_MASK;			else				mfunc |= TI122X_MFUNC0_INTA;			config_writel(socket, TI122X_MFUNC, mfunc);		}	} else {		switch (socket->dev->device) {		case PCI_DEVICE_ID_TI_1251A:		case PCI_DEVICE_ID_TI_1251B:		case PCI_DEVICE_ID_TI_1450:			/* those have INTA elsewhere and INTB in MFUNC0 */			if (operation == HOOK_POWER_PRE)				mfunc &= ~TI122X_MFUNC0_MASK;			else				mfunc |= TI125X_MFUNC0_INTB;			config_writel(socket, TI122X_MFUNC, mfunc);			break;		default:			/* all new bridges are the same */			if (operation == HOOK_POWER_PRE)				mfunc &= ~TI122X_MFUNC1_MASK;			else				mfunc |= TI122X_MFUNC1_INTB;			config_writel(socket, TI122X_MFUNC, mfunc);		}	}	return 0;}static int ti12xx_override(struct yenta_socket *socket){	u32 val, val_orig;	/* make sure that memory burst is active */	val_orig = val = config_readl(socket, TI113X_SYSTEM_CONTROL);	if (disable_clkrun && PCI_FUNC(socket->dev->devfn) == 0) {		printk(KERN_INFO "Yenta: Disabling CLKRUN feature\n");		val |= TI113X_SCR_KEEPCLK;	}	if (!(val & TI122X_SCR_MRBURSTUP)) {		printk(KERN_INFO "Yenta: Enabling burst memory read transactions\n");		val |= TI122X_SCR_MRBURSTUP;	}	if (val_orig != val)		config_writel(socket, TI113X_SYSTEM_CONTROL, val);	/*	 * 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);	/* install power hook */	socket->socket.power_hook = ti12xx_power_hook;	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);}/** * EnE specific part. EnE bridges are register compatible with TI bridges but * have their own test registers and more important their own little problems. * Some fixup code to make everybody happy (TM). */#ifdef CONFIG_YENTA_ENE_TUNE/* * set/clear various test bits: * Defaults to clear the bit. * - mask (u8) defines what bits to change * - bits (u8) is the values to change them to * -> it's * 	current = (current & ~mask) | bits *//* pci ids of devices that wants to have the bit set */#define DEVID(_vend,_dev,_subvend,_subdev,mask,bits) {		\		.vendor		= _vend,			\		.device		= _dev,				\		.subvendor	= _subvend,			\		.subdevice	= _subdev,			\		.driver_data	= ((mask) << 8 | (bits)),	\	}static struct pci_device_id ene_tune_tbl[] = {	/* Echo Audio products based on motorola DSP56301 and DSP56361 */	DEVID(PCI_VENDOR_ID_MOTOROLA, 0x1801, 0xECC0, PCI_ANY_ID,		ENE_TEST_C9_TLTENABLE | ENE_TEST_C9_PFENABLE, ENE_TEST_C9_TLTENABLE),	DEVID(PCI_VENDOR_ID_MOTOROLA, 0x3410, 0xECC0, PCI_ANY_ID,		ENE_TEST_C9_TLTENABLE | ENE_TEST_C9_PFENABLE, ENE_TEST_C9_TLTENABLE),	{}};static void ene_tune_bridge(struct pcmcia_socket *sock, struct pci_bus *bus){	struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket);	struct pci_dev *dev;	struct pci_device_id *id = NULL;	u8 test_c9, old_c9, mask, bits;	list_for_each_entry(dev, &bus->devices, bus_list) {		id = (struct pci_device_id *) pci_match_id(ene_tune_tbl, dev);		if (id)			break;	}	test_c9 = old_c9 = config_readb(socket, ENE_TEST_C9);	if (id) {		mask = (id->driver_data >> 8) & 0xFF;		bits = id->driver_data & 0xFF;		test_c9 = (test_c9 & ~mask) | bits;	}	else		/* default to clear TLTEnable bit, old behaviour */		test_c9 &= ~ENE_TEST_C9_TLTENABLE;	printk(KERN_INFO "yenta EnE: chaning testregister 0xC9, %02x -> %02x\n", old_c9, test_c9);	config_writeb(socket, ENE_TEST_C9, test_c9);}static int ene_override(struct yenta_socket *socket){	/* install tune_bridge() function */	socket->socket.tune_bridge = ene_tune_bridge;	return ti1250_override(socket);}#else#  define ene_override ti1250_override#endif /* !CONFIG_YENTA_ENE_TUNE */#endif /* _LINUX_TI113X_H */

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?