diff options
Diffstat (limited to 'arch/powerpc/sysdev')
-rw-r--r-- | arch/powerpc/sysdev/Kconfig | 6 | ||||
-rw-r--r-- | arch/powerpc/sysdev/Makefile | 5 | ||||
-rw-r--r-- | arch/powerpc/sysdev/cpm1.c | 74 | ||||
-rw-r--r-- | arch/powerpc/sysdev/fsl_lbc.c | 53 | ||||
-rw-r--r-- | arch/powerpc/sysdev/fsl_msi.c | 109 | ||||
-rw-r--r-- | arch/powerpc/sysdev/fsl_msi.h | 8 | ||||
-rw-r--r-- | arch/powerpc/sysdev/fsl_pci.c | 58 | ||||
-rw-r--r-- | arch/powerpc/sysdev/fsl_soc.c | 85 | ||||
-rw-r--r-- | arch/powerpc/sysdev/fsl_soc.h | 8 | ||||
-rw-r--r-- | arch/powerpc/sysdev/mpc8xxx_gpio.c | 171 | ||||
-rw-r--r-- | arch/powerpc/sysdev/mpic.h | 2 | ||||
-rw-r--r-- | arch/powerpc/sysdev/mpic_msi.c | 123 | ||||
-rw-r--r-- | arch/powerpc/sysdev/mpic_pasemi_msi.c | 24 | ||||
-rw-r--r-- | arch/powerpc/sysdev/mpic_u3msi.c | 22 | ||||
-rw-r--r-- | arch/powerpc/sysdev/msi_bitmap.c | 247 | ||||
-rw-r--r-- | arch/powerpc/sysdev/ppc4xx_pci.c | 32 | ||||
-rw-r--r-- | arch/powerpc/sysdev/qe_lib/Kconfig | 9 |
17 files changed, 645 insertions, 391 deletions
diff --git a/arch/powerpc/sysdev/Kconfig b/arch/powerpc/sysdev/Kconfig index 72fb35b9ebca..396582835cb5 100644 --- a/arch/powerpc/sysdev/Kconfig +++ b/arch/powerpc/sysdev/Kconfig | |||
@@ -6,3 +6,9 @@ config PPC4xx_PCI_EXPRESS | |||
6 | bool | 6 | bool |
7 | depends on PCI && 4xx | 7 | depends on PCI && 4xx |
8 | default n | 8 | default n |
9 | |||
10 | config PPC_MSI_BITMAP | ||
11 | bool | ||
12 | depends on PCI_MSI | ||
13 | default y if MPIC | ||
14 | default y if FSL_PCI | ||
diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile index a90054b56d5c..a44709a94f97 100644 --- a/arch/powerpc/sysdev/Makefile +++ b/arch/powerpc/sysdev/Makefile | |||
@@ -5,6 +5,7 @@ endif | |||
5 | mpic-msi-obj-$(CONFIG_PCI_MSI) += mpic_msi.o mpic_u3msi.o mpic_pasemi_msi.o | 5 | mpic-msi-obj-$(CONFIG_PCI_MSI) += mpic_msi.o mpic_u3msi.o mpic_pasemi_msi.o |
6 | obj-$(CONFIG_MPIC) += mpic.o $(mpic-msi-obj-y) | 6 | obj-$(CONFIG_MPIC) += mpic.o $(mpic-msi-obj-y) |
7 | fsl-msi-obj-$(CONFIG_PCI_MSI) += fsl_msi.o | 7 | fsl-msi-obj-$(CONFIG_PCI_MSI) += fsl_msi.o |
8 | obj-$(CONFIG_PPC_MSI_BITMAP) += msi_bitmap.o | ||
8 | 9 | ||
9 | obj-$(CONFIG_PPC_MPC106) += grackle.o | 10 | obj-$(CONFIG_PPC_MPC106) += grackle.o |
10 | obj-$(CONFIG_PPC_DCR_NATIVE) += dcr-low.o | 11 | obj-$(CONFIG_PPC_DCR_NATIVE) += dcr-low.o |
@@ -15,6 +16,7 @@ obj-$(CONFIG_FSL_SOC) += fsl_soc.o | |||
15 | obj-$(CONFIG_FSL_PCI) += fsl_pci.o $(fsl-msi-obj-y) | 16 | obj-$(CONFIG_FSL_PCI) += fsl_pci.o $(fsl-msi-obj-y) |
16 | obj-$(CONFIG_FSL_LBC) += fsl_lbc.o | 17 | obj-$(CONFIG_FSL_LBC) += fsl_lbc.o |
17 | obj-$(CONFIG_FSL_GTM) += fsl_gtm.o | 18 | obj-$(CONFIG_FSL_GTM) += fsl_gtm.o |
19 | obj-$(CONFIG_MPC8xxx_GPIO) += mpc8xxx_gpio.o | ||
18 | obj-$(CONFIG_RAPIDIO) += fsl_rio.o | 20 | obj-$(CONFIG_RAPIDIO) += fsl_rio.o |
19 | obj-$(CONFIG_TSI108_BRIDGE) += tsi108_pci.o tsi108_dev.o | 21 | obj-$(CONFIG_TSI108_BRIDGE) += tsi108_pci.o tsi108_dev.o |
20 | obj-$(CONFIG_QUICC_ENGINE) += qe_lib/ | 22 | obj-$(CONFIG_QUICC_ENGINE) += qe_lib/ |
@@ -36,15 +38,12 @@ ifeq ($(CONFIG_PCI),y) | |||
36 | obj-$(CONFIG_4xx) += ppc4xx_pci.o | 38 | obj-$(CONFIG_4xx) += ppc4xx_pci.o |
37 | endif | 39 | endif |
38 | 40 | ||
39 | # Temporary hack until we have migrated to asm-powerpc | ||
40 | ifeq ($(ARCH),powerpc) | ||
41 | obj-$(CONFIG_CPM) += cpm_common.o | 41 | obj-$(CONFIG_CPM) += cpm_common.o |
42 | obj-$(CONFIG_CPM2) += cpm2.o cpm2_pic.o | 42 | obj-$(CONFIG_CPM2) += cpm2.o cpm2_pic.o |
43 | obj-$(CONFIG_QUICC_ENGINE) += cpm_common.o | 43 | obj-$(CONFIG_QUICC_ENGINE) += cpm_common.o |
44 | obj-$(CONFIG_PPC_DCR) += dcr.o | 44 | obj-$(CONFIG_PPC_DCR) += dcr.o |
45 | obj-$(CONFIG_8xx) += mpc8xx_pic.o cpm1.o | 45 | obj-$(CONFIG_8xx) += mpc8xx_pic.o cpm1.o |
46 | obj-$(CONFIG_UCODE_PATCH) += micropatch.o | 46 | obj-$(CONFIG_UCODE_PATCH) += micropatch.o |
47 | endif | ||
48 | 47 | ||
49 | ifeq ($(CONFIG_SUSPEND),y) | 48 | ifeq ($(CONFIG_SUSPEND),y) |
50 | obj-$(CONFIG_6xx) += 6xx-suspend.o | 49 | obj-$(CONFIG_6xx) += 6xx-suspend.o |
diff --git a/arch/powerpc/sysdev/cpm1.c b/arch/powerpc/sysdev/cpm1.c index 4a04823e8423..490473ce8103 100644 --- a/arch/powerpc/sysdev/cpm1.c +++ b/arch/powerpc/sysdev/cpm1.c | |||
@@ -546,15 +546,11 @@ static int cpm1_gpio16_get(struct gpio_chip *gc, unsigned int gpio) | |||
546 | return !!(in_be16(&iop->dat) & pin_mask); | 546 | return !!(in_be16(&iop->dat) & pin_mask); |
547 | } | 547 | } |
548 | 548 | ||
549 | static void cpm1_gpio16_set(struct gpio_chip *gc, unsigned int gpio, int value) | 549 | static void __cpm1_gpio16_set(struct of_mm_gpio_chip *mm_gc, u16 pin_mask, |
550 | int value) | ||
550 | { | 551 | { |
551 | struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); | ||
552 | struct cpm1_gpio16_chip *cpm1_gc = to_cpm1_gpio16_chip(mm_gc); | 552 | struct cpm1_gpio16_chip *cpm1_gc = to_cpm1_gpio16_chip(mm_gc); |
553 | struct cpm_ioport16 __iomem *iop = mm_gc->regs; | 553 | struct cpm_ioport16 __iomem *iop = mm_gc->regs; |
554 | unsigned long flags; | ||
555 | u16 pin_mask = 1 << (15 - gpio); | ||
556 | |||
557 | spin_lock_irqsave(&cpm1_gc->lock, flags); | ||
558 | 554 | ||
559 | if (value) | 555 | if (value) |
560 | cpm1_gc->cpdata |= pin_mask; | 556 | cpm1_gc->cpdata |= pin_mask; |
@@ -562,6 +558,18 @@ static void cpm1_gpio16_set(struct gpio_chip *gc, unsigned int gpio, int value) | |||
562 | cpm1_gc->cpdata &= ~pin_mask; | 558 | cpm1_gc->cpdata &= ~pin_mask; |
563 | 559 | ||
564 | out_be16(&iop->dat, cpm1_gc->cpdata); | 560 | out_be16(&iop->dat, cpm1_gc->cpdata); |
561 | } | ||
562 | |||
563 | static void cpm1_gpio16_set(struct gpio_chip *gc, unsigned int gpio, int value) | ||
564 | { | ||
565 | struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); | ||
566 | struct cpm1_gpio16_chip *cpm1_gc = to_cpm1_gpio16_chip(mm_gc); | ||
567 | unsigned long flags; | ||
568 | u16 pin_mask = 1 << (15 - gpio); | ||
569 | |||
570 | spin_lock_irqsave(&cpm1_gc->lock, flags); | ||
571 | |||
572 | __cpm1_gpio16_set(mm_gc, pin_mask, value); | ||
565 | 573 | ||
566 | spin_unlock_irqrestore(&cpm1_gc->lock, flags); | 574 | spin_unlock_irqrestore(&cpm1_gc->lock, flags); |
567 | } | 575 | } |
@@ -569,14 +577,17 @@ static void cpm1_gpio16_set(struct gpio_chip *gc, unsigned int gpio, int value) | |||
569 | static int cpm1_gpio16_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) | 577 | static int cpm1_gpio16_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) |
570 | { | 578 | { |
571 | struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); | 579 | struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); |
580 | struct cpm1_gpio16_chip *cpm1_gc = to_cpm1_gpio16_chip(mm_gc); | ||
572 | struct cpm_ioport16 __iomem *iop = mm_gc->regs; | 581 | struct cpm_ioport16 __iomem *iop = mm_gc->regs; |
573 | u16 pin_mask; | 582 | unsigned long flags; |
583 | u16 pin_mask = 1 << (15 - gpio); | ||
574 | 584 | ||
575 | pin_mask = 1 << (15 - gpio); | 585 | spin_lock_irqsave(&cpm1_gc->lock, flags); |
576 | 586 | ||
577 | setbits16(&iop->dir, pin_mask); | 587 | setbits16(&iop->dir, pin_mask); |
588 | __cpm1_gpio16_set(mm_gc, pin_mask, val); | ||
578 | 589 | ||
579 | cpm1_gpio16_set(gc, gpio, val); | 590 | spin_unlock_irqrestore(&cpm1_gc->lock, flags); |
580 | 591 | ||
581 | return 0; | 592 | return 0; |
582 | } | 593 | } |
@@ -584,13 +595,17 @@ static int cpm1_gpio16_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) | |||
584 | static int cpm1_gpio16_dir_in(struct gpio_chip *gc, unsigned int gpio) | 595 | static int cpm1_gpio16_dir_in(struct gpio_chip *gc, unsigned int gpio) |
585 | { | 596 | { |
586 | struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); | 597 | struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); |
598 | struct cpm1_gpio16_chip *cpm1_gc = to_cpm1_gpio16_chip(mm_gc); | ||
587 | struct cpm_ioport16 __iomem *iop = mm_gc->regs; | 599 | struct cpm_ioport16 __iomem *iop = mm_gc->regs; |
588 | u16 pin_mask; | 600 | unsigned long flags; |
601 | u16 pin_mask = 1 << (15 - gpio); | ||
589 | 602 | ||
590 | pin_mask = 1 << (15 - gpio); | 603 | spin_lock_irqsave(&cpm1_gc->lock, flags); |
591 | 604 | ||
592 | clrbits16(&iop->dir, pin_mask); | 605 | clrbits16(&iop->dir, pin_mask); |
593 | 606 | ||
607 | spin_unlock_irqrestore(&cpm1_gc->lock, flags); | ||
608 | |||
594 | return 0; | 609 | return 0; |
595 | } | 610 | } |
596 | 611 | ||
@@ -655,15 +670,11 @@ static int cpm1_gpio32_get(struct gpio_chip *gc, unsigned int gpio) | |||
655 | return !!(in_be32(&iop->dat) & pin_mask); | 670 | return !!(in_be32(&iop->dat) & pin_mask); |
656 | } | 671 | } |
657 | 672 | ||
658 | static void cpm1_gpio32_set(struct gpio_chip *gc, unsigned int gpio, int value) | 673 | static void __cpm1_gpio32_set(struct of_mm_gpio_chip *mm_gc, u32 pin_mask, |
674 | int value) | ||
659 | { | 675 | { |
660 | struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); | ||
661 | struct cpm1_gpio32_chip *cpm1_gc = to_cpm1_gpio32_chip(mm_gc); | 676 | struct cpm1_gpio32_chip *cpm1_gc = to_cpm1_gpio32_chip(mm_gc); |
662 | struct cpm_ioport32b __iomem *iop = mm_gc->regs; | 677 | struct cpm_ioport32b __iomem *iop = mm_gc->regs; |
663 | unsigned long flags; | ||
664 | u32 pin_mask = 1 << (31 - gpio); | ||
665 | |||
666 | spin_lock_irqsave(&cpm1_gc->lock, flags); | ||
667 | 678 | ||
668 | if (value) | 679 | if (value) |
669 | cpm1_gc->cpdata |= pin_mask; | 680 | cpm1_gc->cpdata |= pin_mask; |
@@ -671,6 +682,18 @@ static void cpm1_gpio32_set(struct gpio_chip *gc, unsigned int gpio, int value) | |||
671 | cpm1_gc->cpdata &= ~pin_mask; | 682 | cpm1_gc->cpdata &= ~pin_mask; |
672 | 683 | ||
673 | out_be32(&iop->dat, cpm1_gc->cpdata); | 684 | out_be32(&iop->dat, cpm1_gc->cpdata); |
685 | } | ||
686 | |||
687 | static void cpm1_gpio32_set(struct gpio_chip *gc, unsigned int gpio, int value) | ||
688 | { | ||
689 | struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); | ||
690 | struct cpm1_gpio32_chip *cpm1_gc = to_cpm1_gpio32_chip(mm_gc); | ||
691 | unsigned long flags; | ||
692 | u32 pin_mask = 1 << (31 - gpio); | ||
693 | |||
694 | spin_lock_irqsave(&cpm1_gc->lock, flags); | ||
695 | |||
696 | __cpm1_gpio32_set(mm_gc, pin_mask, value); | ||
674 | 697 | ||
675 | spin_unlock_irqrestore(&cpm1_gc->lock, flags); | 698 | spin_unlock_irqrestore(&cpm1_gc->lock, flags); |
676 | } | 699 | } |
@@ -678,14 +701,17 @@ static void cpm1_gpio32_set(struct gpio_chip *gc, unsigned int gpio, int value) | |||
678 | static int cpm1_gpio32_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) | 701 | static int cpm1_gpio32_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) |
679 | { | 702 | { |
680 | struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); | 703 | struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); |
704 | struct cpm1_gpio32_chip *cpm1_gc = to_cpm1_gpio32_chip(mm_gc); | ||
681 | struct cpm_ioport32b __iomem *iop = mm_gc->regs; | 705 | struct cpm_ioport32b __iomem *iop = mm_gc->regs; |
682 | u32 pin_mask; | 706 | unsigned long flags; |
707 | u32 pin_mask = 1 << (31 - gpio); | ||
683 | 708 | ||
684 | pin_mask = 1 << (31 - gpio); | 709 | spin_lock_irqsave(&cpm1_gc->lock, flags); |
685 | 710 | ||
686 | setbits32(&iop->dir, pin_mask); | 711 | setbits32(&iop->dir, pin_mask); |
712 | __cpm1_gpio32_set(mm_gc, pin_mask, val); | ||
687 | 713 | ||
688 | cpm1_gpio32_set(gc, gpio, val); | 714 | spin_unlock_irqrestore(&cpm1_gc->lock, flags); |
689 | 715 | ||
690 | return 0; | 716 | return 0; |
691 | } | 717 | } |
@@ -693,13 +719,17 @@ static int cpm1_gpio32_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) | |||
693 | static int cpm1_gpio32_dir_in(struct gpio_chip *gc, unsigned int gpio) | 719 | static int cpm1_gpio32_dir_in(struct gpio_chip *gc, unsigned int gpio) |
694 | { | 720 | { |
695 | struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); | 721 | struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); |
722 | struct cpm1_gpio32_chip *cpm1_gc = to_cpm1_gpio32_chip(mm_gc); | ||
696 | struct cpm_ioport32b __iomem *iop = mm_gc->regs; | 723 | struct cpm_ioport32b __iomem *iop = mm_gc->regs; |
697 | u32 pin_mask; | 724 | unsigned long flags; |
725 | u32 pin_mask = 1 << (31 - gpio); | ||
698 | 726 | ||
699 | pin_mask = 1 << (31 - gpio); | 727 | spin_lock_irqsave(&cpm1_gc->lock, flags); |
700 | 728 | ||
701 | clrbits32(&iop->dir, pin_mask); | 729 | clrbits32(&iop->dir, pin_mask); |
702 | 730 | ||
731 | spin_unlock_irqrestore(&cpm1_gc->lock, flags); | ||
732 | |||
703 | return 0; | 733 | return 0; |
704 | } | 734 | } |
705 | 735 | ||
diff --git a/arch/powerpc/sysdev/fsl_lbc.c b/arch/powerpc/sysdev/fsl_lbc.c index 422c8faef593..0494ee55920f 100644 --- a/arch/powerpc/sysdev/fsl_lbc.c +++ b/arch/powerpc/sysdev/fsl_lbc.c | |||
@@ -11,14 +11,19 @@ | |||
11 | * (at your option) any later version. | 11 | * (at your option) any later version. |
12 | */ | 12 | */ |
13 | 13 | ||
14 | #include <linux/init.h> | ||
15 | #include <linux/module.h> | ||
14 | #include <linux/kernel.h> | 16 | #include <linux/kernel.h> |
17 | #include <linux/compiler.h> | ||
18 | #include <linux/spinlock.h> | ||
19 | #include <linux/types.h> | ||
20 | #include <linux/io.h> | ||
15 | #include <linux/of.h> | 21 | #include <linux/of.h> |
22 | #include <asm/prom.h> | ||
16 | #include <asm/fsl_lbc.h> | 23 | #include <asm/fsl_lbc.h> |
17 | 24 | ||
18 | spinlock_t fsl_lbc_lock = __SPIN_LOCK_UNLOCKED(fsl_lbc_lock); | 25 | static spinlock_t fsl_lbc_lock = __SPIN_LOCK_UNLOCKED(fsl_lbc_lock); |
19 | 26 | static struct fsl_lbc_regs __iomem *fsl_lbc_regs; | |
20 | struct fsl_lbc_regs __iomem *fsl_lbc_regs; | ||
21 | EXPORT_SYMBOL(fsl_lbc_regs); | ||
22 | 27 | ||
23 | static char __initdata *compat_lbc[] = { | 28 | static char __initdata *compat_lbc[] = { |
24 | "fsl,pq2-localbus", | 29 | "fsl,pq2-localbus", |
@@ -127,3 +132,43 @@ int fsl_upm_find(phys_addr_t addr_base, struct fsl_upm *upm) | |||
127 | return 0; | 132 | return 0; |
128 | } | 133 | } |
129 | EXPORT_SYMBOL(fsl_upm_find); | 134 | EXPORT_SYMBOL(fsl_upm_find); |
135 | |||
136 | /** | ||
137 | * fsl_upm_run_pattern - actually run an UPM pattern | ||
138 | * @upm: pointer to the fsl_upm structure obtained via fsl_upm_find | ||
139 | * @io_base: remapped pointer to where memory access should happen | ||
140 | * @mar: MAR register content during pattern execution | ||
141 | * | ||
142 | * This function triggers dummy write to the memory specified by the io_base, | ||
143 | * thus UPM pattern actually executed. Note that mar usage depends on the | ||
144 | * pre-programmed AMX bits in the UPM RAM. | ||
145 | */ | ||
146 | int fsl_upm_run_pattern(struct fsl_upm *upm, void __iomem *io_base, u32 mar) | ||
147 | { | ||
148 | int ret = 0; | ||
149 | unsigned long flags; | ||
150 | |||
151 | spin_lock_irqsave(&fsl_lbc_lock, flags); | ||
152 | |||
153 | out_be32(&fsl_lbc_regs->mar, mar << (32 - upm->width)); | ||
154 | |||
155 | switch (upm->width) { | ||
156 | case 8: | ||
157 | out_8(io_base, 0x0); | ||
158 | break; | ||
159 | case 16: | ||
160 | out_be16(io_base, 0x0); | ||
161 | break; | ||
162 | case 32: | ||
163 | out_be32(io_base, 0x0); | ||
164 | break; | ||
165 | default: | ||
166 | ret = -EINVAL; | ||
167 | break; | ||
168 | } | ||
169 | |||
170 | spin_unlock_irqrestore(&fsl_lbc_lock, flags); | ||
171 | |||
172 | return ret; | ||
173 | } | ||
174 | EXPORT_SYMBOL(fsl_upm_run_pattern); | ||
diff --git a/arch/powerpc/sysdev/fsl_msi.c b/arch/powerpc/sysdev/fsl_msi.c index 2c5187cc8a24..f25ce818d40a 100644 --- a/arch/powerpc/sysdev/fsl_msi.c +++ b/arch/powerpc/sysdev/fsl_msi.c | |||
@@ -14,7 +14,6 @@ | |||
14 | */ | 14 | */ |
15 | #include <linux/irq.h> | 15 | #include <linux/irq.h> |
16 | #include <linux/bootmem.h> | 16 | #include <linux/bootmem.h> |
17 | #include <linux/bitmap.h> | ||
18 | #include <linux/msi.h> | 17 | #include <linux/msi.h> |
19 | #include <linux/pci.h> | 18 | #include <linux/pci.h> |
20 | #include <linux/of_platform.h> | 19 | #include <linux/of_platform.h> |
@@ -67,95 +66,22 @@ static struct irq_host_ops fsl_msi_host_ops = { | |||
67 | .map = fsl_msi_host_map, | 66 | .map = fsl_msi_host_map, |
68 | }; | 67 | }; |
69 | 68 | ||
70 | static irq_hw_number_t fsl_msi_alloc_hwirqs(struct fsl_msi *msi, int num) | ||
71 | { | ||
72 | unsigned long flags; | ||
73 | int order = get_count_order(num); | ||
74 | int offset; | ||
75 | |||
76 | spin_lock_irqsave(&msi->bitmap_lock, flags); | ||
77 | |||
78 | offset = bitmap_find_free_region(msi->fsl_msi_bitmap, | ||
79 | NR_MSI_IRQS, order); | ||
80 | |||
81 | spin_unlock_irqrestore(&msi->bitmap_lock, flags); | ||
82 | |||
83 | pr_debug("%s: allocated 0x%x (2^%d) at offset 0x%x\n", | ||
84 | __func__, num, order, offset); | ||
85 | |||
86 | return offset; | ||
87 | } | ||
88 | |||
89 | static void fsl_msi_free_hwirqs(struct fsl_msi *msi, int offset, int num) | ||
90 | { | ||
91 | unsigned long flags; | ||
92 | int order = get_count_order(num); | ||
93 | |||
94 | pr_debug("%s: freeing 0x%x (2^%d) at offset 0x%x\n", | ||
95 | __func__, num, order, offset); | ||
96 | |||
97 | spin_lock_irqsave(&msi->bitmap_lock, flags); | ||
98 | bitmap_release_region(msi->fsl_msi_bitmap, offset, order); | ||
99 | spin_unlock_irqrestore(&msi->bitmap_lock, flags); | ||
100 | } | ||
101 | |||
102 | static int fsl_msi_free_dt_hwirqs(struct fsl_msi *msi) | ||
103 | { | ||
104 | int i; | ||
105 | int len; | ||
106 | const u32 *p; | ||
107 | |||
108 | bitmap_allocate_region(msi->fsl_msi_bitmap, 0, | ||
109 | get_count_order(NR_MSI_IRQS)); | ||
110 | |||
111 | p = of_get_property(msi->of_node, "msi-available-ranges", &len); | ||
112 | |||
113 | if (!p) { | ||
114 | /* No msi-available-ranges property, | ||
115 | * All the 256 MSI interrupts can be used | ||
116 | */ | ||
117 | fsl_msi_free_hwirqs(msi, 0, 0x100); | ||
118 | return 0; | ||
119 | } | ||
120 | |||
121 | if ((len % (2 * sizeof(u32))) != 0) { | ||
122 | printk(KERN_WARNING "fsl_msi: Malformed msi-available-ranges " | ||
123 | "property on %s\n", msi->of_node->full_name); | ||
124 | return -EINVAL; | ||
125 | } | ||
126 | |||
127 | /* Format is: (<u32 start> <u32 count>)+ */ | ||
128 | len /= 2 * sizeof(u32); | ||
129 | for (i = 0; i < len; i++, p += 2) | ||
130 | fsl_msi_free_hwirqs(msi, *p, *(p + 1)); | ||
131 | |||
132 | return 0; | ||
133 | } | ||
134 | |||
135 | static int fsl_msi_init_allocator(struct fsl_msi *msi_data) | 69 | static int fsl_msi_init_allocator(struct fsl_msi *msi_data) |
136 | { | 70 | { |
137 | int rc; | 71 | int rc; |
138 | int size = BITS_TO_LONGS(NR_MSI_IRQS) * sizeof(u32); | ||
139 | 72 | ||
140 | msi_data->fsl_msi_bitmap = kzalloc(size, GFP_KERNEL); | 73 | rc = msi_bitmap_alloc(&msi_data->bitmap, NR_MSI_IRQS, |
74 | msi_data->irqhost->of_node); | ||
75 | if (rc) | ||
76 | return rc; | ||
141 | 77 | ||
142 | if (msi_data->fsl_msi_bitmap == NULL) { | 78 | rc = msi_bitmap_reserve_dt_hwirqs(&msi_data->bitmap); |
143 | pr_debug("%s: ENOMEM allocating allocator bitmap!\n", | 79 | if (rc < 0) { |
144 | __func__); | 80 | msi_bitmap_free(&msi_data->bitmap); |
145 | return -ENOMEM; | 81 | return rc; |
146 | } | 82 | } |
147 | 83 | ||
148 | rc = fsl_msi_free_dt_hwirqs(msi_data); | ||
149 | if (rc) | ||
150 | goto out_free; | ||
151 | |||
152 | return 0; | 84 | return 0; |
153 | out_free: | ||
154 | kfree(msi_data->fsl_msi_bitmap); | ||
155 | |||
156 | msi_data->fsl_msi_bitmap = NULL; | ||
157 | return rc; | ||
158 | |||
159 | } | 85 | } |
160 | 86 | ||
161 | static int fsl_msi_check_device(struct pci_dev *pdev, int nvec, int type) | 87 | static int fsl_msi_check_device(struct pci_dev *pdev, int nvec, int type) |
@@ -175,7 +101,8 @@ static void fsl_teardown_msi_irqs(struct pci_dev *pdev) | |||
175 | if (entry->irq == NO_IRQ) | 101 | if (entry->irq == NO_IRQ) |
176 | continue; | 102 | continue; |
177 | set_irq_msi(entry->irq, NULL); | 103 | set_irq_msi(entry->irq, NULL); |
178 | fsl_msi_free_hwirqs(msi_data, virq_to_hw(entry->irq), 1); | 104 | msi_bitmap_free_hwirqs(&msi_data->bitmap, |
105 | virq_to_hw(entry->irq), 1); | ||
179 | irq_dispose_mapping(entry->irq); | 106 | irq_dispose_mapping(entry->irq); |
180 | } | 107 | } |
181 | 108 | ||
@@ -197,15 +124,14 @@ static void fsl_compose_msi_msg(struct pci_dev *pdev, int hwirq, | |||
197 | 124 | ||
198 | static int fsl_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type) | 125 | static int fsl_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type) |
199 | { | 126 | { |
200 | irq_hw_number_t hwirq; | 127 | int rc, hwirq; |
201 | int rc; | ||
202 | unsigned int virq; | 128 | unsigned int virq; |
203 | struct msi_desc *entry; | 129 | struct msi_desc *entry; |
204 | struct msi_msg msg; | 130 | struct msi_msg msg; |
205 | struct fsl_msi *msi_data = fsl_msi; | 131 | struct fsl_msi *msi_data = fsl_msi; |
206 | 132 | ||
207 | list_for_each_entry(entry, &pdev->msi_list, list) { | 133 | list_for_each_entry(entry, &pdev->msi_list, list) { |
208 | hwirq = fsl_msi_alloc_hwirqs(msi_data, 1); | 134 | hwirq = msi_bitmap_alloc_hwirqs(&msi_data->bitmap, 1); |
209 | if (hwirq < 0) { | 135 | if (hwirq < 0) { |
210 | rc = hwirq; | 136 | rc = hwirq; |
211 | pr_debug("%s: fail allocating msi interrupt\n", | 137 | pr_debug("%s: fail allocating msi interrupt\n", |
@@ -216,9 +142,9 @@ static int fsl_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type) | |||
216 | virq = irq_create_mapping(msi_data->irqhost, hwirq); | 142 | virq = irq_create_mapping(msi_data->irqhost, hwirq); |
217 | 143 | ||
218 | if (virq == NO_IRQ) { | 144 | if (virq == NO_IRQ) { |
219 | pr_debug("%s: fail mapping hwirq 0x%lx\n", | 145 | pr_debug("%s: fail mapping hwirq 0x%x\n", |
220 | __func__, hwirq); | 146 | __func__, hwirq); |
221 | fsl_msi_free_hwirqs(msi_data, hwirq, 1); | 147 | msi_bitmap_free_hwirqs(&msi_data->bitmap, hwirq, 1); |
222 | rc = -ENOSPC; | 148 | rc = -ENOSPC; |
223 | goto out_free; | 149 | goto out_free; |
224 | } | 150 | } |
@@ -317,14 +243,11 @@ static int __devinit fsl_of_msi_probe(struct of_device *dev, | |||
317 | goto error_out; | 243 | goto error_out; |
318 | } | 244 | } |
319 | 245 | ||
320 | msi->of_node = of_node_get(dev->node); | 246 | msi->irqhost = irq_alloc_host(dev->node, IRQ_HOST_MAP_LINEAR, |
247 | NR_MSI_IRQS, &fsl_msi_host_ops, 0); | ||
321 | 248 | ||
322 | msi->irqhost = irq_alloc_host(of_node_get(dev->node), | ||
323 | IRQ_HOST_MAP_LINEAR, | ||
324 | NR_MSI_IRQS, &fsl_msi_host_ops, 0); | ||
325 | if (msi->irqhost == NULL) { | 249 | if (msi->irqhost == NULL) { |
326 | dev_err(&dev->dev, "No memory for MSI irqhost\n"); | 250 | dev_err(&dev->dev, "No memory for MSI irqhost\n"); |
327 | of_node_put(dev->node); | ||
328 | err = -ENOMEM; | 251 | err = -ENOMEM; |
329 | goto error_out; | 252 | goto error_out; |
330 | } | 253 | } |
diff --git a/arch/powerpc/sysdev/fsl_msi.h b/arch/powerpc/sysdev/fsl_msi.h index a653468521fa..331c7e7025b7 100644 --- a/arch/powerpc/sysdev/fsl_msi.h +++ b/arch/powerpc/sysdev/fsl_msi.h | |||
@@ -13,6 +13,8 @@ | |||
13 | #ifndef _POWERPC_SYSDEV_FSL_MSI_H | 13 | #ifndef _POWERPC_SYSDEV_FSL_MSI_H |
14 | #define _POWERPC_SYSDEV_FSL_MSI_H | 14 | #define _POWERPC_SYSDEV_FSL_MSI_H |
15 | 15 | ||
16 | #include <asm/msi_bitmap.h> | ||
17 | |||
16 | #define NR_MSI_REG 8 | 18 | #define NR_MSI_REG 8 |
17 | #define IRQS_PER_MSI_REG 32 | 19 | #define IRQS_PER_MSI_REG 32 |
18 | #define NR_MSI_IRQS (NR_MSI_REG * IRQS_PER_MSI_REG) | 20 | #define NR_MSI_IRQS (NR_MSI_REG * IRQS_PER_MSI_REG) |
@@ -22,9 +24,6 @@ | |||
22 | #define FSL_PIC_IP_IPIC 0x00000002 | 24 | #define FSL_PIC_IP_IPIC 0x00000002 |
23 | 25 | ||
24 | struct fsl_msi { | 26 | struct fsl_msi { |
25 | /* Device node of the MSI interrupt*/ | ||
26 | struct device_node *of_node; | ||
27 | |||
28 | struct irq_host *irqhost; | 27 | struct irq_host *irqhost; |
29 | 28 | ||
30 | unsigned long cascade_irq; | 29 | unsigned long cascade_irq; |
@@ -34,8 +33,7 @@ struct fsl_msi { | |||
34 | void __iomem *msi_regs; | 33 | void __iomem *msi_regs; |
35 | u32 feature; | 34 | u32 feature; |
36 | 35 | ||
37 | unsigned long *fsl_msi_bitmap; | 36 | struct msi_bitmap bitmap; |
38 | spinlock_t bitmap_lock; | ||
39 | }; | 37 | }; |
40 | 38 | ||
41 | #endif /* _POWERPC_SYSDEV_FSL_MSI_H */ | 39 | #endif /* _POWERPC_SYSDEV_FSL_MSI_H */ |
diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c index 61e6d77efa4f..5b264eb4b1f7 100644 --- a/arch/powerpc/sysdev/fsl_pci.c +++ b/arch/powerpc/sysdev/fsl_pci.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * MPC85xx/86xx PCI/PCIE support routing. | 2 | * MPC83xx/85xx/86xx PCI/PCIE support routing. |
3 | * | 3 | * |
4 | * Copyright 2007 Freescale Semiconductor, Inc | 4 | * Copyright 2007,2008 Freescale Semiconductor, Inc |
5 | * | 5 | * |
6 | * Initial author: Xianghua Xiao <x.xiao@freescale.com> | 6 | * Initial author: Xianghua Xiao <x.xiao@freescale.com> |
7 | * Recode: ZHANG WEI <wei.zhang@freescale.com> | 7 | * Recode: ZHANG WEI <wei.zhang@freescale.com> |
@@ -251,20 +251,47 @@ DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8641D, quirk_fsl_pcie_header); | |||
251 | DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8610, quirk_fsl_pcie_header); | 251 | DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8610, quirk_fsl_pcie_header); |
252 | #endif /* CONFIG_PPC_85xx || CONFIG_PPC_86xx */ | 252 | #endif /* CONFIG_PPC_85xx || CONFIG_PPC_86xx */ |
253 | 253 | ||
254 | #if defined(CONFIG_PPC_83xx) | 254 | #if defined(CONFIG_PPC_83xx) || defined(CONFIG_PPC_MPC512x) |
255 | int __init mpc83xx_add_bridge(struct device_node *dev) | 255 | int __init mpc83xx_add_bridge(struct device_node *dev) |
256 | { | 256 | { |
257 | int len; | 257 | int len; |
258 | struct pci_controller *hose; | 258 | struct pci_controller *hose; |
259 | struct resource rsrc; | 259 | struct resource rsrc_reg; |
260 | struct resource rsrc_cfg; | ||
260 | const int *bus_range; | 261 | const int *bus_range; |
261 | int primary = 1, has_address = 0; | 262 | int primary; |
262 | phys_addr_t immr = get_immrbase(); | ||
263 | 263 | ||
264 | pr_debug("Adding PCI host bridge %s\n", dev->full_name); | 264 | pr_debug("Adding PCI host bridge %s\n", dev->full_name); |
265 | 265 | ||
266 | /* Fetch host bridge registers address */ | 266 | /* Fetch host bridge registers address */ |
267 | has_address = (of_address_to_resource(dev, 0, &rsrc) == 0); | 267 | if (of_address_to_resource(dev, 0, &rsrc_reg)) { |
268 | printk(KERN_WARNING "Can't get pci register base!\n"); | ||
269 | return -ENOMEM; | ||
270 | } | ||
271 | |||
272 | memset(&rsrc_cfg, 0, sizeof(rsrc_cfg)); | ||
273 | |||
274 | if (of_address_to_resource(dev, 1, &rsrc_cfg)) { | ||
275 | printk(KERN_WARNING | ||
276 | "No pci config register base in dev tree, " | ||
277 | "using default\n"); | ||
278 | /* | ||
279 | * MPC83xx supports up to two host controllers | ||
280 | * one at 0x8500 has config space registers at 0x8300 | ||
281 | * one at 0x8600 has config space registers at 0x8380 | ||
282 | */ | ||
283 | if ((rsrc_reg.start & 0xfffff) == 0x8500) | ||
284 | rsrc_cfg.start = (rsrc_reg.start & 0xfff00000) + 0x8300; | ||
285 | else if ((rsrc_reg.start & 0xfffff) == 0x8600) | ||
286 | rsrc_cfg.start = (rsrc_reg.start & 0xfff00000) + 0x8380; | ||
287 | } | ||
288 | /* | ||
289 | * Controller at offset 0x8500 is primary | ||
290 | */ | ||
291 | if ((rsrc_reg.start & 0xfffff) == 0x8500) | ||
292 | primary = 1; | ||
293 | else | ||
294 | primary = 0; | ||
268 | 295 | ||
269 | /* Get bus range if any */ | 296 | /* Get bus range if any */ |
270 | bus_range = of_get_property(dev, "bus-range", &len); | 297 | bus_range = of_get_property(dev, "bus-range", &len); |
@@ -281,22 +308,11 @@ int __init mpc83xx_add_bridge(struct device_node *dev) | |||
281 | hose->first_busno = bus_range ? bus_range[0] : 0; | 308 | hose->first_busno = bus_range ? bus_range[0] : 0; |
282 | hose->last_busno = bus_range ? bus_range[1] : 0xff; | 309 | hose->last_busno = bus_range ? bus_range[1] : 0xff; |
283 | 310 | ||
284 | /* MPC83xx supports up to two host controllers one at 0x8500 from immrbar | 311 | setup_indirect_pci(hose, rsrc_cfg.start, rsrc_cfg.start + 4, 0); |
285 | * the other at 0x8600, we consider the 0x8500 the primary controller | ||
286 | */ | ||
287 | /* PCI 1 */ | ||
288 | if ((rsrc.start & 0xfffff) == 0x8500) { | ||
289 | setup_indirect_pci(hose, immr + 0x8300, immr + 0x8304, 0); | ||
290 | } | ||
291 | /* PCI 2 */ | ||
292 | if ((rsrc.start & 0xfffff) == 0x8600) { | ||
293 | setup_indirect_pci(hose, immr + 0x8380, immr + 0x8384, 0); | ||
294 | primary = 0; | ||
295 | } | ||
296 | 312 | ||
297 | printk(KERN_INFO "Found MPC83xx PCI host bridge at 0x%016llx. " | 313 | printk(KERN_INFO "Found FSL PCI host bridge at 0x%016llx. " |
298 | "Firmware bus number: %d->%d\n", | 314 | "Firmware bus number: %d->%d\n", |
299 | (unsigned long long)rsrc.start, hose->first_busno, | 315 | (unsigned long long)rsrc_reg.start, hose->first_busno, |
300 | hose->last_busno); | 316 | hose->last_busno); |
301 | 317 | ||
302 | pr_debug(" ->Hose at 0x%p, cfg_addr=0x%p,cfg_data=0x%p\n", | 318 | pr_debug(" ->Hose at 0x%p, cfg_addr=0x%p,cfg_data=0x%p\n", |
diff --git a/arch/powerpc/sysdev/fsl_soc.c b/arch/powerpc/sysdev/fsl_soc.c index 214388e11807..01b884b25696 100644 --- a/arch/powerpc/sysdev/fsl_soc.c +++ b/arch/powerpc/sysdev/fsl_soc.c | |||
@@ -412,53 +412,6 @@ err: | |||
412 | 412 | ||
413 | arch_initcall(gfar_of_init); | 413 | arch_initcall(gfar_of_init); |
414 | 414 | ||
415 | |||
416 | #ifdef CONFIG_PPC_83xx | ||
417 | static int __init mpc83xx_wdt_init(void) | ||
418 | { | ||
419 | struct resource r; | ||
420 | struct device_node *np; | ||
421 | struct platform_device *dev; | ||
422 | u32 freq = fsl_get_sys_freq(); | ||
423 | int ret; | ||
424 | |||
425 | np = of_find_compatible_node(NULL, "watchdog", "mpc83xx_wdt"); | ||
426 | |||
427 | if (!np) { | ||
428 | ret = -ENODEV; | ||
429 | goto nodev; | ||
430 | } | ||
431 | |||
432 | memset(&r, 0, sizeof(r)); | ||
433 | |||
434 | ret = of_address_to_resource(np, 0, &r); | ||
435 | if (ret) | ||
436 | goto err; | ||
437 | |||
438 | dev = platform_device_register_simple("mpc83xx_wdt", 0, &r, 1); | ||
439 | if (IS_ERR(dev)) { | ||
440 | ret = PTR_ERR(dev); | ||
441 | goto err; | ||
442 | } | ||
443 | |||
444 | ret = platform_device_add_data(dev, &freq, sizeof(freq)); | ||
445 | if (ret) | ||
446 | goto unreg; | ||
447 | |||
448 | of_node_put(np); | ||
449 | return 0; | ||
450 | |||
451 | unreg: | ||
452 | platform_device_unregister(dev); | ||
453 | err: | ||
454 | of_node_put(np); | ||
455 | nodev: | ||
456 | return ret; | ||
457 | } | ||
458 | |||
459 | arch_initcall(mpc83xx_wdt_init); | ||
460 | #endif | ||
461 | |||
462 | static enum fsl_usb2_phy_modes determine_usb_phy(const char *phy_type) | 415 | static enum fsl_usb2_phy_modes determine_usb_phy(const char *phy_type) |
463 | { | 416 | { |
464 | if (!phy_type) | 417 | if (!phy_type) |
@@ -767,42 +720,6 @@ void fsl_rstcr_restart(char *cmd) | |||
767 | #endif | 720 | #endif |
768 | 721 | ||
769 | #if defined(CONFIG_FB_FSL_DIU) || defined(CONFIG_FB_FSL_DIU_MODULE) | 722 | #if defined(CONFIG_FB_FSL_DIU) || defined(CONFIG_FB_FSL_DIU_MODULE) |
770 | struct platform_diu_data_ops diu_ops = { | 723 | struct platform_diu_data_ops diu_ops; |
771 | .diu_size = 1280 * 1024 * 4, /* default one 1280x1024 buffer */ | ||
772 | }; | ||
773 | EXPORT_SYMBOL(diu_ops); | 724 | EXPORT_SYMBOL(diu_ops); |
774 | |||
775 | int __init preallocate_diu_videomemory(void) | ||
776 | { | ||
777 | pr_debug("diu_size=%lu\n", diu_ops.diu_size); | ||
778 | |||
779 | diu_ops.diu_mem = __alloc_bootmem(diu_ops.diu_size, 8, 0); | ||
780 | if (!diu_ops.diu_mem) { | ||
781 | printk(KERN_ERR "fsl-diu: cannot allocate %lu bytes\n", | ||
782 | diu_ops.diu_size); | ||
783 | return -ENOMEM; | ||
784 | } | ||
785 | |||
786 | pr_debug("diu_mem=%p\n", diu_ops.diu_mem); | ||
787 | |||
788 | rh_init(&diu_ops.diu_rh_info, 4096, ARRAY_SIZE(diu_ops.diu_rh_block), | ||
789 | diu_ops.diu_rh_block); | ||
790 | return rh_attach_region(&diu_ops.diu_rh_info, | ||
791 | (unsigned long) diu_ops.diu_mem, | ||
792 | diu_ops.diu_size); | ||
793 | } | ||
794 | |||
795 | static int __init early_parse_diufb(char *p) | ||
796 | { | ||
797 | if (!p) | ||
798 | return 1; | ||
799 | |||
800 | diu_ops.diu_size = _ALIGN_UP(memparse(p, &p), 8); | ||
801 | |||
802 | pr_debug("diu_size=%lu\n", diu_ops.diu_size); | ||
803 | |||
804 | return 0; | ||
805 | } | ||
806 | early_param("diufb", early_parse_diufb); | ||
807 | |||
808 | #endif | 725 | #endif |
diff --git a/arch/powerpc/sysdev/fsl_soc.h b/arch/powerpc/sysdev/fsl_soc.h index 024299887352..60f7f227327c 100644 --- a/arch/powerpc/sysdev/fsl_soc.h +++ b/arch/powerpc/sysdev/fsl_soc.h | |||
@@ -20,14 +20,7 @@ extern int fsl_spi_init(struct spi_board_info *board_infos, | |||
20 | extern void fsl_rstcr_restart(char *cmd); | 20 | extern void fsl_rstcr_restart(char *cmd); |
21 | 21 | ||
22 | #if defined(CONFIG_FB_FSL_DIU) || defined(CONFIG_FB_FSL_DIU_MODULE) | 22 | #if defined(CONFIG_FB_FSL_DIU) || defined(CONFIG_FB_FSL_DIU_MODULE) |
23 | #include <linux/bootmem.h> | ||
24 | #include <asm/rheap.h> | ||
25 | struct platform_diu_data_ops { | 23 | struct platform_diu_data_ops { |
26 | rh_block_t diu_rh_block[16]; | ||
27 | rh_info_t diu_rh_info; | ||
28 | unsigned long diu_size; | ||
29 | void *diu_mem; | ||
30 | |||
31 | unsigned int (*get_pixel_format) (unsigned int bits_per_pixel, | 24 | unsigned int (*get_pixel_format) (unsigned int bits_per_pixel, |
32 | int monitor_port); | 25 | int monitor_port); |
33 | void (*set_gamma_table) (int monitor_port, char *gamma_table_base); | 26 | void (*set_gamma_table) (int monitor_port, char *gamma_table_base); |
@@ -38,7 +31,6 @@ struct platform_diu_data_ops { | |||
38 | }; | 31 | }; |
39 | 32 | ||
40 | extern struct platform_diu_data_ops diu_ops; | 33 | extern struct platform_diu_data_ops diu_ops; |
41 | int __init preallocate_diu_videomemory(void); | ||
42 | #endif | 34 | #endif |
43 | 35 | ||
44 | #endif | 36 | #endif |
diff --git a/arch/powerpc/sysdev/mpc8xxx_gpio.c b/arch/powerpc/sysdev/mpc8xxx_gpio.c new file mode 100644 index 000000000000..103eace36194 --- /dev/null +++ b/arch/powerpc/sysdev/mpc8xxx_gpio.c | |||
@@ -0,0 +1,171 @@ | |||
1 | /* | ||
2 | * GPIOs on MPC8349/8572/8610 and compatible | ||
3 | * | ||
4 | * Copyright (C) 2008 Peter Korsgaard <jacmet@sunsite.dk> | ||
5 | * | ||
6 | * This file is licensed under the terms of the GNU General Public License | ||
7 | * version 2. This program is licensed "as is" without any warranty of any | ||
8 | * kind, whether express or implied. | ||
9 | */ | ||
10 | |||
11 | #include <linux/kernel.h> | ||
12 | #include <linux/init.h> | ||
13 | #include <linux/spinlock.h> | ||
14 | #include <linux/io.h> | ||
15 | #include <linux/of.h> | ||
16 | #include <linux/of_gpio.h> | ||
17 | #include <linux/gpio.h> | ||
18 | |||
19 | #define MPC8XXX_GPIO_PINS 32 | ||
20 | |||
21 | #define GPIO_DIR 0x00 | ||
22 | #define GPIO_ODR 0x04 | ||
23 | #define GPIO_DAT 0x08 | ||
24 | #define GPIO_IER 0x0c | ||
25 | #define GPIO_IMR 0x10 | ||
26 | #define GPIO_ICR 0x14 | ||
27 | |||
28 | struct mpc8xxx_gpio_chip { | ||
29 | struct of_mm_gpio_chip mm_gc; | ||
30 | spinlock_t lock; | ||
31 | |||
32 | /* | ||
33 | * shadowed data register to be able to clear/set output pins in | ||
34 | * open drain mode safely | ||
35 | */ | ||
36 | u32 data; | ||
37 | }; | ||
38 | |||
39 | static inline u32 mpc8xxx_gpio2mask(unsigned int gpio) | ||
40 | { | ||
41 | return 1u << (MPC8XXX_GPIO_PINS - 1 - gpio); | ||
42 | } | ||
43 | |||
44 | static inline struct mpc8xxx_gpio_chip * | ||
45 | to_mpc8xxx_gpio_chip(struct of_mm_gpio_chip *mm) | ||
46 | { | ||
47 | return container_of(mm, struct mpc8xxx_gpio_chip, mm_gc); | ||
48 | } | ||
49 | |||
50 | static void mpc8xxx_gpio_save_regs(struct of_mm_gpio_chip *mm) | ||
51 | { | ||
52 | struct mpc8xxx_gpio_chip *mpc8xxx_gc = to_mpc8xxx_gpio_chip(mm); | ||
53 | |||
54 | mpc8xxx_gc->data = in_be32(mm->regs + GPIO_DAT); | ||
55 | } | ||
56 | |||
57 | static int mpc8xxx_gpio_get(struct gpio_chip *gc, unsigned int gpio) | ||
58 | { | ||
59 | struct of_mm_gpio_chip *mm = to_of_mm_gpio_chip(gc); | ||
60 | |||
61 | return in_be32(mm->regs + GPIO_DAT) & mpc8xxx_gpio2mask(gpio); | ||
62 | } | ||
63 | |||
64 | static void mpc8xxx_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val) | ||
65 | { | ||
66 | struct of_mm_gpio_chip *mm = to_of_mm_gpio_chip(gc); | ||
67 | struct mpc8xxx_gpio_chip *mpc8xxx_gc = to_mpc8xxx_gpio_chip(mm); | ||
68 | unsigned long flags; | ||
69 | |||
70 | spin_lock_irqsave(&mpc8xxx_gc->lock, flags); | ||
71 | |||
72 | if (val) | ||
73 | mpc8xxx_gc->data |= mpc8xxx_gpio2mask(gpio); | ||
74 | else | ||
75 | mpc8xxx_gc->data &= ~mpc8xxx_gpio2mask(gpio); | ||
76 | |||
77 | out_be32(mm->regs + GPIO_DAT, mpc8xxx_gc->data); | ||
78 | |||
79 | spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags); | ||
80 | } | ||
81 | |||
82 | static int mpc8xxx_gpio_dir_in(struct gpio_chip *gc, unsigned int gpio) | ||
83 | { | ||
84 | struct of_mm_gpio_chip *mm = to_of_mm_gpio_chip(gc); | ||
85 | struct mpc8xxx_gpio_chip *mpc8xxx_gc = to_mpc8xxx_gpio_chip(mm); | ||
86 | unsigned long flags; | ||
87 | |||
88 | spin_lock_irqsave(&mpc8xxx_gc->lock, flags); | ||
89 | |||
90 | clrbits32(mm->regs + GPIO_DIR, mpc8xxx_gpio2mask(gpio)); | ||
91 | |||
92 | spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags); | ||
93 | |||
94 | return 0; | ||
95 | } | ||
96 | |||
97 | static int mpc8xxx_gpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) | ||
98 | { | ||
99 | struct of_mm_gpio_chip *mm = to_of_mm_gpio_chip(gc); | ||
100 | struct mpc8xxx_gpio_chip *mpc8xxx_gc = to_mpc8xxx_gpio_chip(mm); | ||
101 | unsigned long flags; | ||
102 | |||
103 | mpc8xxx_gpio_set(gc, gpio, val); | ||
104 | |||
105 | spin_lock_irqsave(&mpc8xxx_gc->lock, flags); | ||
106 | |||
107 | setbits32(mm->regs + GPIO_DIR, mpc8xxx_gpio2mask(gpio)); | ||
108 | |||
109 | spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags); | ||
110 | |||
111 | return 0; | ||
112 | } | ||
113 | |||
114 | static void __init mpc8xxx_add_controller(struct device_node *np) | ||
115 | { | ||
116 | struct mpc8xxx_gpio_chip *mpc8xxx_gc; | ||
117 | struct of_mm_gpio_chip *mm_gc; | ||
118 | struct of_gpio_chip *of_gc; | ||
119 | struct gpio_chip *gc; | ||
120 | int ret; | ||
121 | |||
122 | mpc8xxx_gc = kzalloc(sizeof(*mpc8xxx_gc), GFP_KERNEL); | ||
123 | if (!mpc8xxx_gc) { | ||
124 | ret = -ENOMEM; | ||
125 | goto err; | ||
126 | } | ||
127 | |||
128 | spin_lock_init(&mpc8xxx_gc->lock); | ||
129 | |||
130 | mm_gc = &mpc8xxx_gc->mm_gc; | ||
131 | of_gc = &mm_gc->of_gc; | ||
132 | gc = &of_gc->gc; | ||
133 | |||
134 | mm_gc->save_regs = mpc8xxx_gpio_save_regs; | ||
135 | of_gc->gpio_cells = 2; | ||
136 | gc->ngpio = MPC8XXX_GPIO_PINS; | ||
137 | gc->direction_input = mpc8xxx_gpio_dir_in; | ||
138 | gc->direction_output = mpc8xxx_gpio_dir_out; | ||
139 | gc->get = mpc8xxx_gpio_get; | ||
140 | gc->set = mpc8xxx_gpio_set; | ||
141 | |||
142 | ret = of_mm_gpiochip_add(np, mm_gc); | ||
143 | if (ret) | ||
144 | goto err; | ||
145 | |||
146 | return; | ||
147 | |||
148 | err: | ||
149 | pr_err("%s: registration failed with status %d\n", | ||
150 | np->full_name, ret); | ||
151 | kfree(mpc8xxx_gc); | ||
152 | |||
153 | return; | ||
154 | } | ||
155 | |||
156 | static int __init mpc8xxx_add_gpiochips(void) | ||
157 | { | ||
158 | struct device_node *np; | ||
159 | |||
160 | for_each_compatible_node(np, NULL, "fsl,mpc8349-gpio") | ||
161 | mpc8xxx_add_controller(np); | ||
162 | |||
163 | for_each_compatible_node(np, NULL, "fsl,mpc8572-gpio") | ||
164 | mpc8xxx_add_controller(np); | ||
165 | |||
166 | for_each_compatible_node(np, NULL, "fsl,mpc8610-gpio") | ||
167 | mpc8xxx_add_controller(np); | ||
168 | |||
169 | return 0; | ||
170 | } | ||
171 | arch_initcall(mpc8xxx_add_gpiochips); | ||
diff --git a/arch/powerpc/sysdev/mpic.h b/arch/powerpc/sysdev/mpic.h index fbf8a266941c..6209c62a426d 100644 --- a/arch/powerpc/sysdev/mpic.h +++ b/arch/powerpc/sysdev/mpic.h | |||
@@ -14,8 +14,6 @@ | |||
14 | #ifdef CONFIG_PCI_MSI | 14 | #ifdef CONFIG_PCI_MSI |
15 | extern void mpic_msi_reserve_hwirq(struct mpic *mpic, irq_hw_number_t hwirq); | 15 | extern void mpic_msi_reserve_hwirq(struct mpic *mpic, irq_hw_number_t hwirq); |
16 | extern int mpic_msi_init_allocator(struct mpic *mpic); | 16 | extern int mpic_msi_init_allocator(struct mpic *mpic); |
17 | extern irq_hw_number_t mpic_msi_alloc_hwirqs(struct mpic *mpic, int num); | ||
18 | extern void mpic_msi_free_hwirqs(struct mpic *mpic, int offset, int num); | ||
19 | extern int mpic_u3msi_init(struct mpic *mpic); | 17 | extern int mpic_u3msi_init(struct mpic *mpic); |
20 | extern int mpic_pasemi_msi_init(struct mpic *mpic); | 18 | extern int mpic_pasemi_msi_init(struct mpic *mpic); |
21 | #else | 19 | #else |
diff --git a/arch/powerpc/sysdev/mpic_msi.c b/arch/powerpc/sysdev/mpic_msi.c index de3e5e8bc324..1d44eee80fa1 100644 --- a/arch/powerpc/sysdev/mpic_msi.c +++ b/arch/powerpc/sysdev/mpic_msi.c | |||
@@ -15,59 +15,17 @@ | |||
15 | #include <asm/prom.h> | 15 | #include <asm/prom.h> |
16 | #include <asm/hw_irq.h> | 16 | #include <asm/hw_irq.h> |
17 | #include <asm/ppc-pci.h> | 17 | #include <asm/ppc-pci.h> |
18 | #include <asm/msi_bitmap.h> | ||
18 | 19 | ||
19 | #include <sysdev/mpic.h> | 20 | #include <sysdev/mpic.h> |
20 | 21 | ||
21 | static void __mpic_msi_reserve_hwirq(struct mpic *mpic, irq_hw_number_t hwirq) | ||
22 | { | ||
23 | pr_debug("mpic: reserving hwirq 0x%lx\n", hwirq); | ||
24 | bitmap_allocate_region(mpic->hwirq_bitmap, hwirq, 0); | ||
25 | } | ||
26 | |||
27 | void mpic_msi_reserve_hwirq(struct mpic *mpic, irq_hw_number_t hwirq) | 22 | void mpic_msi_reserve_hwirq(struct mpic *mpic, irq_hw_number_t hwirq) |
28 | { | 23 | { |
29 | unsigned long flags; | ||
30 | |||
31 | /* The mpic calls this even when there is no allocator setup */ | 24 | /* The mpic calls this even when there is no allocator setup */ |
32 | if (!mpic->hwirq_bitmap) | 25 | if (!mpic->msi_bitmap.bitmap) |
33 | return; | 26 | return; |
34 | 27 | ||
35 | spin_lock_irqsave(&mpic->bitmap_lock, flags); | 28 | msi_bitmap_reserve_hwirq(&mpic->msi_bitmap, hwirq); |
36 | __mpic_msi_reserve_hwirq(mpic, hwirq); | ||
37 | spin_unlock_irqrestore(&mpic->bitmap_lock, flags); | ||
38 | } | ||
39 | |||
40 | irq_hw_number_t mpic_msi_alloc_hwirqs(struct mpic *mpic, int num) | ||
41 | { | ||
42 | unsigned long flags; | ||
43 | int offset, order = get_count_order(num); | ||
44 | |||
45 | spin_lock_irqsave(&mpic->bitmap_lock, flags); | ||
46 | /* | ||
47 | * This is fast, but stricter than we need. We might want to add | ||
48 | * a fallback routine which does a linear search with no alignment. | ||
49 | */ | ||
50 | offset = bitmap_find_free_region(mpic->hwirq_bitmap, mpic->irq_count, | ||
51 | order); | ||
52 | spin_unlock_irqrestore(&mpic->bitmap_lock, flags); | ||
53 | |||
54 | pr_debug("mpic: allocated 0x%x (2^%d) at offset 0x%x\n", | ||
55 | num, order, offset); | ||
56 | |||
57 | return offset; | ||
58 | } | ||
59 | |||
60 | void mpic_msi_free_hwirqs(struct mpic *mpic, int offset, int num) | ||
61 | { | ||
62 | unsigned long flags; | ||
63 | int order = get_count_order(num); | ||
64 | |||
65 | pr_debug("mpic: freeing 0x%x (2^%d) at offset 0x%x\n", | ||
66 | num, order, offset); | ||
67 | |||
68 | spin_lock_irqsave(&mpic->bitmap_lock, flags); | ||
69 | bitmap_release_region(mpic->hwirq_bitmap, offset, order); | ||
70 | spin_unlock_irqrestore(&mpic->bitmap_lock, flags); | ||
71 | } | 29 | } |
72 | 30 | ||
73 | #ifdef CONFIG_MPIC_U3_HT_IRQS | 31 | #ifdef CONFIG_MPIC_U3_HT_IRQS |
@@ -83,13 +41,13 @@ static int mpic_msi_reserve_u3_hwirqs(struct mpic *mpic) | |||
83 | 41 | ||
84 | /* Reserve source numbers we know are reserved in the HW */ | 42 | /* Reserve source numbers we know are reserved in the HW */ |
85 | for (i = 0; i < 8; i++) | 43 | for (i = 0; i < 8; i++) |
86 | __mpic_msi_reserve_hwirq(mpic, i); | 44 | msi_bitmap_reserve_hwirq(&mpic->msi_bitmap, i); |
87 | 45 | ||
88 | for (i = 42; i < 46; i++) | 46 | for (i = 42; i < 46; i++) |
89 | __mpic_msi_reserve_hwirq(mpic, i); | 47 | msi_bitmap_reserve_hwirq(&mpic->msi_bitmap, i); |
90 | 48 | ||
91 | for (i = 100; i < 105; i++) | 49 | for (i = 100; i < 105; i++) |
92 | __mpic_msi_reserve_hwirq(mpic, i); | 50 | msi_bitmap_reserve_hwirq(&mpic->msi_bitmap, i); |
93 | 51 | ||
94 | np = NULL; | 52 | np = NULL; |
95 | while ((np = of_find_all_nodes(np))) { | 53 | while ((np = of_find_all_nodes(np))) { |
@@ -99,7 +57,7 @@ static int mpic_msi_reserve_u3_hwirqs(struct mpic *mpic) | |||
99 | while (of_irq_map_one(np, index++, &oirq) == 0) { | 57 | while (of_irq_map_one(np, index++, &oirq) == 0) { |
100 | ops->xlate(mpic->irqhost, NULL, oirq.specifier, | 58 | ops->xlate(mpic->irqhost, NULL, oirq.specifier, |
101 | oirq.size, &hwirq, &flags); | 59 | oirq.size, &hwirq, &flags); |
102 | __mpic_msi_reserve_hwirq(mpic, hwirq); | 60 | msi_bitmap_reserve_hwirq(&mpic->msi_bitmap, hwirq); |
103 | } | 61 | } |
104 | } | 62 | } |
105 | 63 | ||
@@ -112,70 +70,25 @@ static int mpic_msi_reserve_u3_hwirqs(struct mpic *mpic) | |||
112 | } | 70 | } |
113 | #endif | 71 | #endif |
114 | 72 | ||
115 | static int mpic_msi_reserve_dt_hwirqs(struct mpic *mpic) | ||
116 | { | ||
117 | int i, len; | ||
118 | const u32 *p; | ||
119 | |||
120 | p = of_get_property(mpic->irqhost->of_node, | ||
121 | "msi-available-ranges", &len); | ||
122 | if (!p) { | ||
123 | pr_debug("mpic: no msi-available-ranges property found on %s\n", | ||
124 | mpic->irqhost->of_node->full_name); | ||
125 | return -ENODEV; | ||
126 | } | ||
127 | |||
128 | if (len % 8 != 0) { | ||
129 | printk(KERN_WARNING "mpic: Malformed msi-available-ranges " | ||
130 | "property on %s\n", mpic->irqhost->of_node->full_name); | ||
131 | return -EINVAL; | ||
132 | } | ||
133 | |||
134 | bitmap_allocate_region(mpic->hwirq_bitmap, 0, | ||
135 | get_count_order(mpic->irq_count)); | ||
136 | |||
137 | /* Format is: (<u32 start> <u32 count>)+ */ | ||
138 | len /= sizeof(u32); | ||
139 | for (i = 0; i < len / 2; i++, p += 2) | ||
140 | mpic_msi_free_hwirqs(mpic, *p, *(p + 1)); | ||
141 | |||
142 | return 0; | ||
143 | } | ||
144 | |||
145 | int mpic_msi_init_allocator(struct mpic *mpic) | 73 | int mpic_msi_init_allocator(struct mpic *mpic) |
146 | { | 74 | { |
147 | int rc, size; | 75 | int rc; |
148 | |||
149 | BUG_ON(mpic->hwirq_bitmap); | ||
150 | spin_lock_init(&mpic->bitmap_lock); | ||
151 | 76 | ||
152 | size = BITS_TO_LONGS(mpic->irq_count) * sizeof(long); | 77 | rc = msi_bitmap_alloc(&mpic->msi_bitmap, mpic->irq_count, |
153 | pr_debug("mpic: allocator bitmap size is 0x%x bytes\n", size); | 78 | mpic->irqhost->of_node); |
79 | if (rc) | ||
80 | return rc; | ||
154 | 81 | ||
155 | mpic->hwirq_bitmap = alloc_maybe_bootmem(size, GFP_KERNEL); | 82 | rc = msi_bitmap_reserve_dt_hwirqs(&mpic->msi_bitmap); |
156 | 83 | if (rc > 0) { | |
157 | if (!mpic->hwirq_bitmap) { | ||
158 | pr_debug("mpic: ENOMEM allocating allocator bitmap!\n"); | ||
159 | return -ENOMEM; | ||
160 | } | ||
161 | |||
162 | memset(mpic->hwirq_bitmap, 0, size); | ||
163 | |||
164 | rc = mpic_msi_reserve_dt_hwirqs(mpic); | ||
165 | if (rc) { | ||
166 | if (mpic->flags & MPIC_U3_HT_IRQS) | 84 | if (mpic->flags & MPIC_U3_HT_IRQS) |
167 | rc = mpic_msi_reserve_u3_hwirqs(mpic); | 85 | rc = mpic_msi_reserve_u3_hwirqs(mpic); |
168 | 86 | ||
169 | if (rc) | 87 | if (rc) { |
170 | goto out_free; | 88 | msi_bitmap_free(&mpic->msi_bitmap); |
89 | return rc; | ||
90 | } | ||
171 | } | 91 | } |
172 | 92 | ||
173 | return 0; | 93 | return 0; |
174 | |||
175 | out_free: | ||
176 | if (mem_init_done) | ||
177 | kfree(mpic->hwirq_bitmap); | ||
178 | |||
179 | mpic->hwirq_bitmap = NULL; | ||
180 | return rc; | ||
181 | } | 94 | } |
diff --git a/arch/powerpc/sysdev/mpic_pasemi_msi.c b/arch/powerpc/sysdev/mpic_pasemi_msi.c index 68aff6076675..656cb772b691 100644 --- a/arch/powerpc/sysdev/mpic_pasemi_msi.c +++ b/arch/powerpc/sysdev/mpic_pasemi_msi.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <asm/prom.h> | 22 | #include <asm/prom.h> |
23 | #include <asm/hw_irq.h> | 23 | #include <asm/hw_irq.h> |
24 | #include <asm/ppc-pci.h> | 24 | #include <asm/ppc-pci.h> |
25 | #include <asm/msi_bitmap.h> | ||
25 | 26 | ||
26 | #include "mpic.h" | 27 | #include "mpic.h" |
27 | 28 | ||
@@ -81,8 +82,8 @@ static void pasemi_msi_teardown_msi_irqs(struct pci_dev *pdev) | |||
81 | continue; | 82 | continue; |
82 | 83 | ||
83 | set_irq_msi(entry->irq, NULL); | 84 | set_irq_msi(entry->irq, NULL); |
84 | mpic_msi_free_hwirqs(msi_mpic, virq_to_hw(entry->irq), | 85 | msi_bitmap_free_hwirqs(&msi_mpic->msi_bitmap, |
85 | ALLOC_CHUNK); | 86 | virq_to_hw(entry->irq), ALLOC_CHUNK); |
86 | irq_dispose_mapping(entry->irq); | 87 | irq_dispose_mapping(entry->irq); |
87 | } | 88 | } |
88 | 89 | ||
@@ -91,11 +92,10 @@ static void pasemi_msi_teardown_msi_irqs(struct pci_dev *pdev) | |||
91 | 92 | ||
92 | static int pasemi_msi_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type) | 93 | static int pasemi_msi_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type) |
93 | { | 94 | { |
94 | irq_hw_number_t hwirq; | ||
95 | unsigned int virq; | 95 | unsigned int virq; |
96 | struct msi_desc *entry; | 96 | struct msi_desc *entry; |
97 | struct msi_msg msg; | 97 | struct msi_msg msg; |
98 | int ret; | 98 | int hwirq; |
99 | 99 | ||
100 | pr_debug("pasemi_msi_setup_msi_irqs, pdev %p nvec %d type %d\n", | 100 | pr_debug("pasemi_msi_setup_msi_irqs, pdev %p nvec %d type %d\n", |
101 | pdev, nvec, type); | 101 | pdev, nvec, type); |
@@ -109,17 +109,19 @@ static int pasemi_msi_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type) | |||
109 | * few MSIs for someone, but restrictions will apply to how the | 109 | * few MSIs for someone, but restrictions will apply to how the |
110 | * sources can be changed independently. | 110 | * sources can be changed independently. |
111 | */ | 111 | */ |
112 | ret = mpic_msi_alloc_hwirqs(msi_mpic, ALLOC_CHUNK); | 112 | hwirq = msi_bitmap_alloc_hwirqs(&msi_mpic->msi_bitmap, |
113 | hwirq = ret; | 113 | ALLOC_CHUNK); |
114 | if (ret < 0) { | 114 | if (hwirq < 0) { |
115 | pr_debug("pasemi_msi: failed allocating hwirq\n"); | 115 | pr_debug("pasemi_msi: failed allocating hwirq\n"); |
116 | return hwirq; | 116 | return hwirq; |
117 | } | 117 | } |
118 | 118 | ||
119 | virq = irq_create_mapping(msi_mpic->irqhost, hwirq); | 119 | virq = irq_create_mapping(msi_mpic->irqhost, hwirq); |
120 | if (virq == NO_IRQ) { | 120 | if (virq == NO_IRQ) { |
121 | pr_debug("pasemi_msi: failed mapping hwirq 0x%lx\n", hwirq); | 121 | pr_debug("pasemi_msi: failed mapping hwirq 0x%x\n", |
122 | mpic_msi_free_hwirqs(msi_mpic, hwirq, ALLOC_CHUNK); | 122 | hwirq); |
123 | msi_bitmap_free_hwirqs(&msi_mpic->msi_bitmap, hwirq, | ||
124 | ALLOC_CHUNK); | ||
123 | return -ENOSPC; | 125 | return -ENOSPC; |
124 | } | 126 | } |
125 | 127 | ||
@@ -133,8 +135,8 @@ static int pasemi_msi_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type) | |||
133 | set_irq_chip(virq, &mpic_pasemi_msi_chip); | 135 | set_irq_chip(virq, &mpic_pasemi_msi_chip); |
134 | set_irq_type(virq, IRQ_TYPE_EDGE_RISING); | 136 | set_irq_type(virq, IRQ_TYPE_EDGE_RISING); |
135 | 137 | ||
136 | pr_debug("pasemi_msi: allocated virq 0x%x (hw 0x%lx) addr 0x%x\n", | 138 | pr_debug("pasemi_msi: allocated virq 0x%x (hw 0x%x) " \ |
137 | virq, hwirq, msg.address_lo); | 139 | "addr 0x%x\n", virq, hwirq, msg.address_lo); |
138 | 140 | ||
139 | /* Likewise, the device writes [0...511] into the target | 141 | /* Likewise, the device writes [0...511] into the target |
140 | * register to generate MSI [512...1023] | 142 | * register to generate MSI [512...1023] |
diff --git a/arch/powerpc/sysdev/mpic_u3msi.c b/arch/powerpc/sysdev/mpic_u3msi.c index 6e2f8686fdfc..0a8f5a9e87c9 100644 --- a/arch/powerpc/sysdev/mpic_u3msi.c +++ b/arch/powerpc/sysdev/mpic_u3msi.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <asm/prom.h> | 16 | #include <asm/prom.h> |
17 | #include <asm/hw_irq.h> | 17 | #include <asm/hw_irq.h> |
18 | #include <asm/ppc-pci.h> | 18 | #include <asm/ppc-pci.h> |
19 | #include <asm/msi_bitmap.h> | ||
19 | 20 | ||
20 | #include "mpic.h" | 21 | #include "mpic.h" |
21 | 22 | ||
@@ -101,7 +102,8 @@ static void u3msi_teardown_msi_irqs(struct pci_dev *pdev) | |||
101 | continue; | 102 | continue; |
102 | 103 | ||
103 | set_irq_msi(entry->irq, NULL); | 104 | set_irq_msi(entry->irq, NULL); |
104 | mpic_msi_free_hwirqs(msi_mpic, virq_to_hw(entry->irq), 1); | 105 | msi_bitmap_free_hwirqs(&msi_mpic->msi_bitmap, |
106 | virq_to_hw(entry->irq), 1); | ||
105 | irq_dispose_mapping(entry->irq); | 107 | irq_dispose_mapping(entry->irq); |
106 | } | 108 | } |
107 | 109 | ||
@@ -110,29 +112,27 @@ static void u3msi_teardown_msi_irqs(struct pci_dev *pdev) | |||
110 | 112 | ||
111 | static int u3msi_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type) | 113 | static int u3msi_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type) |
112 | { | 114 | { |
113 | irq_hw_number_t hwirq; | ||
114 | unsigned int virq; | 115 | unsigned int virq; |
115 | struct msi_desc *entry; | 116 | struct msi_desc *entry; |
116 | struct msi_msg msg; | 117 | struct msi_msg msg; |
117 | u64 addr; | 118 | u64 addr; |
118 | int ret; | 119 | int hwirq; |
119 | 120 | ||
120 | addr = find_ht_magic_addr(pdev); | 121 | addr = find_ht_magic_addr(pdev); |
121 | msg.address_lo = addr & 0xFFFFFFFF; | 122 | msg.address_lo = addr & 0xFFFFFFFF; |
122 | msg.address_hi = addr >> 32; | 123 | msg.address_hi = addr >> 32; |
123 | 124 | ||
124 | list_for_each_entry(entry, &pdev->msi_list, list) { | 125 | list_for_each_entry(entry, &pdev->msi_list, list) { |
125 | ret = mpic_msi_alloc_hwirqs(msi_mpic, 1); | 126 | hwirq = msi_bitmap_alloc_hwirqs(&msi_mpic->msi_bitmap, 1); |
126 | if (ret < 0) { | 127 | if (hwirq < 0) { |
127 | pr_debug("u3msi: failed allocating hwirq\n"); | 128 | pr_debug("u3msi: failed allocating hwirq\n"); |
128 | return ret; | 129 | return hwirq; |
129 | } | 130 | } |
130 | hwirq = ret; | ||
131 | 131 | ||
132 | virq = irq_create_mapping(msi_mpic->irqhost, hwirq); | 132 | virq = irq_create_mapping(msi_mpic->irqhost, hwirq); |
133 | if (virq == NO_IRQ) { | 133 | if (virq == NO_IRQ) { |
134 | pr_debug("u3msi: failed mapping hwirq 0x%lx\n", hwirq); | 134 | pr_debug("u3msi: failed mapping hwirq 0x%x\n", hwirq); |
135 | mpic_msi_free_hwirqs(msi_mpic, hwirq, 1); | 135 | msi_bitmap_free_hwirqs(&msi_mpic->msi_bitmap, hwirq, 1); |
136 | return -ENOSPC; | 136 | return -ENOSPC; |
137 | } | 137 | } |
138 | 138 | ||
@@ -140,8 +140,8 @@ static int u3msi_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type) | |||
140 | set_irq_chip(virq, &mpic_u3msi_chip); | 140 | set_irq_chip(virq, &mpic_u3msi_chip); |
141 | set_irq_type(virq, IRQ_TYPE_EDGE_RISING); | 141 | set_irq_type(virq, IRQ_TYPE_EDGE_RISING); |
142 | 142 | ||
143 | pr_debug("u3msi: allocated virq 0x%x (hw 0x%lx) addr 0x%lx\n", | 143 | pr_debug("u3msi: allocated virq 0x%x (hw 0x%x) addr 0x%lx\n", |
144 | virq, hwirq, addr); | 144 | virq, hwirq, (unsigned long)addr); |
145 | 145 | ||
146 | msg.data = hwirq; | 146 | msg.data = hwirq; |
147 | write_msi_msg(virq, &msg); | 147 | write_msi_msg(virq, &msg); |
diff --git a/arch/powerpc/sysdev/msi_bitmap.c b/arch/powerpc/sysdev/msi_bitmap.c new file mode 100644 index 000000000000..f84217b8863a --- /dev/null +++ b/arch/powerpc/sysdev/msi_bitmap.c | |||
@@ -0,0 +1,247 @@ | |||
1 | /* | ||
2 | * Copyright 2006-2008, Michael Ellerman, IBM Corporation. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or | ||
5 | * modify it under the terms of the GNU General Public License | ||
6 | * as published by the Free Software Foundation; version 2 of the | ||
7 | * License. | ||
8 | * | ||
9 | */ | ||
10 | |||
11 | #include <linux/kernel.h> | ||
12 | #include <linux/bitmap.h> | ||
13 | #include <asm/msi_bitmap.h> | ||
14 | |||
15 | int msi_bitmap_alloc_hwirqs(struct msi_bitmap *bmp, int num) | ||
16 | { | ||
17 | unsigned long flags; | ||
18 | int offset, order = get_count_order(num); | ||
19 | |||
20 | spin_lock_irqsave(&bmp->lock, flags); | ||
21 | /* | ||
22 | * This is fast, but stricter than we need. We might want to add | ||
23 | * a fallback routine which does a linear search with no alignment. | ||
24 | */ | ||
25 | offset = bitmap_find_free_region(bmp->bitmap, bmp->irq_count, order); | ||
26 | spin_unlock_irqrestore(&bmp->lock, flags); | ||
27 | |||
28 | pr_debug("msi_bitmap: allocated 0x%x (2^%d) at offset 0x%x\n", | ||
29 | num, order, offset); | ||
30 | |||
31 | return offset; | ||
32 | } | ||
33 | |||
34 | void msi_bitmap_free_hwirqs(struct msi_bitmap *bmp, unsigned int offset, | ||
35 | unsigned int num) | ||
36 | { | ||
37 | unsigned long flags; | ||
38 | int order = get_count_order(num); | ||
39 | |||
40 | pr_debug("msi_bitmap: freeing 0x%x (2^%d) at offset 0x%x\n", | ||
41 | num, order, offset); | ||
42 | |||
43 | spin_lock_irqsave(&bmp->lock, flags); | ||
44 | bitmap_release_region(bmp->bitmap, offset, order); | ||
45 | spin_unlock_irqrestore(&bmp->lock, flags); | ||
46 | } | ||
47 | |||
48 | void msi_bitmap_reserve_hwirq(struct msi_bitmap *bmp, unsigned int hwirq) | ||
49 | { | ||
50 | unsigned long flags; | ||
51 | |||
52 | pr_debug("msi_bitmap: reserving hwirq 0x%x\n", hwirq); | ||
53 | |||
54 | spin_lock_irqsave(&bmp->lock, flags); | ||
55 | bitmap_allocate_region(bmp->bitmap, hwirq, 0); | ||
56 | spin_unlock_irqrestore(&bmp->lock, flags); | ||
57 | } | ||
58 | |||
59 | /** | ||
60 | * msi_bitmap_reserve_dt_hwirqs - Reserve irqs specified in the device tree. | ||
61 | * @bmp: pointer to the MSI bitmap. | ||
62 | * | ||
63 | * Looks in the device tree to see if there is a property specifying which | ||
64 | * irqs can be used for MSI. If found those irqs reserved in the device tree | ||
65 | * are reserved in the bitmap. | ||
66 | * | ||
67 | * Returns 0 for success, < 0 if there was an error, and > 0 if no property | ||
68 | * was found in the device tree. | ||
69 | **/ | ||
70 | int msi_bitmap_reserve_dt_hwirqs(struct msi_bitmap *bmp) | ||
71 | { | ||
72 | int i, j, len; | ||
73 | const u32 *p; | ||
74 | |||
75 | if (!bmp->of_node) | ||
76 | return 1; | ||
77 | |||
78 | p = of_get_property(bmp->of_node, "msi-available-ranges", &len); | ||
79 | if (!p) { | ||
80 | pr_debug("msi_bitmap: no msi-available-ranges property " \ | ||
81 | "found on %s\n", bmp->of_node->full_name); | ||
82 | return 1; | ||
83 | } | ||
84 | |||
85 | if (len % (2 * sizeof(u32)) != 0) { | ||
86 | printk(KERN_WARNING "msi_bitmap: Malformed msi-available-ranges" | ||
87 | " property on %s\n", bmp->of_node->full_name); | ||
88 | return -EINVAL; | ||
89 | } | ||
90 | |||
91 | bitmap_allocate_region(bmp->bitmap, 0, get_count_order(bmp->irq_count)); | ||
92 | |||
93 | spin_lock(&bmp->lock); | ||
94 | |||
95 | /* Format is: (<u32 start> <u32 count>)+ */ | ||
96 | len /= 2 * sizeof(u32); | ||
97 | for (i = 0; i < len; i++, p += 2) { | ||
98 | for (j = 0; j < *(p + 1); j++) | ||
99 | bitmap_release_region(bmp->bitmap, *p + j, 0); | ||
100 | } | ||
101 | |||
102 | spin_unlock(&bmp->lock); | ||
103 | |||
104 | return 0; | ||
105 | } | ||
106 | |||
107 | int msi_bitmap_alloc(struct msi_bitmap *bmp, unsigned int irq_count, | ||
108 | struct device_node *of_node) | ||
109 | { | ||
110 | int size; | ||
111 | |||
112 | if (!irq_count) | ||
113 | return -EINVAL; | ||
114 | |||
115 | size = BITS_TO_LONGS(irq_count) * sizeof(long); | ||
116 | pr_debug("msi_bitmap: allocator bitmap size is 0x%x bytes\n", size); | ||
117 | |||
118 | bmp->bitmap = zalloc_maybe_bootmem(size, GFP_KERNEL); | ||
119 | if (!bmp->bitmap) { | ||
120 | pr_debug("msi_bitmap: ENOMEM allocating allocator bitmap!\n"); | ||
121 | return -ENOMEM; | ||
122 | } | ||
123 | |||
124 | /* We zalloc'ed the bitmap, so all irqs are free by default */ | ||
125 | spin_lock_init(&bmp->lock); | ||
126 | bmp->of_node = of_node_get(of_node); | ||
127 | bmp->irq_count = irq_count; | ||
128 | |||
129 | return 0; | ||
130 | } | ||
131 | |||
132 | void msi_bitmap_free(struct msi_bitmap *bmp) | ||
133 | { | ||
134 | /* we can't free the bitmap we don't know if it's bootmem etc. */ | ||
135 | of_node_put(bmp->of_node); | ||
136 | bmp->bitmap = NULL; | ||
137 | } | ||
138 | |||
139 | #ifdef CONFIG_MSI_BITMAP_SELFTEST | ||
140 | |||
141 | #define check(x) \ | ||
142 | if (!(x)) printk("msi_bitmap: test failed at line %d\n", __LINE__); | ||
143 | |||
144 | void test_basics(void) | ||
145 | { | ||
146 | struct msi_bitmap bmp; | ||
147 | int i, size = 512; | ||
148 | |||
149 | /* Can't allocate a bitmap of 0 irqs */ | ||
150 | check(msi_bitmap_alloc(&bmp, 0, NULL) != 0); | ||
151 | |||
152 | /* of_node may be NULL */ | ||
153 | check(0 == msi_bitmap_alloc(&bmp, size, NULL)); | ||
154 | |||
155 | /* Should all be free by default */ | ||
156 | check(0 == bitmap_find_free_region(bmp.bitmap, size, | ||
157 | get_count_order(size))); | ||
158 | bitmap_release_region(bmp.bitmap, 0, get_count_order(size)); | ||
159 | |||
160 | /* With no node, there's no msi-available-ranges, so expect > 0 */ | ||
161 | check(msi_bitmap_reserve_dt_hwirqs(&bmp) > 0); | ||
162 | |||
163 | /* Should all still be free */ | ||
164 | check(0 == bitmap_find_free_region(bmp.bitmap, size, | ||
165 | get_count_order(size))); | ||
166 | bitmap_release_region(bmp.bitmap, 0, get_count_order(size)); | ||
167 | |||
168 | /* Check we can fill it up and then no more */ | ||
169 | for (i = 0; i < size; i++) | ||
170 | check(msi_bitmap_alloc_hwirqs(&bmp, 1) >= 0); | ||
171 | |||
172 | check(msi_bitmap_alloc_hwirqs(&bmp, 1) < 0); | ||
173 | |||
174 | /* Should all be allocated */ | ||
175 | check(bitmap_find_free_region(bmp.bitmap, size, 0) < 0); | ||
176 | |||
177 | /* And if we free one we can then allocate another */ | ||
178 | msi_bitmap_free_hwirqs(&bmp, size / 2, 1); | ||
179 | check(msi_bitmap_alloc_hwirqs(&bmp, 1) == size / 2); | ||
180 | |||
181 | msi_bitmap_free(&bmp); | ||
182 | |||
183 | /* Clients may check bitmap == NULL for "not-allocated" */ | ||
184 | check(bmp.bitmap == NULL); | ||
185 | |||
186 | kfree(bmp.bitmap); | ||
187 | } | ||
188 | |||
189 | void test_of_node(void) | ||
190 | { | ||
191 | u32 prop_data[] = { 10, 10, 25, 3, 40, 1, 100, 100, 200, 20 }; | ||
192 | const char *expected_str = "0-9,20-24,28-39,41-99,220-255"; | ||
193 | char *prop_name = "msi-available-ranges"; | ||
194 | char *node_name = "/fakenode"; | ||
195 | struct device_node of_node; | ||
196 | struct property prop; | ||
197 | struct msi_bitmap bmp; | ||
198 | int size = 256; | ||
199 | DECLARE_BITMAP(expected, size); | ||
200 | |||
201 | /* There should really be a struct device_node allocator */ | ||
202 | memset(&of_node, 0, sizeof(of_node)); | ||
203 | kref_init(&of_node.kref); | ||
204 | of_node.full_name = node_name; | ||
205 | |||
206 | check(0 == msi_bitmap_alloc(&bmp, size, &of_node)); | ||
207 | |||
208 | /* No msi-available-ranges, so expect > 0 */ | ||
209 | check(msi_bitmap_reserve_dt_hwirqs(&bmp) > 0); | ||
210 | |||
211 | /* Should all still be free */ | ||
212 | check(0 == bitmap_find_free_region(bmp.bitmap, size, | ||
213 | get_count_order(size))); | ||
214 | bitmap_release_region(bmp.bitmap, 0, get_count_order(size)); | ||
215 | |||
216 | /* Now create a fake msi-available-ranges property */ | ||
217 | |||
218 | /* There should really .. oh whatever */ | ||
219 | memset(&prop, 0, sizeof(prop)); | ||
220 | prop.name = prop_name; | ||
221 | prop.value = &prop_data; | ||
222 | prop.length = sizeof(prop_data); | ||
223 | |||
224 | of_node.properties = ∝ | ||
225 | |||
226 | /* msi-available-ranges, so expect == 0 */ | ||
227 | check(msi_bitmap_reserve_dt_hwirqs(&bmp) == 0); | ||
228 | |||
229 | /* Check we got the expected result */ | ||
230 | check(0 == bitmap_parselist(expected_str, expected, size)); | ||
231 | check(bitmap_equal(expected, bmp.bitmap, size)); | ||
232 | |||
233 | msi_bitmap_free(&bmp); | ||
234 | kfree(bmp.bitmap); | ||
235 | } | ||
236 | |||
237 | int msi_bitmap_selftest(void) | ||
238 | { | ||
239 | printk(KERN_DEBUG "Running MSI bitmap self-tests ...\n"); | ||
240 | |||
241 | test_basics(); | ||
242 | test_of_node(); | ||
243 | |||
244 | return 0; | ||
245 | } | ||
246 | late_initcall(msi_bitmap_selftest); | ||
247 | #endif /* CONFIG_MSI_BITMAP_SELFTEST */ | ||
diff --git a/arch/powerpc/sysdev/ppc4xx_pci.c b/arch/powerpc/sysdev/ppc4xx_pci.c index fb368dfde5d4..9f6f73d584d6 100644 --- a/arch/powerpc/sysdev/ppc4xx_pci.c +++ b/arch/powerpc/sysdev/ppc4xx_pci.c | |||
@@ -30,14 +30,12 @@ | |||
30 | #include <asm/machdep.h> | 30 | #include <asm/machdep.h> |
31 | #include <asm/dcr.h> | 31 | #include <asm/dcr.h> |
32 | #include <asm/dcr-regs.h> | 32 | #include <asm/dcr-regs.h> |
33 | #include <mm/mmu_decl.h> | ||
33 | 34 | ||
34 | #include "ppc4xx_pci.h" | 35 | #include "ppc4xx_pci.h" |
35 | 36 | ||
36 | static int dma_offset_set; | 37 | static int dma_offset_set; |
37 | 38 | ||
38 | /* Move that to a useable header */ | ||
39 | extern unsigned long total_memory; | ||
40 | |||
41 | #define U64_TO_U32_LOW(val) ((u32)((val) & 0x00000000ffffffffULL)) | 39 | #define U64_TO_U32_LOW(val) ((u32)((val) & 0x00000000ffffffffULL)) |
42 | #define U64_TO_U32_HIGH(val) ((u32)((val) >> 32)) | 40 | #define U64_TO_U32_HIGH(val) ((u32)((val) >> 32)) |
43 | 41 | ||
@@ -105,7 +103,8 @@ static int __init ppc4xx_parse_dma_ranges(struct pci_controller *hose, | |||
105 | 103 | ||
106 | /* Default */ | 104 | /* Default */ |
107 | res->start = 0; | 105 | res->start = 0; |
108 | res->end = size = 0x80000000; | 106 | size = 0x80000000; |
107 | res->end = size - 1; | ||
109 | res->flags = IORESOURCE_MEM | IORESOURCE_PREFETCH; | 108 | res->flags = IORESOURCE_MEM | IORESOURCE_PREFETCH; |
110 | 109 | ||
111 | /* Get dma-ranges property */ | 110 | /* Get dma-ranges property */ |
@@ -167,13 +166,13 @@ static int __init ppc4xx_parse_dma_ranges(struct pci_controller *hose, | |||
167 | */ | 166 | */ |
168 | if (size < total_memory) { | 167 | if (size < total_memory) { |
169 | printk(KERN_ERR "%s: dma-ranges too small " | 168 | printk(KERN_ERR "%s: dma-ranges too small " |
170 | "(size=%llx total_memory=%lx)\n", | 169 | "(size=%llx total_memory=%llx)\n", |
171 | hose->dn->full_name, size, total_memory); | 170 | hose->dn->full_name, size, (u64)total_memory); |
172 | return -ENXIO; | 171 | return -ENXIO; |
173 | } | 172 | } |
174 | 173 | ||
175 | /* Check we are a power of 2 size and that base is a multiple of size*/ | 174 | /* Check we are a power of 2 size and that base is a multiple of size*/ |
176 | if (!is_power_of_2(size) || | 175 | if ((size & (size - 1)) != 0 || |
177 | (res->start & (size - 1)) != 0) { | 176 | (res->start & (size - 1)) != 0) { |
178 | printk(KERN_ERR "%s: dma-ranges unaligned\n", | 177 | printk(KERN_ERR "%s: dma-ranges unaligned\n", |
179 | hose->dn->full_name); | 178 | hose->dn->full_name); |
@@ -277,9 +276,16 @@ static void __init ppc4xx_probe_pci_bridge(struct device_node *np) | |||
277 | const int *bus_range; | 276 | const int *bus_range; |
278 | int primary = 0; | 277 | int primary = 0; |
279 | 278 | ||
279 | /* Check if device is enabled */ | ||
280 | if (!of_device_is_available(np)) { | ||
281 | printk(KERN_INFO "%s: Port disabled via device-tree\n", | ||
282 | np->full_name); | ||
283 | return; | ||
284 | } | ||
285 | |||
280 | /* Fetch config space registers address */ | 286 | /* Fetch config space registers address */ |
281 | if (of_address_to_resource(np, 0, &rsrc_cfg)) { | 287 | if (of_address_to_resource(np, 0, &rsrc_cfg)) { |
282 | printk(KERN_ERR "%s:Can't get PCI config register base !", | 288 | printk(KERN_ERR "%s: Can't get PCI config register base !", |
283 | np->full_name); | 289 | np->full_name); |
284 | return; | 290 | return; |
285 | } | 291 | } |
@@ -810,7 +816,7 @@ static int ppc460ex_pciex_init_port_hw(struct ppc4xx_pciex_port *port) | |||
810 | switch (port->index) { | 816 | switch (port->index) { |
811 | case 0: | 817 | case 0: |
812 | mtdcri(SDR0, PESDR0_460EX_L0CDRCTL, 0x00003230); | 818 | mtdcri(SDR0, PESDR0_460EX_L0CDRCTL, 0x00003230); |
813 | mtdcri(SDR0, PESDR0_460EX_L0DRV, 0x00000136); | 819 | mtdcri(SDR0, PESDR0_460EX_L0DRV, 0x00000130); |
814 | mtdcri(SDR0, PESDR0_460EX_L0CLK, 0x00000006); | 820 | mtdcri(SDR0, PESDR0_460EX_L0CLK, 0x00000006); |
815 | 821 | ||
816 | mtdcri(SDR0, PESDR0_460EX_PHY_CTL_RST,0x10000000); | 822 | mtdcri(SDR0, PESDR0_460EX_PHY_CTL_RST,0x10000000); |
@@ -821,10 +827,10 @@ static int ppc460ex_pciex_init_port_hw(struct ppc4xx_pciex_port *port) | |||
821 | mtdcri(SDR0, PESDR1_460EX_L1CDRCTL, 0x00003230); | 827 | mtdcri(SDR0, PESDR1_460EX_L1CDRCTL, 0x00003230); |
822 | mtdcri(SDR0, PESDR1_460EX_L2CDRCTL, 0x00003230); | 828 | mtdcri(SDR0, PESDR1_460EX_L2CDRCTL, 0x00003230); |
823 | mtdcri(SDR0, PESDR1_460EX_L3CDRCTL, 0x00003230); | 829 | mtdcri(SDR0, PESDR1_460EX_L3CDRCTL, 0x00003230); |
824 | mtdcri(SDR0, PESDR1_460EX_L0DRV, 0x00000136); | 830 | mtdcri(SDR0, PESDR1_460EX_L0DRV, 0x00000130); |
825 | mtdcri(SDR0, PESDR1_460EX_L1DRV, 0x00000136); | 831 | mtdcri(SDR0, PESDR1_460EX_L1DRV, 0x00000130); |
826 | mtdcri(SDR0, PESDR1_460EX_L2DRV, 0x00000136); | 832 | mtdcri(SDR0, PESDR1_460EX_L2DRV, 0x00000130); |
827 | mtdcri(SDR0, PESDR1_460EX_L3DRV, 0x00000136); | 833 | mtdcri(SDR0, PESDR1_460EX_L3DRV, 0x00000130); |
828 | mtdcri(SDR0, PESDR1_460EX_L0CLK, 0x00000006); | 834 | mtdcri(SDR0, PESDR1_460EX_L0CLK, 0x00000006); |
829 | mtdcri(SDR0, PESDR1_460EX_L1CLK, 0x00000006); | 835 | mtdcri(SDR0, PESDR1_460EX_L1CLK, 0x00000006); |
830 | mtdcri(SDR0, PESDR1_460EX_L2CLK, 0x00000006); | 836 | mtdcri(SDR0, PESDR1_460EX_L2CLK, 0x00000006); |
diff --git a/arch/powerpc/sysdev/qe_lib/Kconfig b/arch/powerpc/sysdev/qe_lib/Kconfig index 1ce546462be5..76ffbc48d4b9 100644 --- a/arch/powerpc/sysdev/qe_lib/Kconfig +++ b/arch/powerpc/sysdev/qe_lib/Kconfig | |||
@@ -24,12 +24,3 @@ config QE_USB | |||
24 | bool | 24 | bool |
25 | help | 25 | help |
26 | QE USB Host Controller support | 26 | QE USB Host Controller support |
27 | |||
28 | config QE_GPIO | ||
29 | bool "QE GPIO support" | ||
30 | depends on QUICC_ENGINE | ||
31 | select GENERIC_GPIO | ||
32 | select ARCH_REQUIRE_GPIOLIB | ||
33 | help | ||
34 | Say Y here if you're going to use hardware that connects to the | ||
35 | QE GPIOs. | ||