serial baud_base, high baud rates and divisors
Hi,
when using a 720 (running linux, of course ;-) as serial console for a 715(old) I've noticed that the terminal (720) produces garbage when the 715 comes to the firmware prompt (both running at 115200). This is not a flow control or something problem. Investigating on that I've found some oddities concerning setserial, baud_base and the divisor calculation in the serial driver ...
- by default all parisc serial devices' baud_base is set to 454545 (derived from the LASI UART crystal's frequency). The actual divisor is calculated in change_speed() of serial.c to be
quot = baud_base / baud;
with all integers. Thus, 454545 / 115200 = 3. The resulting baud rate should be something like 454545 / 3 = 151515. That's somewhat far away from 115200, explaining the garbage.
- I've made a simple measurement of the actual baud rate using a DMM with builtin frequency counter: set the port to 8N1 and outputting 0x55 continously should produce a square wave of half the baud rate frequency at the transmit pin. So I've verified that at least the 720 seems to have a real baud_base of 460800 (the measured frequency was 57.6kHz for a divisor of 4).
- trying to change the baud_base using setserial to 460800 failed with EADDRINUSE. I've found the reason to be a loop in set_serial_info():
/* Make sure address is not already in use */
if (new_serial.type) {
for (i = 0 ; i < NR_PORTS; i++)
if ((state != &rs_table[i]) &&
(rs_table[i].port == new_port) &&
rs_table[i].type)
return -EADDRINUSE;
} Memory mapped parisc ports all have port == 0, so this has to fail. Temporary workaround: `setserial /dev/ttyS1 port 0x10000 ...' once will prevent the above loop from finding conflicts.
So, the following things have to be fixed:
- get/set_serial_info have to be enhanced for memory mapped ports
- setserial should be enhanced accordingly
- divisor calculation should be changed at least to round to nearest, not round towards zero, or LASI ports might still suffer from the first problem _if_ they really have baud_base 454545
- baud_base should be initialized correctly for other gsc based ports.
If someone can confirm my analysis and tell me the direction of how to fix these things I would be willing to work on it (shouldn't be hard, maybe boring ;-).
Enrik
Signature · 4 lines
Enrik Berkhan plan b. GmbH
Rüppurrer Straße 4
+49-721-388582 (voice) 76137 Karlsruhe
+49-721-388581 (fax) GermanyQuoted 8 lines · Enrik Berkhan
Hi,
when using a 720 (running linux, of course ;-) as serial console for a 715(old) I've noticed that the terminal (720) produces garbage when the 715 comes to the firmware prompt (both running at 115200). This is not a flow control or something problem. Investigating on that I've found some oddities concerning setserial,
baud_baseand the divisor calculation in the serial driver ...
AFAIK the firmware output only happens at 9600 baud (8N1) and you can't change that. After the linux kernel has booted you can of course use a higher rate.
Helge
Signature · 3 lines
Helge Deller SAP AG - LinuxLab and Unix Platforms email: [email protected]
Quoted 3 lines · Helge Deller
AFAIK the firmware output only happens at 9600 baud (8N1) and you can't change that. After the linux kernel has booted you can of course use a higher rate.
The firmware allows higher baud rates, at least on the 710, 715 and 720. I'm using it, so it does work ;-) Try "help rs232" when in boot admin mode.
Enrik
Signature · 4 lines
Enrik Berkhan plan b. GmbH
Rüppurrer Straße 4
+49-721-388582 (voice) 76137 Karlsruhe
+49-721-388581 (fax) GermanyQuoted 2 lines · Helge Deller
AFAIK the firmware output only happens at 9600 baud (8N1) and you can't change that.
Actually, I think one can. But I doubt HP is going to fix any firmware bugs related to console speeds other than 9600.
Running 19200 was crashing A500 console/GSP last year. I finally convinced the firmware team it was the same problem that happened at 9600 (less frequently of course).
I haven't verfied it was fixed in new PDC.
grant
Quoted 3 lines · Enrik Berkhan
Investigating on
that I've found some oddities concerning setserial,baud_baseand the divisor calculation in the serial driver ...
good work.
...
Quoted 8 lines
Memory mapped parisc ports all have port == 0, so this has to fail. Temporary workaround: `setserial
/dev/ttyS1port0x10000...' once will prevent the above loop from finding conflicts.So, the following things have to be fixed:
- get/set_serial_info have to be enhanced for memory mapped ports
- setserial should be enhanced accordingly
If other non-intel architectures don't have a solution for this. My first thought was to assign fake port addresses.
Do PCI serial cards also use MMIO?
Quoted 4 lines
- divisor calculation should be changed at least to round to nearest, not round towards zero, or LASI ports might still suffer from the first problem _if_ they really have
baud_base454545
-baud_baseshould be initialized correctly for other gsc based ports.
We'd have to dig a bit for documentation on this.
Please poke me offline if that doesn't happen in the next week or so.
Quoted 3 lines
If someone can confirm my analysis and tell me the direction of how to fix these things I would be willing to work on it (shouldn't be hard, maybe boring ;-).
cool - thanks,
grant
Quoted 5 lines · Grant Grundler
Quoted 2 lines
- get/set_serial_info have to be enhanced for memory mapped ports
- setserial should be enhanced accordinglyIf other non-intel architectures don't have a solution for this. My first thought was to assign fake port addresses.
Looks like most other architectures have their own code even when using 16450 like UARTs (e.g. arch/mips/au1000/common/serial.c). Especially set_serial_info is architecture dependent, because it just doesn't make much sense to fiddle with irq and port settings on parisc, does it? Faking port adresses could be a workaround, but it's not clean as it might make the ports show up in /proc/ioports ...
But enhancing the test for doubly assigned ports to
if ((rs_table[i].port == port) &&
(rs_table[i].iomem_base == req->iomem_base))might be ok. This code can be found in register_serial().
BTW, drivers/gsc/serial.c does no request_mem_region(). Is this in- tentional?
Quoted 1 line
Do PCI serial cards also use MMIO?
I don't know.
Quoted 4 lines
Quoted 1 line
-
baud_baseshould be initialized correctly for other gsc based ports.We'd have to dig a bit for documentation on this.
Please poke me offline if that doesn't happen in the next week or so.
The hardball ers states a 7.3728MHz (== 16 * 460800) baud rate clock, which confirms the output of my DMM. So we would need a table holding the baud_base for each device?
Enrik
Signature · 4 lines
Enrik Berkhan plan b. GmbH
Rüppurrer Straße 4
+49-721-388582 (voice) 76137 Karlsruhe
+49-721-388581 (fax) GermanyQuoted 6 lines · Enrik Berkhan
But enhancing the test for doubly assigned ports to
if ((rs_table[i].port == port) && (rs_table[i].iomem_base == req->iomem_base))might be ok. This code can be found in
register_serial().
Yeah - you are right.
Quoted 2 lines
BTW,
drivers/gsc/serial.cdoes norequest_mem_region(). Is this in- tentional?
probably. Check if an entry for serial exists in /prc/iomem. At one point, the device discover code was changed to automatically do the request_mem_region() devics firmware told us about.
Quoted 3 lines
The hardball ers states a 7.3728MHz (== 16 * 460800) baud rate clock, which confirms the output of my DMM. So we would need a table holding the
baud_basefor each device?
Dunno. We might given different generations of HW.
grant
Quoted 7 lines · Grant Grundler
Quoted 2 lines · Enrik Berkhan
BTW,
drivers/gsc/serial.cdoes norequest_mem_region(). Is this in- tentional?probably. Check if an entry for serial exists in /prc/iomem. At one point, the device discover code was changed to automatically do the
request_mem_region()devics firmware told us about.
Where one point' == last night' :-)
I'm not quite sure about the way I've done it -- I might set it up to always claim rather than only claim on device detection, and take the name from the hardware database rather than the driver.
I suspect I've broken module unload with the current code, and I need a release_mem_region on deregistration... investigating now.
Signature · 1 line
Revolutions do not require corporate support.