diff options
| author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2006-07-05 13:13:03 -0400 | 
|---|---|---|
| committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2006-07-05 13:13:03 -0400 | 
| commit | 5e66dd6d66ffe758b39b6dcadf2330753ee1159b (patch) | |
| tree | a72cdcff4448e4af9425cc213ddf56ab23e697fe /drivers/macintosh/macio_asic.c | |
| parent | 026477c1141b67e98e3bd8bdedb7d4b88a3ecd09 (diff) | |
| parent | ca78f6baca863afe2e6a244a0fe94b3a70211d46 (diff) | |
Merge branch 'master' of /home/trondmy/kernel/linux-2.6/
Diffstat (limited to 'drivers/macintosh/macio_asic.c')
| -rw-r--r-- | drivers/macintosh/macio_asic.c | 152 | 
1 files changed, 103 insertions, 49 deletions
| diff --git a/drivers/macintosh/macio_asic.c b/drivers/macintosh/macio_asic.c index 40ae7b6a939d..80c0c665b5f6 100644 --- a/drivers/macintosh/macio_asic.c +++ b/drivers/macintosh/macio_asic.c @@ -280,75 +280,128 @@ static void macio_release_dev(struct device *dev)  static int macio_resource_quirks(struct device_node *np, struct resource *res,  				 int index)  { -	if (res->flags & IORESOURCE_MEM) { -		/* Grand Central has too large resource 0 on some machines */ -		if (index == 0 && !strcmp(np->name, "gc")) -			res->end = res->start + 0x1ffff; +	/* Only quirks for memory resources for now */ +	if ((res->flags & IORESOURCE_MEM) == 0) +		return 0; + +	/* Grand Central has too large resource 0 on some machines */ +	if (index == 0 && !strcmp(np->name, "gc")) +		res->end = res->start + 0x1ffff; -		/* Airport has bogus resource 2 */ -		if (index >= 2 && !strcmp(np->name, "radio")) -			return 1; +	/* Airport has bogus resource 2 */ +	if (index >= 2 && !strcmp(np->name, "radio")) +		return 1;  #ifndef CONFIG_PPC64 -		/* DBDMAs may have bogus sizes */ -		if ((res->start & 0x0001f000) == 0x00008000) -			res->end = res->start + 0xff; +	/* DBDMAs may have bogus sizes */ +	if ((res->start & 0x0001f000) == 0x00008000) +		res->end = res->start + 0xff;  #endif /* CONFIG_PPC64 */ -		/* ESCC parent eats child resources. We could have added a -		 * level of hierarchy, but I don't really feel the need -		 * for it -		 */ -		if (!strcmp(np->name, "escc")) -			return 1; - -		/* ESCC has bogus resources >= 3 */ -		if (index >= 3 && !(strcmp(np->name, "ch-a") && -				    strcmp(np->name, "ch-b"))) -			return 1; - -		/* Media bay has too many resources, keep only first one */ -		if (index > 0 && !strcmp(np->name, "media-bay")) -			return 1; - -		/* Some older IDE resources have bogus sizes */ -		if (!(strcmp(np->name, "IDE") && strcmp(np->name, "ATA") && -		      strcmp(np->type, "ide") && strcmp(np->type, "ata"))) { -			if (index == 0 && (res->end - res->start) > 0xfff) -				res->end = res->start + 0xfff; -			if (index == 1 && (res->end - res->start) > 0xff) -				res->end = res->start + 0xff; -		} +	/* ESCC parent eats child resources. We could have added a +	 * level of hierarchy, but I don't really feel the need +	 * for it +	 */ +	if (!strcmp(np->name, "escc")) +		return 1; + +	/* ESCC has bogus resources >= 3 */ +	if (index >= 3 && !(strcmp(np->name, "ch-a") && +			    strcmp(np->name, "ch-b"))) +		return 1; + +	/* Media bay has too many resources, keep only first one */ +	if (index > 0 && !strcmp(np->name, "media-bay")) +		return 1; + +	/* Some older IDE resources have bogus sizes */ +	if (!(strcmp(np->name, "IDE") && strcmp(np->name, "ATA") && +	      strcmp(np->type, "ide") && strcmp(np->type, "ata"))) { +		if (index == 0 && (res->end - res->start) > 0xfff) +			res->end = res->start + 0xfff; +		if (index == 1 && (res->end - res->start) > 0xff) +			res->end = res->start + 0xff;  	}  	return 0;  } +static void macio_create_fixup_irq(struct macio_dev *dev, int index, +				   unsigned int line) +{ +	unsigned int irq; -static void macio_setup_interrupts(struct macio_dev *dev) +	irq = irq_create_mapping(NULL, line, 0); +	if (irq != NO_IRQ) { +		dev->interrupt[index].start = irq; +		dev->interrupt[index].flags = IORESOURCE_IRQ; +		dev->interrupt[index].name = dev->ofdev.dev.bus_id; +	} +	if (dev->n_interrupts <= index) +		dev->n_interrupts = index + 1; +} + +static void macio_add_missing_resources(struct macio_dev *dev)  {  	struct device_node *np = dev->ofdev.node; -	int i,j; +	unsigned int irq_base; + +	/* Gatwick has some missing interrupts on child nodes */ +	if (dev->bus->chip->type != macio_gatwick) +		return; -	/* For now, we use pre-parsed entries in the device-tree for -	 * interrupt routing and addresses, but we should change that -	 * to dynamically parsed entries and so get rid of most of the -	 * clutter in struct device_node +	/* irq_base is always 64 on gatwick. I have no cleaner way to get +	 * that value from here at this point  	 */ -	for (i = j = 0; i < np->n_intrs; i++) { +	irq_base = 64; + +	/* Fix SCC */ +	if (strcmp(np->name, "ch-a") == 0) { +		macio_create_fixup_irq(dev, 0, 15 + irq_base); +		macio_create_fixup_irq(dev, 1,  4 + irq_base); +		macio_create_fixup_irq(dev, 2,  5 + irq_base); +		printk(KERN_INFO "macio: fixed SCC irqs on gatwick\n"); +	} + +	/* Fix media-bay */ +	if (strcmp(np->name, "media-bay") == 0) { +		macio_create_fixup_irq(dev, 0, 29 + irq_base); +		printk(KERN_INFO "macio: fixed media-bay irq on gatwick\n"); +	} + +	/* Fix left media bay childs */ +	if (dev->media_bay != NULL && strcmp(np->name, "floppy") == 0) { +		macio_create_fixup_irq(dev, 0, 19 + irq_base); +		macio_create_fixup_irq(dev, 1,  1 + irq_base); +		printk(KERN_INFO "macio: fixed left floppy irqs\n"); +	} +	if (dev->media_bay != NULL && strcasecmp(np->name, "ata4") == 0) { +		macio_create_fixup_irq(dev, 0, 14 + irq_base); +		macio_create_fixup_irq(dev, 0,  3 + irq_base); +		printk(KERN_INFO "macio: fixed left ide irqs\n"); +	} +} + +static void macio_setup_interrupts(struct macio_dev *dev) +{ +	struct device_node *np = dev->ofdev.node; +	unsigned int irq; +	int i = 0, j = 0; + +	for (;;) {  		struct resource *res = &dev->interrupt[j];  		if (j >= MACIO_DEV_COUNT_IRQS)  			break; -		res->start = np->intrs[i].line; -		res->flags = IORESOURCE_IO; -		if (np->intrs[j].sense) -			res->flags |= IORESOURCE_IRQ_LOWLEVEL; -		else -			res->flags |= IORESOURCE_IRQ_HIGHEDGE; +		irq = irq_of_parse_and_map(np, i++); +		if (irq == NO_IRQ) +			break; +		res->start = irq; +		res->flags = IORESOURCE_IRQ;  		res->name = dev->ofdev.dev.bus_id; -		if (macio_resource_quirks(np, res, i)) +		if (macio_resource_quirks(np, res, i - 1)) {  			memset(res, 0, sizeof(struct resource)); -		else +			continue; +		} else  			j++;  	}  	dev->n_interrupts = j; @@ -445,6 +498,7 @@ static struct macio_dev * macio_add_one_device(struct macio_chip *chip,  	/* Setup interrupts & resources */  	macio_setup_interrupts(dev);  	macio_setup_resources(dev, parent_res); +	macio_add_missing_resources(dev);  	/* Register with core */  	if (of_device_register(&dev->ofdev) != 0) { | 
