From: fabrizio.gennari@philips.com
To: <linux-kernel@vger.kernel.org>
Subject: Patch for supporting CPR register in 16C950 UART
Date: Fri, 18 May 2001 18:14:23 +0200 [thread overview]
Message-ID: <0056900018047773000002L032*@MHS> (raw)
[-- Attachment #1: MEMO 05/18/01 18:00:46 --]
[-- Type: text/plain, Size: 909 bytes --]
Hello.
Here is a patch (tested on kernels 2.4.3 and 2.4.4) that adds 2 ioctl's in serial.c. One, TCSSERCPR, sets the CPR register in 16C950 UARTs. This register is a pre-scaler (that is, a divisor) for the clock. If the value is N, the clock is divided by N/8.
If N<8, pre-scaling is disabled by setting bit 7 of MCR to 0. The other one, TCGSERCPR,, reads the value of CPR. If pre-scaling is disabled, it returns 8 (i.e., the clock frequency is left intact).
The patch also disables resetting the UART via the CSR register every time the serial device is opened (in the startup() function). This would reset the content of CPR.
---------------------------------------------------------
Fabrizio Gennari tel. +39 039 203 7816
Philips Research Monza fax. +39 039 203 7800
via G. Casati 23 fabrizio.gennari@philips.com
20052 Monza (MI) Italy http://www.research.philips.com
[-- Attachment #2: serial-patch --]
[-- Type: application/octet-stream, Size: 3666 bytes --]
diff -ruN linux-2.4.3/drivers/char/serial.c linux-2.4.3-patched/drivers/char/serial.c
--- linux-2.4.3/drivers/char/serial.c Wed Mar 7 05:13:51 2001
+++ linux-2.4.3-patched/drivers/char/serial.c Fri May 18 16:28:30 2001
@@ -1259,7 +1259,7 @@
serial_outp(info, UART_EFR, UART_EFR_ECB);
serial_outp(info, UART_IER, 0);
serial_outp(info, UART_LCR, 0);
- serial_icr_write(info, UART_CSR, 0); /* Reset the UART */
+ /* serial_icr_write(info, UART_CSR, 0); */ /* Reset the UART */
serial_outp(info, UART_LCR, 0xBF);
serial_outp(info, UART_EFR, UART_EFR_ECB);
serial_outp(info, UART_LCR, 0);
@@ -1364,9 +1364,12 @@
*/
serial_outp(info, UART_LCR, UART_LCR_WLEN8); /* reset DLAB */
- info->MCR = 0;
+ if (state->type == PORT_16C950)
+ info->MCR &= UART_MCR_PRESCALER;
+ else
+ info->MCR = 0;
if (info->tty->termios->c_cflag & CBAUD)
- info->MCR = UART_MCR_DTR | UART_MCR_RTS;
+ info->MCR |= UART_MCR_DTR | UART_MCR_RTS;
#ifdef CONFIG_SERIAL_MANY_PORTS
if (info->flags & ASYNC_FOURPORT) {
if (state->irq == 0)
@@ -2514,6 +2517,41 @@
}
#endif
+static int get_clock_prescaler(struct async_struct * info, unsigned char *value)
+{
+ unsigned char cpr;
+
+ if (!(serial_in(info, UART_MCR) & UART_MCR_PRESCALER))
+ cpr = 8;
+ else
+ cpr = serial_icr_read(info, UART_CPR);
+
+ if (copy_to_user(value,&cpr,sizeof(unsigned char)))
+ return -EFAULT;
+
+ return 0;
+}
+
+static int set_clock_prescaler(struct async_struct * info, unsigned char *value)
+{
+ unsigned char cpr;
+
+ if (copy_from_user(&cpr,value,sizeof(unsigned char)))
+ return -EFAULT;
+
+ if (cpr < 8){
+ info->MCR &= ~UART_MCR_PRESCALER;
+ }
+ else{
+ info->MCR |= UART_MCR_PRESCALER;
+ }
+
+ serial_out(info, UART_MCR, info->MCR);
+ serial_icr_write(info, UART_CPR, cpr);
+
+ return 0;
+}
+
static int rs_ioctl(struct tty_struct *tty, struct file * file,
unsigned int cmd, unsigned long arg)
{
@@ -2668,6 +2706,14 @@
if (copy_to_user((void *)arg, &icount, sizeof(icount)))
return -EFAULT;
return 0;
+ case TIOCGSERCPR: /* Get serial clock prescaler */
+ if (info->state->type == PORT_16C950)
+ return get_clock_prescaler(info, (unsigned char *) arg);
+ return -ENXIO;
+ case TIOCSSERCPR: /* Set serial clock prescaler */
+ if (info->state->type == PORT_16C950)
+ return set_clock_prescaler(info, (unsigned char *) arg);
+ return -ENXIO;
case TIOCSERGWILD:
case TIOCSERSWILD:
/* "setserial -W" is called in Debian boot */
diff -ruN linux-2.4.3/include/asm-i386/ioctls.h linux-2.4.3-patched/include/asm-i386/ioctls.h
--- linux-2.4.3/include/asm-i386/ioctls.h Fri Jul 24 20:10:16 1998
+++ linux-2.4.3-patched/include/asm-i386/ioctls.h Thu May 17 16:34:08 2001
@@ -67,6 +67,8 @@
#define TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */
#define TIOCGHAYESESP 0x545E /* Get Hayes ESP configuration */
#define TIOCSHAYESESP 0x545F /* Set Hayes ESP configuration */
+#define TIOCGSERCPR 0x5460 /* Get serial clock prescaler*/
+#define TIOCSSERCPR 0x5461 /* Set serial clock prescaler*/
/* Used for packet mode */
#define TIOCPKT_DATA 0
diff -ruN linux-2.4.3/include/linux/serial_reg.h linux-2.4.3-patched/include/linux/serial_reg.h
--- linux-2.4.3/include/linux/serial_reg.h Wed Mar 7 04:28:35 2001
+++ linux-2.4.3-patched/include/linux/serial_reg.h Thu May 17 16:23:32 2001
@@ -121,6 +121,7 @@
/*
* These are the definitions for the Modem Control Register
*/
+#define UART_MCR_PRESCALER 0x80 /* Enable clock prescaler */
#define UART_MCR_LOOP 0x10 /* Enable loopback test mode */
#define UART_MCR_OUT2 0x08 /* Out2 complement */
#define UART_MCR_OUT1 0x04 /* Out1 complement */
reply other threads:[~2001-05-18 16:02 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to='0056900018047773000002L032*@MHS' \
--to=fabrizio.gennari@philips.com \
--cc=linux-kernel@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox