diff options
Diffstat (limited to 'arch/powerpc/sysdev')
| -rw-r--r-- | arch/powerpc/sysdev/dart.h | 6 | ||||
| -rw-r--r-- | arch/powerpc/sysdev/dart_iommu.c | 49 |
2 files changed, 48 insertions, 7 deletions
diff --git a/arch/powerpc/sysdev/dart.h b/arch/powerpc/sysdev/dart.h index c2d05763ccbe..1c8817c4835e 100644 --- a/arch/powerpc/sysdev/dart.h +++ b/arch/powerpc/sysdev/dart.h | |||
| @@ -47,8 +47,12 @@ | |||
| 47 | /* U4 registers */ | 47 | /* U4 registers */ |
| 48 | #define DART_BASE_U4_BASE_MASK 0xffffff | 48 | #define DART_BASE_U4_BASE_MASK 0xffffff |
| 49 | #define DART_BASE_U4_BASE_SHIFT 0 | 49 | #define DART_BASE_U4_BASE_SHIFT 0 |
| 50 | #define DART_CNTL_U4_FLUSHTLB 0x20000000 | ||
| 51 | #define DART_CNTL_U4_ENABLE 0x80000000 | 50 | #define DART_CNTL_U4_ENABLE 0x80000000 |
| 51 | #define DART_CNTL_U4_IONE 0x40000000 | ||
| 52 | #define DART_CNTL_U4_FLUSHTLB 0x20000000 | ||
| 53 | #define DART_CNTL_U4_IDLE 0x10000000 | ||
| 54 | #define DART_CNTL_U4_PAR_EN 0x08000000 | ||
| 55 | #define DART_CNTL_U4_IONE_MASK 0x07ffffff | ||
| 52 | #define DART_SIZE_U4_SIZE_MASK 0x1fff | 56 | #define DART_SIZE_U4_SIZE_MASK 0x1fff |
| 53 | #define DART_SIZE_U4_SIZE_SHIFT 0 | 57 | #define DART_SIZE_U4_SIZE_SHIFT 0 |
| 54 | 58 | ||
diff --git a/arch/powerpc/sysdev/dart_iommu.c b/arch/powerpc/sysdev/dart_iommu.c index 6232091cc72b..7c7f34ce4986 100644 --- a/arch/powerpc/sysdev/dart_iommu.c +++ b/arch/powerpc/sysdev/dart_iommu.c | |||
| @@ -101,8 +101,8 @@ retry: | |||
| 101 | if (l == (1L << limit)) { | 101 | if (l == (1L << limit)) { |
| 102 | if (limit < 4) { | 102 | if (limit < 4) { |
| 103 | limit++; | 103 | limit++; |
| 104 | reg = DART_IN(DART_CNTL); | 104 | reg = DART_IN(DART_CNTL); |
| 105 | reg &= ~inv_bit; | 105 | reg &= ~inv_bit; |
| 106 | DART_OUT(DART_CNTL, reg); | 106 | DART_OUT(DART_CNTL, reg); |
| 107 | goto retry; | 107 | goto retry; |
| 108 | } else | 108 | } else |
| @@ -111,11 +111,39 @@ retry: | |||
| 111 | } | 111 | } |
| 112 | } | 112 | } |
| 113 | 113 | ||
| 114 | static inline void dart_tlb_invalidate_one(unsigned long bus_rpn) | ||
| 115 | { | ||
| 116 | unsigned int reg; | ||
| 117 | unsigned int l, limit; | ||
| 118 | |||
| 119 | reg = DART_CNTL_U4_ENABLE | DART_CNTL_U4_IONE | | ||
| 120 | (bus_rpn & DART_CNTL_U4_IONE_MASK); | ||
| 121 | DART_OUT(DART_CNTL, reg); | ||
| 122 | |||
| 123 | limit = 0; | ||
| 124 | wait_more: | ||
| 125 | l = 0; | ||
| 126 | while ((DART_IN(DART_CNTL) & DART_CNTL_U4_IONE) && l < (1L << limit)) { | ||
| 127 | rmb(); | ||
| 128 | l++; | ||
| 129 | } | ||
| 130 | |||
| 131 | if (l == (1L << limit)) { | ||
| 132 | if (limit < 4) { | ||
| 133 | limit++; | ||
| 134 | goto wait_more; | ||
| 135 | } else | ||
| 136 | panic("DART: TLB did not flush after waiting a long " | ||
| 137 | "time. Buggy U4 ?"); | ||
| 138 | } | ||
| 139 | } | ||
| 140 | |||
| 114 | static void dart_flush(struct iommu_table *tbl) | 141 | static void dart_flush(struct iommu_table *tbl) |
| 115 | { | 142 | { |
| 116 | if (dart_dirty) | 143 | if (dart_dirty) { |
| 117 | dart_tlb_invalidate_all(); | 144 | dart_tlb_invalidate_all(); |
| 118 | dart_dirty = 0; | 145 | dart_dirty = 0; |
| 146 | } | ||
| 119 | } | 147 | } |
| 120 | 148 | ||
| 121 | static void dart_build(struct iommu_table *tbl, long index, | 149 | static void dart_build(struct iommu_table *tbl, long index, |
| @@ -124,6 +152,7 @@ static void dart_build(struct iommu_table *tbl, long index, | |||
| 124 | { | 152 | { |
| 125 | unsigned int *dp; | 153 | unsigned int *dp; |
| 126 | unsigned int rpn; | 154 | unsigned int rpn; |
| 155 | long l; | ||
| 127 | 156 | ||
| 128 | DBG("dart: build at: %lx, %lx, addr: %x\n", index, npages, uaddr); | 157 | DBG("dart: build at: %lx, %lx, addr: %x\n", index, npages, uaddr); |
| 129 | 158 | ||
| @@ -135,7 +164,8 @@ static void dart_build(struct iommu_table *tbl, long index, | |||
| 135 | /* On U3, all memory is contigous, so we can move this | 164 | /* On U3, all memory is contigous, so we can move this |
| 136 | * out of the loop. | 165 | * out of the loop. |
| 137 | */ | 166 | */ |
| 138 | while (npages--) { | 167 | l = npages; |
| 168 | while (l--) { | ||
| 139 | rpn = virt_to_abs(uaddr) >> DART_PAGE_SHIFT; | 169 | rpn = virt_to_abs(uaddr) >> DART_PAGE_SHIFT; |
| 140 | 170 | ||
| 141 | *(dp++) = DARTMAP_VALID | (rpn & DARTMAP_RPNMASK); | 171 | *(dp++) = DARTMAP_VALID | (rpn & DARTMAP_RPNMASK); |
| @@ -143,7 +173,14 @@ static void dart_build(struct iommu_table *tbl, long index, | |||
| 143 | uaddr += DART_PAGE_SIZE; | 173 | uaddr += DART_PAGE_SIZE; |
| 144 | } | 174 | } |
| 145 | 175 | ||
| 146 | dart_dirty = 1; | 176 | if (dart_is_u4) { |
| 177 | rpn = index; | ||
| 178 | mb(); /* make sure all updates have reached memory */ | ||
| 179 | while (npages--) | ||
| 180 | dart_tlb_invalidate_one(rpn++); | ||
| 181 | } else { | ||
| 182 | dart_dirty = 1; | ||
| 183 | } | ||
| 147 | } | 184 | } |
| 148 | 185 | ||
| 149 | 186 | ||
