Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions arch/arm/boot/dts/overlays/revpi-flat-s-2022-overlay.dts
Original file line number Diff line number Diff line change
Expand Up @@ -369,10 +369,12 @@
fragment@8 {
target = <&uart3>;
__overlay__ {
linux,rs485-enabled-at-boot-time;
rs485-rts-active-low;
dmas = <&dma 19>;
dma-names = "tx";
pinctrl-names = "default";
pinctrl-0 = <&rs485_0_pins>;
linux,rs485-enabled-at-boot-time;
rs485-rts-active-low;
rs485-term-gpios = <&expander 14 GPIO_ACTIVE_LOW>;
status = "okay";
};
Expand Down
56 changes: 49 additions & 7 deletions drivers/dma/bcm2835-dma.c
Original file line number Diff line number Diff line change
Expand Up @@ -592,7 +592,8 @@ static void bcm2835_dma_fill_cb_chain_with_sg(
enum dma_transfer_direction direction,
struct bcm2835_cb_entry *cb,
struct scatterlist *sgl,
unsigned int sg_len)
unsigned int sg_len,
enum dma_slave_buswidth buswidth)
{
size_t len, max_len;
unsigned int i;
Expand All @@ -607,7 +608,7 @@ static void bcm2835_dma_fill_cb_chain_with_sg(
for (addr = sg_dma_address(sgent),
len = sg_dma_len(sgent);
len > 0;
addr += scb->len, len -= scb->len, cb++) {
cb++) {
scb = (struct bcm2711_dma40_scb *)cb->cb;
if (direction == DMA_DEV_TO_MEM) {
scb->dst = lower_32_bits(addr);
Expand All @@ -617,18 +618,46 @@ static void bcm2835_dma_fill_cb_chain_with_sg(
scb->srci = upper_32_bits(addr) | BCM2711_DMA40_INC;
}
scb->len = min(len, max_len);

addr += scb->len;
len -= scb->len;

/* Setup 2D X-Y len*/
scb->len /= buswidth;
scb->len--;
scb->len = BCM2711_DMA40_STRIDE(scb->len);
scb->len |= buswidth;
}
} else {
for (addr = sg_dma_address(sgent),
len = sg_dma_len(sgent);
len > 0;
addr += cb->cb->length, len -= cb->cb->length,
cb++) {
if (direction == DMA_DEV_TO_MEM)
cb->cb->dst = addr;
else
cb->cb->src = addr;
cb->cb->length = min(len, max_len);

addr += cb->cb->length;
len -= cb->cb->length;

if (!c->is_lite_channel) {
/* Setup 2D X-Y len*/
cb->cb->length /= buswidth;
cb->cb->length--;
cb->cb->length <<= 16;
cb->cb->length |= buswidth;
}

trace_printk("DMA: DUMP CB\n");
trace_printk("DMA: CB INFO: 0x%08x\n", cb->cb->info);
trace_printk("DMA: CB src: 0x%08x\n", cb->cb->src);
trace_printk("DMA: CB dst: 0x%08x\n", cb->cb->dst);
trace_printk("DMA: CB length: 0x%08x\n", cb->cb->length);
trace_printk("DMA: CB stride: 0x%08x\n", cb->cb->stride);
trace_printk("DMA: CB next: 0x%08x\n", cb->cb->next);
trace_printk("DMA: DUMP CB END\n");
}
}
}
Expand Down Expand Up @@ -897,6 +926,7 @@ static struct dma_async_tx_descriptor *bcm2835_dma_prep_slave_sg(
WIDE_SOURCE(c->dreq) | WIDE_DEST(c->dreq);
u32 extra = BCM2835_DMA_INT_EN;
size_t frames;
enum dma_slave_buswidth buswidth;

if (!is_slave_direction(direction)) {
dev_err(chan->device->dev,
Expand All @@ -910,6 +940,7 @@ static struct dma_async_tx_descriptor *bcm2835_dma_prep_slave_sg(
if (direction == DMA_DEV_TO_MEM) {
if (c->cfg.src_addr_width != DMA_SLAVE_BUSWIDTH_4_BYTES)
return NULL;
buswidth = c->cfg.src_addr_width;
src = c->cfg.src_addr;
/*
* One would think it ought to be possible to get the physical
Expand All @@ -921,8 +952,13 @@ static struct dma_async_tx_descriptor *bcm2835_dma_prep_slave_sg(
src |= 0x400000000ull;
info |= BCM2835_DMA_S_DREQ | BCM2835_DMA_D_INC;
} else {
if (c->cfg.dst_addr_width != DMA_SLAVE_BUSWIDTH_4_BYTES)
return NULL;
if (c->cfg.dst_addr_width != DMA_SLAVE_BUSWIDTH_4_BYTES) {
if (c->is_lite_channel)
return NULL;
if (c->cfg.dst_addr_width != DMA_SLAVE_BUSWIDTH_1_BYTE)
return NULL;
}
buswidth = c->cfg.dst_addr_width;
dst = c->cfg.dst_addr;
if (c->is_40bit_channel)
dst |= 0x400000000ull;
Expand All @@ -932,6 +968,10 @@ static struct dma_async_tx_descriptor *bcm2835_dma_prep_slave_sg(
/* count frames in sg list */
frames = bcm2835_dma_count_frames_for_sg(c, sgl, sg_len);

/* Set 2D mode for all but lite channels */
if (!c->is_lite_channel)
info |= BCM2835_DMA_TDMODE;

/* allocate the CB chain */
d = bcm2835_dma_create_cb_chain(c, direction, false,
info, extra,
Expand All @@ -942,7 +982,7 @@ static struct dma_async_tx_descriptor *bcm2835_dma_prep_slave_sg(

/* fill in frames with scatterlist pointers */
bcm2835_dma_fill_cb_chain_with_sg(c, direction, d->cb_list,
sgl, sg_len);
sgl, sg_len, buswidth);

return vchan_tx_prep(&c->vc, &d->vd, flags);
}
Expand Down Expand Up @@ -1261,7 +1301,9 @@ static int bcm2835_dma_probe(struct platform_device *pdev)
od->ddev.device_terminate_all = bcm2835_dma_terminate_all;
od->ddev.device_synchronize = bcm2835_dma_synchronize;
od->ddev.src_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_4_BYTES);
od->ddev.dst_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_4_BYTES);
/* TODO: support further byte widths */
od->ddev.dst_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
BIT(DMA_SLAVE_BUSWIDTH_4_BYTES);
od->ddev.directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV) |
BIT(DMA_MEM_TO_MEM);
od->ddev.residue_granularity = DMA_RESIDUE_GRANULARITY_BURST;
Expand Down
75 changes: 63 additions & 12 deletions drivers/tty/serial/amba-pl011.c
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,9 @@ struct uart_amba_port {
};

static unsigned int pl011_tx_empty(struct uart_port *port);
static void dump_buffer(unsigned char *buff, unsigned int len);
static void pl011_rs485_tx_start(struct uart_amba_port *uap);


static unsigned int pl011_reg_to_offset(const struct uart_amba_port *uap,
unsigned int reg)
Expand Down Expand Up @@ -403,18 +406,25 @@ static void pl011_dma_probe(struct uart_amba_port *uap)
/* DMA is the sole user of the platform data right now */
struct amba_pl011_data *plat = dev_get_platdata(uap->port.dev);
struct device *dev = uap->port.dev;
struct dma_slave_config tx_conf = {
.dst_addr = uap->port.mapbase +
pl011_reg_to_offset(uap, REG_DR),
.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE,
.direction = DMA_MEM_TO_DEV,
.dst_maxburst = uap->fifosize >> 1,
.device_fc = false,
};
struct dma_slave_config tx_conf;
struct dma_chan *chan;
dma_cap_mask_t mask;

tx_conf.dst_addr = uap->port.mapbase +
pl011_reg_to_offset(uap, REG_DR);
// XXX: translate from phys to bus address. Use dma-ranges property
// for this?
tx_conf.dst_addr -= 0x80000000;

printk(KERN_INFO "DST ADDR IS 0x%08x\n", (u32) tx_conf.dst_addr);

tx_conf.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
tx_conf.direction = DMA_MEM_TO_DEV;
tx_conf.dst_maxburst = uap->fifosize >> 1;
tx_conf.device_fc = false;

uap->dma_probed = true;

chan = dma_request_chan(dev, "tx");
if (IS_ERR(chan)) {
if (PTR_ERR(chan) == -EPROBE_DEFER) {
Expand Down Expand Up @@ -553,6 +563,8 @@ static void pl011_dma_tx_callback(void *data)
unsigned long flags;
u16 dmacr;

trace_printk("DMA TX CALLBACK\n");

spin_lock_irqsave(&uap->port.lock, flags);
if (uap->dmatx.queued)
dma_unmap_sg(dmatx->chan->device->dev, &dmatx->sg, 1,
Expand Down Expand Up @@ -588,6 +600,16 @@ static void pl011_dma_tx_callback(void *data)
spin_unlock_irqrestore(&uap->port.lock, flags);
}

static void dump_buffer(unsigned char *buff, unsigned int len)
{
int i;

for (i = 0; i < len; i++)
trace_printk("0x%02x (%c) ", buff[i], buff[i]);

trace_printk("\n");
}

/*
* Try to refill the TX DMA buffer.
* Locking: called with port lock held and IRQs disabled.
Expand Down Expand Up @@ -627,9 +649,12 @@ static int pl011_dma_tx_refill(struct uart_amba_port *uap)
if (count > PL011_DMA_BUFFER_SIZE)
count = PL011_DMA_BUFFER_SIZE;

if (xmit->tail < xmit->head)
if (xmit->tail < xmit->head) {
memcpy(&dmatx->buf[0], &xmit->buf[xmit->tail], count);
else {
trace_printk("Dumping DMA buffer (1)\n");
dump_buffer(dmatx->buf, count);
trace_printk("Dumping DMA buffer (1) END\n");
} else {
size_t first = UART_XMIT_SIZE - xmit->tail;
size_t second;

Expand All @@ -638,8 +663,17 @@ static int pl011_dma_tx_refill(struct uart_amba_port *uap)
second = count - first;

memcpy(&dmatx->buf[0], &xmit->buf[xmit->tail], first);
if (second)

trace_printk("Dumping DMA buffer (2a)\n");
dump_buffer(dmatx->buf, first);
trace_printk("Dumping DMA buffer (2a) END\n");

if (second) {
memcpy(&dmatx->buf[first], &xmit->buf[0], second);
trace_printk("Dumping DMA buffer (2b)\n");
dump_buffer(&dmatx->buf[first], second);
trace_printk("Dumping DMA buffer (2b) END\n");
}
}

dmatx->sg.length = count;
Expand Down Expand Up @@ -673,6 +707,10 @@ static int pl011_dma_tx_refill(struct uart_amba_port *uap)
/* Fire the DMA transaction */
dma_dev->device_issue_pending(chan);

if ((uap->port.rs485.flags & SER_RS485_ENABLED) &&
!uap->rs485_tx_started)
pl011_rs485_tx_start(uap);

uap->dmacr |= UART011_TXDMAE;
pl011_write(uap->dmacr, uap, REG_DMACR);
uap->dmatx.queued = true;
Expand Down Expand Up @@ -789,6 +827,10 @@ static inline bool pl011_dma_tx_start(struct uart_amba_port *uap)
return false;
}

if ((uap->port.rs485.flags & SER_RS485_ENABLED) &&
!uap->rs485_tx_started)
pl011_rs485_tx_start(uap);

pl011_write(uap->port.x_char, uap, REG_DR);
uap->port.icount.tx++;
uap->port.x_char = 0;
Expand Down Expand Up @@ -1357,8 +1399,11 @@ static void pl011_start_tx(struct uart_port *port)
struct uart_amba_port *uap =
container_of(port, struct uart_amba_port, port);

if (!pl011_dma_tx_start(uap))
if (!pl011_dma_tx_start(uap)) {
trace_printk("Using PIO instead of DMA\n");
pl011_start_tx_pio(uap);
} else
trace_printk("Using DMA !!!\n");
}

static void pl011_stop_rx(struct uart_port *port)
Expand Down Expand Up @@ -1432,6 +1477,7 @@ static bool pl011_tx_char(struct uart_amba_port *uap, unsigned char c,
pl011_read(uap, REG_FR) & UART01x_FR_TXFF)
return false; /* unable to transmit character */

trace_printk("PIO - 0x%02x (%c) ", c, c);
pl011_write(c, uap, REG_DR);
uap->port.icount.tx++;

Expand Down Expand Up @@ -1897,6 +1943,9 @@ static int pl011_startup(struct uart_port *port)
/* Startup DMA */
pl011_dma_startup(uap);

trace_printk("%s TX DMA\n", uap->using_tx_dma ? "USING " : "NOT USING ");
trace_printk("%s RX DMA\n", uap->using_rx_dma ? "USING " : "NOT USING ");

pl011_enable_interrupts(uap);

return 0;
Expand Down Expand Up @@ -2797,7 +2846,9 @@ static int pl011_setup_port(struct device *dev, struct uart_amba_port *uap,

uap->port.dev = dev;
uap->port.mapbase = mmiobase->start;
trace_printk("MAPBASE IS 0x%08x\n", (u32) mmiobase->start);
uap->port.membase = base;
trace_printk("MEMBASE IS 0x%08x\n", (u32) base);
uap->port.fifosize = uap->fifosize;
uap->port.has_sysrq = IS_ENABLED(CONFIG_SERIAL_AMBA_PL011_CONSOLE);
uap->port.flags = UPF_BOOT_AUTOCONF;
Expand Down
2 changes: 1 addition & 1 deletion localversion-rt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
-rt74
-rt75