NVIDIA: SAUCE: serial: pl011: add nvidia pl011 controller support

BugLink: https://bugs.launchpad.net/bugs/2080908

Add support for Nvidia's UART controller based on pl011.

http://nvbugs/3414248
http://nvbugs/4754882

Signed-off-by: kartik <kkartik@nvidia.com>
Tested-by: Petlozu Pravareshwar <petlozup@nvidia.com>
Signed-off-by: Laxman Dewangan <ldewangan@nvidia.com>
Acked-by: Noah Wager <noah.wager@canonical.com>
Acked-by: Jacob Martin <jacob.martin@canonical.com>
Signed-off-by: Noah Wager <noah.wager@canonical.com>
This commit is contained in:
kartik
2021-11-17 17:01:51 +05:30
committed by Noah Wager
parent 40587f6911
commit 0096d71b82
+56
View File
@@ -30,6 +30,7 @@
#include <linux/amba/bus.h>
#include <linux/amba/serial.h>
#include <linux/clk.h>
#include <linux/reset.h>
#include <linux/slab.h>
#include <linux/dmaengine.h>
#include <linux/dma-mapping.h>
@@ -114,6 +115,8 @@ struct vendor_data {
bool cts_event_workaround;
bool always_enabled;
bool fixed_options;
bool enable_car;
bool dma_workaround;
unsigned int (*get_fifosize)(struct amba_device *dev);
};
@@ -123,6 +126,23 @@ static unsigned int get_fifosize_arm(struct amba_device *dev)
return amba_rev(dev) < 3 ? 16 : 32;
}
static struct vendor_data vendor_nvidia = {
.reg_offset = pl011_std_offsets,
.ifls = UART011_IFLS_RX4_8|UART011_IFLS_TX4_8,
.fr_busy = UART01x_FR_BUSY,
.fr_dsr = UART01x_FR_DSR,
.fr_cts = UART01x_FR_CTS,
.fr_ri = UART011_FR_RI,
.oversampling = false,
.dma_threshold = false,
.cts_event_workaround = false,
.always_enabled = false,
.fixed_options = false,
.enable_car = true,
.dma_workaround = true,
.get_fifosize = get_fifosize_arm,
};
static struct vendor_data vendor_arm = {
.reg_offset = pl011_std_offsets,
.ifls = UART011_IFLS_RX4_8 | UART011_IFLS_TX4_8,
@@ -255,6 +275,7 @@ struct uart_amba_port {
struct uart_port port;
const u16 *reg_offset;
struct clk *clk;
struct reset_control *rst;
const struct vendor_data *vendor;
unsigned int dmacr; /* dma control reg */
unsigned int im; /* interrupt mask */
@@ -609,6 +630,19 @@ static int pl011_dma_tx_refill(struct uart_amba_port *uap)
*/
count -= 1;
/*
* Tegra GPC DMA driver requires the data to be multiple of burst size.
* Make count a multiple of burst size.
*/
if (uap->vendor->dma_workaround) {
count -= (count % (uap->fifosize >> 1));
if (count < (uap->fifosize >> 1)) {
uap->dmatx.queued = false;
return 0;
}
}
/* Else proceed to copy the TX chars to the DMA buffer and fire DMA */
if (count > PL011_DMA_BUFFER_SIZE)
count = PL011_DMA_BUFFER_SIZE;
@@ -2752,6 +2786,16 @@ static int pl011_register_port(struct uart_amba_port *uap)
{
int ret, i;
/* Reset the controller and enable clock for initial reg_write.
* This is required for Tegra Pl011 controller.
*/
if (uap->vendor->enable_car) {
reset_control_assert(uap->rst);
udelay(10);
reset_control_deassert(uap->rst);
clk_prepare_enable(uap->clk);
}
/* Ensure interrupts from this UART are masked and cleared */
pl011_write(0, uap, REG_IMSC);
pl011_write(0xffff, uap, REG_ICR);
@@ -2802,6 +2846,13 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id)
if (IS_ERR(uap->clk))
return PTR_ERR(uap->clk);
if (vendor->enable_car) {
uap->rst = devm_reset_control_get_exclusive(&dev->dev,
"serial");
if (IS_ERR(uap->rst))
return PTR_ERR(uap->rst);
}
uap->reg_offset = vendor->reg_offset;
uap->vendor = vendor;
uap->fifosize = vendor->get_fifosize(dev);
@@ -2985,6 +3036,11 @@ static const struct amba_id pl011_ids[] = {
.mask = 0x00ffffff,
.data = &vendor_st,
},
{
.id = 0x00051011,
.mask = 0x00ffffff,
.data = &vendor_nvidia,
},
{ 0, 0 },
};