aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/sysdev/qe_lib/qe.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/sysdev/qe_lib/qe.c')
-rw-r--r--arch/powerpc/sysdev/qe_lib/qe.c36
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 */
171void qe_setbrg(u32 brg, u32 rate) 178void 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