[PATCH] rbtx4938: Fix secondary PCIC and glue internal NICs

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



* Fix pci ops for secondary PCIC
* Do not reserve 1MB for PCI MEM region (leave PCIBIOS_MIN_MEM zero)
* Use NETDEV_REGISTER event to provide ethernet addresses for internal
  NICs (tc35815 driver)
* Check return value of early_read_config_word()

Signed-off-by: Atsushi Nemoto <anemo@xxxxxxxxxxxxx>
---
 arch/mips/pci/ops-tx4938.c                |   60 ++++++++++++++++------------
 arch/mips/tx4938/toshiba_rbtx4938/setup.c |   56 ++++++++++++++++----------
 2 files changed, 72 insertions(+), 44 deletions(-)

diff --git a/arch/mips/pci/ops-tx4938.c b/arch/mips/pci/ops-tx4938.c
index 4450070..db435bf 100644
--- a/arch/mips/pci/ops-tx4938.c
+++ b/arch/mips/pci/ops-tx4938.c
@@ -46,50 +46,61 @@ struct resource tx4938_pcic1_pci_mem_res
 	.flags	= IORESOURCE_MEM
 };
 
-static int mkaddr(int bus, int dev_fn, int where, int *flagsp)
+static int mkaddr(int bus, int dev_fn, int where,
+		  struct tx4938_pcic_reg *pcicptr)
 {
 	if (bus > 0) {
 		/* Type 1 configuration */
-		tx4938_pcicptr->g2pcfgadrs = ((bus & 0xff) << 0x10) |
+		pcicptr->g2pcfgadrs = ((bus & 0xff) << 0x10) |
 		    ((dev_fn & 0xff) << 0x08) | (where & 0xfc) | 1;
 	} else {
 		if (dev_fn >= PCI_DEVFN(TX4938_PCIC_MAX_DEVNU, 0))
 			return -1;
 
 		/* Type 0 configuration */
-		tx4938_pcicptr->g2pcfgadrs = ((bus & 0xff) << 0x10) |
+		pcicptr->g2pcfgadrs = ((bus & 0xff) << 0x10) |
 		    ((dev_fn & 0xff) << 0x08) | (where & 0xfc);
 	}
 	/* clear M_ABORT and Disable M_ABORT Int. */
-	tx4938_pcicptr->pcistatus =
-	    (tx4938_pcicptr->pcistatus & 0x0000ffff) |
+	pcicptr->pcistatus =
+	    (pcicptr->pcistatus & 0x0000ffff) |
 	    (PCI_STATUS_REC_MASTER_ABORT << 16);
-	tx4938_pcicptr->pcimask &= ~PCI_STATUS_REC_MASTER_ABORT;
+	pcicptr->pcimask &= ~PCI_STATUS_REC_MASTER_ABORT;
 
 	return 0;
 }
 
-static int check_abort(int flags)
+static int check_abort(struct tx4938_pcic_reg *pcicptr)
 {
 	int code = PCIBIOS_SUCCESSFUL;
 	/* wait write cycle completion before checking error status */
-	while (tx4938_pcicptr->pcicstatus & TX4938_PCIC_PCICSTATUS_IWB)
+	while (pcicptr->pcicstatus & TX4938_PCIC_PCICSTATUS_IWB)
 				;
-	if (tx4938_pcicptr->pcistatus & (PCI_STATUS_REC_MASTER_ABORT << 16)) {
-		tx4938_pcicptr->pcistatus =
-		    (tx4938_pcicptr->
+	if (pcicptr->pcistatus & (PCI_STATUS_REC_MASTER_ABORT << 16)) {
+		pcicptr->pcistatus =
+		    (pcicptr->
 		     pcistatus & 0x0000ffff) | (PCI_STATUS_REC_MASTER_ABORT
 						<< 16);
-		tx4938_pcicptr->pcimask |= PCI_STATUS_REC_MASTER_ABORT;
+		pcicptr->pcimask |= PCI_STATUS_REC_MASTER_ABORT;
 		code = PCIBIOS_DEVICE_NOT_FOUND;
 	}
 	return code;
 }
 
+extern struct pci_controller tx4938_pci_controller[];
+extern struct tx4938_pcic_reg *get_tx4938_pcicptr(int ch);
+
+static struct tx4938_pcic_reg *pci_bus_to_pcicptr(struct pci_bus *bus)
+{
+	struct pci_controller *channel = bus->sysdata;
+	return get_tx4938_pcicptr(channel - &tx4938_pci_controller[0]);
+}
+
 static int tx4938_pcibios_read_config(struct pci_bus *bus, unsigned int devfn,
 					int where, int size, u32 * val)
 {
-	int flags, retval, dev, busno, func;
+	int retval, dev, busno, func;
+	struct tx4938_pcic_reg *pcicptr = pci_bus_to_pcicptr(bus);
 
 	dev = PCI_SLOT(devfn);
 	func = PCI_FUNC(devfn);
@@ -101,12 +112,12 @@ static int tx4938_pcibios_read_config(st
 		busno = 0;
 	}
 
-	if (mkaddr(busno, devfn, where, &flags))
+	if (mkaddr(busno, devfn, where, pcicptr))
 		return -1;
 
 	switch (size) {
 	case 1:
-		*val = *(volatile u8 *) ((unsigned long) & tx4938_pcicptr->g2pcfgdata |
+		*val = *(volatile u8 *) ((unsigned long) & pcicptr->g2pcfgdata |
 #ifdef __BIG_ENDIAN
 			      ((where & 3) ^ 3));
 #else
@@ -114,7 +125,7 @@ static int tx4938_pcibios_read_config(st
 #endif
 		break;
 	case 2:
-		*val = *(volatile u16 *) ((unsigned long) & tx4938_pcicptr->g2pcfgdata |
+		*val = *(volatile u16 *) ((unsigned long) & pcicptr->g2pcfgdata |
 #ifdef __BIG_ENDIAN
 				((where & 3) ^ 2));
 #else
@@ -122,11 +133,11 @@ static int tx4938_pcibios_read_config(st
 #endif
 		break;
 	case 4:
-		*val = tx4938_pcicptr->g2pcfgdata;
+		*val = pcicptr->g2pcfgdata;
 		break;
 	}
 
-	retval = check_abort(flags);
+	retval = check_abort(pcicptr);
 	if (retval == PCIBIOS_DEVICE_NOT_FOUND)
 		*val = 0xffffffff;
 
@@ -136,7 +147,8 @@ static int tx4938_pcibios_read_config(st
 static int tx4938_pcibios_write_config(struct pci_bus *bus, unsigned int devfn, int where,
 						int size, u32 val)
 {
-	int flags, dev, busno, func;
+	int dev, busno, func;
+	struct tx4938_pcic_reg *pcicptr = pci_bus_to_pcicptr(bus);
 
 	busno = bus->number;
 	dev = PCI_SLOT(devfn);
@@ -149,12 +161,12 @@ static int tx4938_pcibios_write_config(s
 		busno = 0;
 	}
 
-	if (mkaddr(busno, devfn, where, &flags))
+	if (mkaddr(busno, devfn, where, pcicptr))
 		return -1;
 
 	switch (size) {
 	case 1:
-		*(volatile u8 *) ((unsigned long) & tx4938_pcicptr->g2pcfgdata |
+		*(volatile u8 *) ((unsigned long) & pcicptr->g2pcfgdata |
 #ifdef __BIG_ENDIAN
 			  ((where & 3) ^ 3)) = val;
 #else
@@ -162,7 +174,7 @@ static int tx4938_pcibios_write_config(s
 #endif
 		break;
 	case 2:
-		*(volatile u16 *) ((unsigned long) & tx4938_pcicptr->g2pcfgdata |
+		*(volatile u16 *) ((unsigned long) & pcicptr->g2pcfgdata |
 #ifdef __BIG_ENDIAN
 			((where & 0x3) ^ 0x2)) = val;
 #else
@@ -170,11 +182,11 @@ static int tx4938_pcibios_write_config(s
 #endif
 		break;
 	case 4:
-		tx4938_pcicptr->g2pcfgdata = val;
+		pcicptr->g2pcfgdata = val;
 		break;
 	}
 
-	return check_abort(flags);
+	return check_abort(pcicptr);
 }
 
 struct pci_ops tx4938_pci_ops = {
diff --git a/arch/mips/tx4938/toshiba_rbtx4938/setup.c b/arch/mips/tx4938/toshiba_rbtx4938/setup.c
index 66163ba..9446dc9 100644
--- a/arch/mips/tx4938/toshiba_rbtx4938/setup.c
+++ b/arch/mips/tx4938/toshiba_rbtx4938/setup.c
@@ -20,6 +20,7 @@
 #include <linux/console.h>
 #include <linux/pci.h>
 #include <linux/pm.h>
+#include <linux/netdevice.h>
 
 #include <asm/wbflush.h>
 #include <asm/reboot.h>
@@ -348,7 +349,7 @@ static struct pci_dev *fake_pci_dev(stru
 	static struct pci_dev dev;
 	static struct pci_bus bus;
 
-	dev.sysdata = (void *)hose;
+	dev.sysdata = bus.sysdata = hose;
 	dev.devfn = devfn;
 	bus.number = busnr;
 	bus.ops = hose->pci_ops;
@@ -381,8 +382,10 @@ int txboard_pci66_check(struct pci_contr
 	printk("PCI: Checking 66MHz capabilities...\n");
 
 	for (pci_devfn=devfn_start; pci_devfn<devfn_stop; pci_devfn++) {
-		early_read_config_word(hose, top_bus, current_bus, pci_devfn,
-				       PCI_VENDOR_ID, &vid);
+		if (early_read_config_word(hose, top_bus, current_bus,
+					   pci_devfn, PCI_VENDOR_ID,
+					   &vid) != PCIBIOS_SUCCESSFUL)
+			continue;
 
 		if (vid == 0xffff) continue;
 
@@ -459,7 +462,6 @@ static int __init tx4938_pcibios_init(vo
 	int extarb = !(tx4938_ccfgptr->ccfg & TX4938_CCFG_PCIXARB);
 
 	PCIBIOS_MIN_IO = 0x00001000UL;
-	PCIBIOS_MIN_MEM = 0x01000000UL;
 
 	mem_base[0] = txboard_request_phys_region_shrink(&mem_size[0]);
 	io_base[0] = txboard_request_phys_region_shrink(&io_size[0]);
@@ -606,26 +608,11 @@ static int rbtx4938_spi_cs_func(int chip
 #ifdef CONFIG_PCI
 extern int spi_eeprom_read(int chipid, int address, unsigned char *buf, int len);
 
-int rbtx4938_get_tx4938_ethaddr(struct pci_dev *dev, unsigned char *addr)
+static int rbtx4938_get_tx4938_ethaddr(int ch, unsigned char *addr)
 {
-	struct pci_controller *channel = (struct pci_controller *)dev->bus->sysdata;
 	static unsigned char dat[17];
 	static int read_dat = 0;
-	int ch = 0;
 
-	if (channel != &tx4938_pci_controller[1])
-		return -ENODEV;
-	/* TX4938 PCIC1 */
-	switch (PCI_SLOT(dev->devfn)) {
-	case TX4938_PCIC_IDSEL_AD_TO_SLOT(31):
-		ch = 0;
-		break;
-	case TX4938_PCIC_IDSEL_AD_TO_SLOT(30):
-		ch = 1;
-		break;
-	default:
-		return -ENODEV;
-	}
 	if (!read_dat) {
 		unsigned char sum;
 		int i;
@@ -646,6 +633,35 @@ int rbtx4938_get_tx4938_ethaddr(struct p
 	memcpy(addr, &dat[4 + 6 * ch], 6);
 	return 0;
 }
+
+static int rbtx4938_netdev_event(struct notifier_block *this,
+				 unsigned long event,
+				 void *ptr)
+{
+	struct net_device *dev = (struct net_device *)ptr;
+	if (event == NETDEV_REGISTER) {
+		int ch = -1;
+		if (dev->irq == RBTX4938_IRQ_IRC + TX4938_IR_ETH0)
+			ch = 0;
+		else if (dev->irq == RBTX4938_IRQ_IRC + TX4938_IR_ETH1)
+			ch = 1;
+		if (ch >= 0)
+			rbtx4938_get_tx4938_ethaddr(ch, dev->dev_addr);
+	}
+	return NOTIFY_DONE;
+}
+
+static struct notifier_block rbtx4938_netdev_notifier = {
+	.notifier_call = rbtx4938_netdev_event,
+};
+
+static int __init rbtx4938_setup_eth(void)
+{
+	if (tx4938_ccfgptr->pcfg & (TX4938_PCFG_ETH0_SEL|TX4938_PCFG_ETH1_SEL))
+		register_netdevice_notifier(&rbtx4938_netdev_notifier);
+	return 0;
+}
+device_initcall(rbtx4938_setup_eth);
 #endif /* CONFIG_PCI */
 
 extern void __init txx9_spi_init(unsigned long base, int (*cs_func)(int chipid, int on));


[Index of Archives]     [Linux MIPS Home]     [LKML Archive]     [Linux ARM Kernel]     [Linux ARM]     [Linux]     [Git]     [Yosemite News]     [Linux SCSI]     [Linux Hams]

  Powered by Linux