diff options
Diffstat (limited to 'drivers/pcmcia/yenta_socket.c')
| -rw-r--r-- | drivers/pcmcia/yenta_socket.c | 47 | 
1 files changed, 24 insertions, 23 deletions
diff --git a/drivers/pcmcia/yenta_socket.c b/drivers/pcmcia/yenta_socket.c index 0347a29f297b..f0997c36c9b7 100644 --- a/drivers/pcmcia/yenta_socket.c +++ b/drivers/pcmcia/yenta_socket.c @@ -72,6 +72,7 @@ static inline void cb_writel(struct yenta_socket *socket, unsigned reg, u32 val)  {  	debug("%p %04x %08x\n", socket, reg, val);  	writel(val, socket->base + reg); +	readl(socket->base + reg); /* avoid problems with PCI write posting */  }  static inline u8 config_readb(struct yenta_socket *socket, unsigned offset) @@ -136,6 +137,7 @@ static inline void exca_writeb(struct yenta_socket *socket, unsigned reg, u8 val  {  	debug("%p %04x %02x\n", socket, reg, val);  	writeb(val, socket->base + 0x800 + reg); +	readb(socket->base + 0x800 + reg); /* PCI write posting... */  }  static void exca_writew(struct yenta_socket *socket, unsigned reg, u16 val) @@ -143,6 +145,10 @@ static void exca_writew(struct yenta_socket *socket, unsigned reg, u16 val)  	debug("%p %04x %04x\n", socket, reg, val);  	writeb(val, socket->base + 0x800 + reg);  	writeb(val >> 8, socket->base + 0x800 + reg + 1); + +	/* PCI write posting... */ +	readb(socket->base + 0x800 + reg); +	readb(socket->base + 0x800 + reg + 1);  }  /* @@ -667,7 +673,7 @@ static int yenta_search_res(struct yenta_socket *socket, struct resource *res,  	return 0;  } -static void yenta_allocate_res(struct yenta_socket *socket, int nr, unsigned type, int addr_start, int addr_end) +static int yenta_allocate_res(struct yenta_socket *socket, int nr, unsigned type, int addr_start, int addr_end)  {  	struct resource *root, *res;  	struct pci_bus_region region; @@ -676,7 +682,7 @@ static void yenta_allocate_res(struct yenta_socket *socket, int nr, unsigned typ  	res = socket->dev->resource + PCI_BRIDGE_RESOURCES + nr;  	/* Already allocated? */  	if (res->parent) -		return; +		return 0;  	/* The granularity of the memory limit is 4kB, on IO it's 4 bytes */  	mask = ~0xfff; @@ -692,7 +698,7 @@ static void yenta_allocate_res(struct yenta_socket *socket, int nr, unsigned typ  		pcibios_bus_to_resource(socket->dev, res, ®ion);  		root = pci_find_parent_resource(socket->dev, res);  		if (root && (request_resource(root, res) == 0)) -			return; +			return 0;  		printk(KERN_INFO "yenta %s: Preassigned resource %d busy or not available, reconfiguring...\n",  				pci_name(socket->dev), nr);  	} @@ -700,35 +706,27 @@ static void yenta_allocate_res(struct yenta_socket *socket, int nr, unsigned typ  	if (type & IORESOURCE_IO) {  		if ((yenta_search_res(socket, res, BRIDGE_IO_MAX)) ||  		    (yenta_search_res(socket, res, BRIDGE_IO_ACC)) || -		    (yenta_search_res(socket, res, BRIDGE_IO_MIN))) { -			config_writel(socket, addr_start, res->start); -			config_writel(socket, addr_end, res->end); -			return; -		} +		    (yenta_search_res(socket, res, BRIDGE_IO_MIN))) +			return 1;  	} else {  		if (type & IORESOURCE_PREFETCH) {  			if ((yenta_search_res(socket, res, BRIDGE_MEM_MAX)) ||  			    (yenta_search_res(socket, res, BRIDGE_MEM_ACC)) || -			    (yenta_search_res(socket, res, BRIDGE_MEM_MIN))) { -				config_writel(socket, addr_start, res->start); -				config_writel(socket, addr_end, res->end); -				return; -			} +			    (yenta_search_res(socket, res, BRIDGE_MEM_MIN))) +				return 1;  			/* Approximating prefetchable by non-prefetchable */  			res->flags = IORESOURCE_MEM;  		}  		if ((yenta_search_res(socket, res, BRIDGE_MEM_MAX)) ||  		    (yenta_search_res(socket, res, BRIDGE_MEM_ACC)) || -		    (yenta_search_res(socket, res, BRIDGE_MEM_MIN))) { -			config_writel(socket, addr_start, res->start); -			config_writel(socket, addr_end, res->end); -			return; -		} +		    (yenta_search_res(socket, res, BRIDGE_MEM_MIN))) +			return 1;  	}  	printk(KERN_INFO "yenta %s: no resource of type %x available, trying to continue...\n",  	       pci_name(socket->dev), type);  	res->start = res->end = res->flags = 0; +	return 0;  }  /* @@ -736,14 +734,17 @@ static void yenta_allocate_res(struct yenta_socket *socket, int nr, unsigned typ   */  static void yenta_allocate_resources(struct yenta_socket *socket)  { -	yenta_allocate_res(socket, 0, IORESOURCE_IO, +	int program = 0; +	program += yenta_allocate_res(socket, 0, IORESOURCE_IO,  			   PCI_CB_IO_BASE_0, PCI_CB_IO_LIMIT_0); -	yenta_allocate_res(socket, 1, IORESOURCE_IO, +	program += yenta_allocate_res(socket, 1, IORESOURCE_IO,  			   PCI_CB_IO_BASE_1, PCI_CB_IO_LIMIT_1); -	yenta_allocate_res(socket, 2, IORESOURCE_MEM|IORESOURCE_PREFETCH, +	program += yenta_allocate_res(socket, 2, IORESOURCE_MEM|IORESOURCE_PREFETCH,  			   PCI_CB_MEMORY_BASE_0, PCI_CB_MEMORY_LIMIT_0); -	yenta_allocate_res(socket, 3, IORESOURCE_MEM, +	program += yenta_allocate_res(socket, 3, IORESOURCE_MEM,  			   PCI_CB_MEMORY_BASE_1, PCI_CB_MEMORY_LIMIT_1); +	if (program) +		pci_setup_cardbus(socket->dev->subordinate);  } @@ -758,7 +759,7 @@ static void yenta_free_resources(struct yenta_socket *socket)  		res = socket->dev->resource + PCI_BRIDGE_RESOURCES + i;  		if (res->start != 0 && res->end != 0)  			release_resource(res); -		res->start = res->end = 0; +		res->start = res->end = res->flags = 0;  	}  }  | 
