aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wan
diff options
context:
space:
mode:
authorKrzysztof Halasa <khc@pm.waw.pl>2009-09-04 23:59:49 -0400
committerDavid S. Miller <davem@davemloft.net>2009-09-07 04:56:49 -0400
commit5dbc46506a4f7b9f564bb7589a49ed32bc1caa15 (patch)
tree160ba16158671e2967e37f9d7feab8dbc2707141 /drivers/net/wan
parent32e6a0c82e7a7991a02414d830f262e1f4db73e6 (diff)
IXP42x HSS support for setting internal clock rate
HSS usually uses external clocks, so it's not a big deal. Internal clock is used for direct DTE-DTE connections and when the DCE doesn't provide it's own clock. This also depends on the oscillator frequency. Intel seems to have calculated the clock register settings for 33.33 MHz (66.66 MHz timer base). Their settings seem quite suboptimal both in terms of average frequency (60 ppm is unacceptable for G.703 applications, their primary intended usage(?)) and jitter. Many (most?) platforms use a 33.333 MHz oscillator, a 10 ppm difference from Intel's base. Instead of creating static tables, I've created a procedure to program the HSS clock register. The register consists of 3 parts (A, B, C). The average frequency (= bit rate) is: 66.66x MHz / (A + (B + 1) / (C + 1)) The procedure aims at the closest average frequency, possibly at the cost of increased jitter. Nobody would be able to directly drive an unbufferred transmitter with a HSS anyway, and the frequency error is what it really counts. I've verified the above with an oscilloscope on IXP425. It seems IXP46x and possibly IXP43x use a bit different clock generation algorithm - it looks like the avg frequency is: (on IXP465) 66.66x MHz / (A + B / (C + 1)). Also they use much greater precomputed A and B - on IXP425 it would simply result in more jitter, but I don't know how does it work on IXP46x (perhaps 3 least significant bits aren't used?). Anyway it looks that they were aiming for exactly +60 ppm or -60 ppm, while <1 ppm is typically possible (with a synchronized clock, of course). The attached patch makes it possible to set almost any bit rate (my IXP425 533 MHz quits at > 22 Mb/s if a single port is used, and the minimum is ca. 65 Kb/s). This is independent of MVIP (multi-E1/T1 on one HSS) mode. Signed-off-by: Krzysztof HaƂasa <khc@pm.waw.pl> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/wan')
-rw-r--r--drivers/net/wan/ixp4xx_hss.c95
1 files changed, 91 insertions, 4 deletions
diff --git a/drivers/net/wan/ixp4xx_hss.c b/drivers/net/wan/ixp4xx_hss.c
index bb719b6114cb..c705046d8615 100644
--- a/drivers/net/wan/ixp4xx_hss.c
+++ b/drivers/net/wan/ixp4xx_hss.c
@@ -166,6 +166,29 @@
166#define CLK46X_SPEED_4096KHZ (( 16 << 22) | (280 << 12) | 1023) 166#define CLK46X_SPEED_4096KHZ (( 16 << 22) | (280 << 12) | 1023)
167#define CLK46X_SPEED_8192KHZ (( 8 << 22) | (280 << 12) | 2047) 167#define CLK46X_SPEED_8192KHZ (( 8 << 22) | (280 << 12) | 2047)
168 168
169/*
170 * HSS_CONFIG_CLOCK_CR register consists of 3 parts:
171 * A (10 bits), B (10 bits) and C (12 bits).
172 * IXP42x HSS clock generator operation (verified with an oscilloscope):
173 * Each clock bit takes 7.5 ns (1 / 133.xx MHz).
174 * The clock sequence consists of (C - B) states of 0s and 1s, each state is
175 * A bits wide. It's followed by (B + 1) states of 0s and 1s, each state is
176 * (A + 1) bits wide.
177 *
178 * The resulting average clock frequency (assuming 33.333 MHz oscillator) is:
179 * freq = 66.666 MHz / (A + (B + 1) / (C + 1))
180 * minumum freq = 66.666 MHz / (A + 1)
181 * maximum freq = 66.666 MHz / A
182 *
183 * Example: A = 2, B = 2, C = 7, CLOCK_CR register = 2 << 22 | 2 << 12 | 7
184 * freq = 66.666 MHz / (2 + (2 + 1) / (7 + 1)) = 28.07 MHz (Mb/s).
185 * The clock sequence is: 1100110011 (5 doubles) 000111000 (3 triples).
186 * The sequence takes (C - B) * A + (B + 1) * (A + 1) = 5 * 2 + 3 * 3 bits
187 * = 19 bits (each 7.5 ns long) = 142.5 ns (then the sequence repeats).
188 * The sequence consists of 4 complete clock periods, thus the average
189 * frequency (= clock rate) is 4 / 142.5 ns = 28.07 MHz (Mb/s).
190 * (max specified clock rate for IXP42x HSS is 8.192 Mb/s).
191 */
169 192
170/* hss_config, LUT entries */ 193/* hss_config, LUT entries */
171#define TDMMAP_UNASSIGNED 0 194#define TDMMAP_UNASSIGNED 0
@@ -239,6 +262,7 @@ struct port {
239 unsigned int clock_type, clock_rate, loopback; 262 unsigned int clock_type, clock_rate, loopback;
240 unsigned int initialized, carrier; 263 unsigned int initialized, carrier;
241 u8 hdlc_cfg; 264 u8 hdlc_cfg;
265 u32 clock_reg;
242}; 266};
243 267
244/* NPE message structure */ 268/* NPE message structure */
@@ -393,7 +417,7 @@ static void hss_config(struct port *port)
393 msg.cmd = PORT_CONFIG_WRITE; 417 msg.cmd = PORT_CONFIG_WRITE;
394 msg.hss_port = port->id; 418 msg.hss_port = port->id;
395 msg.index = HSS_CONFIG_CLOCK_CR; 419 msg.index = HSS_CONFIG_CLOCK_CR;
396 msg.data32 = CLK42X_SPEED_2048KHZ /* FIXME */; 420 msg.data32 = port->clock_reg;
397 hss_npe_send(port, &msg, "HSS_SET_CLOCK_CR"); 421 hss_npe_send(port, &msg, "HSS_SET_CLOCK_CR");
398 422
399 memset(&msg, 0, sizeof(msg)); 423 memset(&msg, 0, sizeof(msg));
@@ -1160,6 +1184,62 @@ static int hss_hdlc_attach(struct net_device *dev, unsigned short encoding,
1160 } 1184 }
1161} 1185}
1162 1186
1187static u32 check_clock(u32 rate, u32 a, u32 b, u32 c,
1188 u32 *best, u32 *best_diff, u32 *reg)
1189{
1190 /* a is 10-bit, b is 10-bit, c is 12-bit */
1191 u64 new_rate;
1192 u32 new_diff;
1193
1194 new_rate = ixp4xx_timer_freq * (u64)(c + 1);
1195 do_div(new_rate, a * (c + 1) + b + 1);
1196 new_diff = abs((u32)new_rate - rate);
1197
1198 if (new_diff < *best_diff) {
1199 *best = new_rate;
1200 *best_diff = new_diff;
1201 *reg = (a << 22) | (b << 12) | c;
1202 }
1203 return new_diff;
1204}
1205
1206static void find_best_clock(u32 rate, u32 *best, u32 *reg)
1207{
1208 u32 a, b, diff = 0xFFFFFFFF;
1209
1210 a = ixp4xx_timer_freq / rate;
1211
1212 if (a > 0x3FF) { /* 10-bit value - we can go as slow as ca. 65 kb/s */
1213 check_clock(rate, 0x3FF, 1, 1, best, &diff, reg);
1214 return;
1215 }
1216 if (a == 0) { /* > 66.666 MHz */
1217 a = 1; /* minimum divider is 1 (a = 0, b = 1, c = 1) */
1218 rate = ixp4xx_timer_freq;
1219 }
1220
1221 if (rate * a == ixp4xx_timer_freq) { /* don't divide by 0 later */
1222 check_clock(rate, a - 1, 1, 1, best, &diff, reg);
1223 return;
1224 }
1225
1226 for (b = 0; b < 0x400; b++) {
1227 u64 c = (b + 1) * (u64)rate;
1228 do_div(c, ixp4xx_timer_freq - rate * a);
1229 c--;
1230 if (c >= 0xFFF) { /* 12-bit - no need to check more 'b's */
1231 if (b == 0 && /* also try a bit higher rate */
1232 !check_clock(rate, a - 1, 1, 1, best, &diff, reg))
1233 return;
1234 check_clock(rate, a, b, 0xFFF, best, &diff, reg);
1235 return;
1236 }
1237 if (!check_clock(rate, a, b, c, best, &diff, reg))
1238 return;
1239 if (!check_clock(rate, a, b, c + 1, best, &diff, reg))
1240 return;
1241 }
1242}
1163 1243
1164static int hss_hdlc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) 1244static int hss_hdlc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
1165{ 1245{
@@ -1182,7 +1262,7 @@ static int hss_hdlc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
1182 } 1262 }
1183 memset(&new_line, 0, sizeof(new_line)); 1263 memset(&new_line, 0, sizeof(new_line));
1184 new_line.clock_type = port->clock_type; 1264 new_line.clock_type = port->clock_type;
1185 new_line.clock_rate = 2048000; /* FIXME */ 1265 new_line.clock_rate = port->clock_rate;
1186 new_line.loopback = port->loopback; 1266 new_line.loopback = port->loopback;
1187 if (copy_to_user(line, &new_line, size)) 1267 if (copy_to_user(line, &new_line, size))
1188 return -EFAULT; 1268 return -EFAULT;
@@ -1206,7 +1286,13 @@ static int hss_hdlc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
1206 return -EINVAL; 1286 return -EINVAL;
1207 1287
1208 port->clock_type = clk; /* Update settings */ 1288 port->clock_type = clk; /* Update settings */
1209 /* FIXME port->clock_rate = new_line.clock_rate */; 1289 if (clk == CLOCK_INT)
1290 find_best_clock(new_line.clock_rate, &port->clock_rate,
1291 &port->clock_reg);
1292 else {
1293 port->clock_rate = 0;
1294 port->clock_reg = CLK42X_SPEED_2048KHZ;
1295 }
1210 port->loopback = new_line.loopback; 1296 port->loopback = new_line.loopback;
1211 1297
1212 spin_lock_irqsave(&npe_lock, flags); 1298 spin_lock_irqsave(&npe_lock, flags);
@@ -1266,7 +1352,8 @@ static int __devinit hss_init_one(struct platform_device *pdev)
1266 dev->netdev_ops = &hss_hdlc_ops; 1352 dev->netdev_ops = &hss_hdlc_ops;
1267 dev->tx_queue_len = 100; 1353 dev->tx_queue_len = 100;
1268 port->clock_type = CLOCK_EXT; 1354 port->clock_type = CLOCK_EXT;
1269 port->clock_rate = 2048000; 1355 port->clock_rate = 0;
1356 port->clock_reg = CLK42X_SPEED_2048KHZ;
1270 port->id = pdev->id; 1357 port->id = pdev->id;
1271 port->dev = &pdev->dev; 1358 port->dev = &pdev->dev;
1272 port->plat = pdev->dev.platform_data; 1359 port->plat = pdev->dev.platform_data;