diff options
Diffstat (limited to 'arch/powerpc/sysdev/qe_lib/qe.c')
-rw-r--r-- | arch/powerpc/sysdev/qe_lib/qe.c | 36 |
1 files changed, 23 insertions, 13 deletions
diff --git a/arch/powerpc/sysdev/qe_lib/qe.c b/arch/powerpc/sysdev/qe_lib/qe.c index 90f87408b5d..3d57d3835b0 100644 --- a/arch/powerpc/sysdev/qe_lib/qe.c +++ b/arch/powerpc/sysdev/qe_lib/qe.c | |||
@@ -141,7 +141,7 @@ EXPORT_SYMBOL(qe_issue_cmd); | |||
141 | * 16 BRGs, which can be connected to the QE channels or output | 141 | * 16 BRGs, which can be connected to the QE channels or output |
142 | * as clocks. The BRGs are in two different block of internal | 142 | * as clocks. The BRGs are in two different block of internal |
143 | * memory mapped space. | 143 | * memory mapped space. |
144 | * The baud rate clock is the system clock divided by something. | 144 | * The BRG clock is the QE clock divided by 2. |
145 | * It was set up long ago during the initial boot phase and is | 145 | * It was set up long ago during the initial boot phase and is |
146 | * is given to us. | 146 | * is given to us. |
147 | * Baud rate clocks are zero-based in the driver code (as that maps | 147 | * Baud rate clocks are zero-based in the driver code (as that maps |
@@ -165,28 +165,38 @@ unsigned int get_brg_clk(void) | |||
165 | return brg_clk; | 165 | return brg_clk; |
166 | } | 166 | } |
167 | 167 | ||
168 | /* This function is used by UARTS, or anything else that uses a 16x | 168 | /* Program the BRG to the given sampling rate and multiplier |
169 | * oversampled clock. | 169 | * |
170 | * @brg: the BRG, 1-16 | ||
171 | * @rate: the desired sampling rate | ||
172 | * @multiplier: corresponds to the value programmed in GUMR_L[RDCR] or | ||
173 | * GUMR_L[TDCR]. E.g., if this BRG is the RX clock, and GUMR_L[RDCR]=01, | ||
174 | * then 'multiplier' should be 8. | ||
175 | * | ||
176 | * Also note that the value programmed into the BRGC register must be even. | ||
170 | */ | 177 | */ |
171 | void qe_setbrg(u32 brg, u32 rate) | 178 | void qe_setbrg(unsigned int brg, unsigned int rate, unsigned int multiplier) |
172 | { | 179 | { |
173 | volatile u32 *bp; | ||
174 | u32 divisor, tempval; | 180 | u32 divisor, tempval; |
175 | int div16 = 0; | 181 | u32 div16 = 0; |
176 | 182 | ||
177 | bp = &qe_immr->brg.brgc[brg]; | 183 | divisor = get_brg_clk() / (rate * multiplier); |
178 | 184 | ||
179 | divisor = (get_brg_clk() / rate); | ||
180 | if (divisor > QE_BRGC_DIVISOR_MAX + 1) { | 185 | if (divisor > QE_BRGC_DIVISOR_MAX + 1) { |
181 | div16 = 1; | 186 | div16 = QE_BRGC_DIV16; |
182 | divisor /= 16; | 187 | divisor /= 16; |
183 | } | 188 | } |
184 | 189 | ||
185 | tempval = ((divisor - 1) << QE_BRGC_DIVISOR_SHIFT) | QE_BRGC_ENABLE; | 190 | /* Errata QE_General4, which affects some MPC832x and MPC836x SOCs, says |
186 | if (div16) | 191 | that the BRG divisor must be even if you're not using divide-by-16 |
187 | tempval |= QE_BRGC_DIV16; | 192 | mode. */ |
193 | if (!div16 && (divisor & 1)) | ||
194 | divisor++; | ||
195 | |||
196 | tempval = ((divisor - 1) << QE_BRGC_DIVISOR_SHIFT) | | ||
197 | QE_BRGC_ENABLE | div16; | ||
188 | 198 | ||
189 | out_be32(bp, tempval); | 199 | out_be32(&qe_immr->brg.brgc[brg - 1], tempval); |
190 | } | 200 | } |
191 | 201 | ||
192 | /* Initialize SNUMs (thread serial numbers) according to | 202 | /* Initialize SNUMs (thread serial numbers) according to |