From 1c055e55a242a33e574e48be530e06770a210dcd Mon Sep 17 00:00:00 2001 From: hc <hc@nodka.com> Date: Mon, 19 Feb 2024 03:26:26 +0000 Subject: [PATCH] add r8169 read mac form eeprom --- kernel/drivers/tty/serial/max310x.c | 153 +++++++++++++++++++++++++++++++++----------------- 1 files changed, 100 insertions(+), 53 deletions(-) diff --git a/kernel/drivers/tty/serial/max310x.c b/kernel/drivers/tty/serial/max310x.c index c1ab0db..5bf8dd6 100644 --- a/kernel/drivers/tty/serial/max310x.c +++ b/kernel/drivers/tty/serial/max310x.c @@ -248,6 +248,7 @@ struct max310x_devtype { char name[9]; int nr; + u8 mode1; int (*detect)(struct device *); void (*power)(struct uart_port *, int); }; @@ -257,12 +258,17 @@ struct work_struct tx_work; struct work_struct md_work; struct work_struct rs_work; + + u8 wr_header; + u8 rd_header; + u8 rx_buf[MAX310X_FIFO_SIZE]; }; +#define to_max310x_port(_port) \ + container_of(_port, struct max310x_one, port) struct max310x_port { struct max310x_devtype *devtype; struct regmap *regmap; - struct mutex mutex; struct clk *clk; #ifdef CONFIG_GPIOLIB struct gpio_chip gpio; @@ -410,6 +416,7 @@ static const struct max310x_devtype max3107_devtype = { .name = "MAX3107", .nr = 1, + .mode1 = MAX310X_MODE1_AUTOSLEEP_BIT | MAX310X_MODE1_IRQSEL_BIT, .detect = max3107_detect, .power = max310x_power, }; @@ -417,6 +424,7 @@ static const struct max310x_devtype max3108_devtype = { .name = "MAX3108", .nr = 1, + .mode1 = MAX310X_MODE1_AUTOSLEEP_BIT, .detect = max3108_detect, .power = max310x_power, }; @@ -424,6 +432,7 @@ static const struct max310x_devtype max3109_devtype = { .name = "MAX3109", .nr = 2, + .mode1 = MAX310X_MODE1_AUTOSLEEP_BIT, .detect = max3109_detect, .power = max310x_power, }; @@ -431,6 +440,7 @@ static const struct max310x_devtype max14830_devtype = { .name = "MAX14830", .nr = 4, + .mode1 = MAX310X_MODE1_IRQSEL_BIT, .detect = max14830_detect, .power = max14830_power, }; @@ -613,11 +623,11 @@ static void max310x_batch_write(struct uart_port *port, u8 *txbuf, unsigned int len) { - u8 header[] = { (port->iobase + MAX310X_THR_REG) | MAX310X_WRITE_BIT }; + struct max310x_one *one = to_max310x_port(port); struct spi_transfer xfer[] = { { - .tx_buf = &header, - .len = sizeof(header), + .tx_buf = &one->wr_header, + .len = sizeof(one->wr_header), }, { .tx_buf = txbuf, .len = len, @@ -628,11 +638,11 @@ static void max310x_batch_read(struct uart_port *port, u8 *rxbuf, unsigned int len) { - u8 header[] = { port->iobase + MAX310X_RHR_REG }; + struct max310x_one *one = to_max310x_port(port); struct spi_transfer xfer[] = { { - .tx_buf = &header, - .len = sizeof(header), + .tx_buf = &one->rd_header, + .len = sizeof(one->rd_header), }, { .rx_buf = rxbuf, .len = len, @@ -643,8 +653,8 @@ static void max310x_handle_rx(struct uart_port *port, unsigned int rxlen) { + struct max310x_one *one = to_max310x_port(port); unsigned int sts, ch, flag, i; - u8 buf[MAX310X_FIFO_SIZE]; if (port->read_status_mask == MAX310X_LSR_RXOVR_BIT) { /* We are just reading, happily ignoring any error conditions. @@ -659,7 +669,7 @@ * */ sts = max310x_port_read(port, MAX310X_LSR_IRQSTS_REG); - max310x_batch_read(port, buf, rxlen); + max310x_batch_read(port, one->rx_buf, rxlen); port->icount.rx += rxlen; flag = TTY_NORMAL; @@ -670,9 +680,16 @@ port->icount.overrun++; } - for (i = 0; i < rxlen; ++i) { - uart_insert_char(port, sts, MAX310X_LSR_RXOVR_BIT, buf[i], flag); - } + for (i = 0; i < (rxlen - 1); ++i) + uart_insert_char(port, sts, 0, one->rx_buf[i], flag); + + /* + * Handle the overrun case for the last character only, since + * the RxFIFO overflow happens after it is pushed to the FIFO + * tail. + */ + uart_insert_char(port, sts, MAX310X_LSR_RXOVR_BIT, + one->rx_buf[rxlen-1], flag); } else { if (unlikely(rxlen >= port->fifosize)) { @@ -772,10 +789,9 @@ static void max310x_start_tx(struct uart_port *port) { - struct max310x_one *one = container_of(port, struct max310x_one, port); + struct max310x_one *one = to_max310x_port(port); - if (!work_pending(&one->tx_work)) - schedule_work(&one->tx_work); + schedule_work(&one->tx_work); } static irqreturn_t max310x_port_irq(struct max310x_port *s, int portno) @@ -832,14 +848,11 @@ return IRQ_RETVAL(handled); } -static void max310x_wq_proc(struct work_struct *ws) +static void max310x_tx_proc(struct work_struct *ws) { struct max310x_one *one = container_of(ws, struct max310x_one, tx_work); - struct max310x_port *s = dev_get_drvdata(one->port.dev); - mutex_lock(&s->mutex); max310x_handle_tx(&one->port); - mutex_unlock(&s->mutex); } static unsigned int max310x_tx_empty(struct uart_port *port) @@ -869,7 +882,7 @@ static void max310x_set_mctrl(struct uart_port *port, unsigned int mctrl) { - struct max310x_one *one = container_of(port, struct max310x_one, port); + struct max310x_one *one = to_max310x_port(port); schedule_work(&one->md_work); } @@ -942,16 +955,42 @@ /* Configure flow control */ max310x_port_write(port, MAX310X_XON1_REG, termios->c_cc[VSTART]); max310x_port_write(port, MAX310X_XOFF1_REG, termios->c_cc[VSTOP]); - if (termios->c_cflag & CRTSCTS) + + /* Disable transmitter before enabling AutoCTS or auto transmitter + * flow control + */ + if (termios->c_cflag & CRTSCTS || termios->c_iflag & IXOFF) { + max310x_port_update(port, MAX310X_MODE1_REG, + MAX310X_MODE1_TXDIS_BIT, + MAX310X_MODE1_TXDIS_BIT); + } + + port->status &= ~(UPSTAT_AUTOCTS | UPSTAT_AUTORTS | UPSTAT_AUTOXOFF); + + if (termios->c_cflag & CRTSCTS) { + /* Enable AUTORTS and AUTOCTS */ + port->status |= UPSTAT_AUTOCTS | UPSTAT_AUTORTS; flow |= MAX310X_FLOWCTRL_AUTOCTS_BIT | MAX310X_FLOWCTRL_AUTORTS_BIT; + } if (termios->c_iflag & IXON) flow |= MAX310X_FLOWCTRL_SWFLOW3_BIT | MAX310X_FLOWCTRL_SWFLOWEN_BIT; - if (termios->c_iflag & IXOFF) + if (termios->c_iflag & IXOFF) { + port->status |= UPSTAT_AUTOXOFF; flow |= MAX310X_FLOWCTRL_SWFLOW1_BIT | MAX310X_FLOWCTRL_SWFLOWEN_BIT; + } max310x_port_write(port, MAX310X_FLOWCTRL_REG, flow); + + /* Enable transmitter after disabling AutoCTS and auto transmitter + * flow control + */ + if (!(termios->c_cflag & CRTSCTS) && !(termios->c_iflag & IXOFF)) { + max310x_port_update(port, MAX310X_MODE1_REG, + MAX310X_MODE1_TXDIS_BIT, + 0); + } /* Get baud rate generator configuration */ baud = uart_get_baud_rate(port, termios, old, @@ -968,37 +1007,36 @@ static void max310x_rs_proc(struct work_struct *ws) { struct max310x_one *one = container_of(ws, struct max310x_one, rs_work); - unsigned int val; + unsigned int delay, mode1 = 0, mode2 = 0; - val = (one->port.rs485.delay_rts_before_send << 4) | + delay = (one->port.rs485.delay_rts_before_send << 4) | one->port.rs485.delay_rts_after_send; - max310x_port_write(&one->port, MAX310X_HDPIXDELAY_REG, val); + max310x_port_write(&one->port, MAX310X_HDPIXDELAY_REG, delay); if (one->port.rs485.flags & SER_RS485_ENABLED) { - max310x_port_update(&one->port, MAX310X_MODE1_REG, - MAX310X_MODE1_TRNSCVCTRL_BIT, - MAX310X_MODE1_TRNSCVCTRL_BIT); - max310x_port_update(&one->port, MAX310X_MODE2_REG, - MAX310X_MODE2_ECHOSUPR_BIT, - MAX310X_MODE2_ECHOSUPR_BIT); - } else { - max310x_port_update(&one->port, MAX310X_MODE1_REG, - MAX310X_MODE1_TRNSCVCTRL_BIT, 0); - max310x_port_update(&one->port, MAX310X_MODE2_REG, - MAX310X_MODE2_ECHOSUPR_BIT, 0); + mode1 = MAX310X_MODE1_TRNSCVCTRL_BIT; + + if (!(one->port.rs485.flags & SER_RS485_RX_DURING_TX)) + mode2 = MAX310X_MODE2_ECHOSUPR_BIT; } + + max310x_port_update(&one->port, MAX310X_MODE1_REG, + MAX310X_MODE1_TRNSCVCTRL_BIT, mode1); + max310x_port_update(&one->port, MAX310X_MODE2_REG, + MAX310X_MODE2_ECHOSUPR_BIT, mode2); } static int max310x_rs485_config(struct uart_port *port, struct serial_rs485 *rs485) { - struct max310x_one *one = container_of(port, struct max310x_one, port); + struct max310x_one *one = to_max310x_port(port); if ((rs485->delay_rts_before_send > 0x0f) || (rs485->delay_rts_after_send > 0x0f)) return -ERANGE; - rs485->flags &= SER_RS485_RTS_ON_SEND | SER_RS485_ENABLED; + rs485->flags &= SER_RS485_RTS_ON_SEND | SER_RS485_RX_DURING_TX | + SER_RS485_ENABLED; memset(rs485->padding, 0, sizeof(rs485->padding)); port->rs485 = *rs485; @@ -1023,6 +1061,22 @@ max310x_port_write(port, MAX310X_MODE2_REG, val); max310x_port_update(port, MAX310X_MODE2_REG, MAX310X_MODE2_FIFORST_BIT, 0); + + /* Configure mode1/mode2 to have rs485/rs232 enabled at startup */ + val = (clamp(port->rs485.delay_rts_before_send, 0U, 15U) << 4) | + clamp(port->rs485.delay_rts_after_send, 0U, 15U); + max310x_port_write(port, MAX310X_HDPIXDELAY_REG, val); + + if (port->rs485.flags & SER_RS485_ENABLED) { + max310x_port_update(port, MAX310X_MODE1_REG, + MAX310X_MODE1_TRNSCVCTRL_BIT, + MAX310X_MODE1_TRNSCVCTRL_BIT); + + if (!(port->rs485.flags & SER_RS485_RX_DURING_TX)) + max310x_port_update(port, MAX310X_MODE2_REG, + MAX310X_MODE2_ECHOSUPR_BIT, + MAX310X_MODE2_ECHOSUPR_BIT); + } /* Configure flow control levels */ /* Flow control halt level 96, resume level 48 */ @@ -1208,8 +1262,7 @@ return PTR_ERR(regmap); /* Alloc port structure */ - s = devm_kzalloc(dev, sizeof(*s) + - sizeof(struct max310x_one) * devtype->nr, GFP_KERNEL); + s = devm_kzalloc(dev, struct_size(s, p, devtype->nr), GFP_KERNEL); if (!s) { dev_err(dev, "Error allocating port structure\n"); return -ENOMEM; @@ -1269,15 +1322,12 @@ MAX310X_BRGDIVLSB_REG + offs, &ret); } while (ret != 0x01); - regmap_update_bits(s->regmap, MAX310X_MODE1_REG + offs, - MAX310X_MODE1_AUTOSLEEP_BIT, - MAX310X_MODE1_AUTOSLEEP_BIT); + regmap_write(s->regmap, MAX310X_MODE1_REG + offs, + devtype->mode1); } uartclk = max310x_set_ref_clk(dev, s, freq, xtal); dev_dbg(dev, "Reference clock set to %i Hz\n", uartclk); - - mutex_init(&s->mutex); for (i = 0; i < devtype->nr; i++) { unsigned int line; @@ -1305,16 +1355,16 @@ max310x_port_write(&s->p[i].port, MAX310X_IRQEN_REG, 0); /* Clear IRQ status register */ max310x_port_read(&s->p[i].port, MAX310X_IRQSTS_REG); - /* Enable IRQ pin */ - max310x_port_update(&s->p[i].port, MAX310X_MODE1_REG, - MAX310X_MODE1_IRQSEL_BIT, - MAX310X_MODE1_IRQSEL_BIT); /* Initialize queue for start TX */ - INIT_WORK(&s->p[i].tx_work, max310x_wq_proc); + INIT_WORK(&s->p[i].tx_work, max310x_tx_proc); /* Initialize queue for changing LOOPBACK mode */ INIT_WORK(&s->p[i].md_work, max310x_md_proc); /* Initialize queue for changing RS485 mode */ INIT_WORK(&s->p[i].rs_work, max310x_rs_proc); + /* Initialize SPI-transfer buffers */ + s->p[i].wr_header = (s->p[i].port.iobase + MAX310X_THR_REG) | + MAX310X_WRITE_BIT; + s->p[i].rd_header = (s->p[i].port.iobase + MAX310X_RHR_REG); /* Register port */ ret = uart_add_one_port(&max310x_uart, &s->p[i].port); @@ -1362,8 +1412,6 @@ } } - mutex_destroy(&s->mutex); - out_clk: clk_disable_unprepare(s->clk); @@ -1384,7 +1432,6 @@ s->devtype->power(&s->p[i].port, 0); } - mutex_destroy(&s->mutex); clk_disable_unprepare(s->clk); return 0; -- Gitblit v1.6.2