summaryrefslogtreecommitdiff
path: root/drivers/serial/serial_msm_geni.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/serial/serial_msm_geni.c')
-rw-r--r--drivers/serial/serial_msm_geni.c65
1 files changed, 47 insertions, 18 deletions
diff --git a/drivers/serial/serial_msm_geni.c b/drivers/serial/serial_msm_geni.c
index 3943ca43e49..78fd9389c03 100644
--- a/drivers/serial/serial_msm_geni.c
+++ b/drivers/serial/serial_msm_geni.c
@@ -11,15 +11,10 @@
#include <clk.h>
#include <common.h>
#include <dm.h>
-#include <dm/pinctrl.h>
#include <errno.h>
-#include <linux/compiler.h>
-#include <log.h>
#include <linux/delay.h>
-#include <malloc.h>
+#include <misc.h>
#include <serial.h>
-#include <watchdog.h>
-#include <linux/bug.h>
#define UART_OVERSAMPLING 32
#define STALE_TIMEOUT 160
@@ -116,6 +111,10 @@
#define TX_FIFO_DEPTH_MSK (GENMASK(21, 16))
#define TX_FIFO_DEPTH_SHFT 16
+/* GENI SE QUP Registers */
+#define QUP_HW_VER_REG 0x4
+#define QUP_SE_VERSION_2_5 0x20050000
+
/*
* Predefined packing configuration of the serial engine (CFG0, CFG1 regs)
* for uart mode.
@@ -133,11 +132,12 @@ DECLARE_GLOBAL_DATA_PTR;
struct msm_serial_data {
phys_addr_t base;
u32 baud;
+ u32 oversampling;
};
unsigned long root_freq[] = {7372800, 14745600, 19200000, 29491200,
- 32000000, 48000000, 64000000, 80000000,
- 96000000, 100000000};
+ 32000000, 48000000, 64000000, 80000000,
+ 96000000, 100000000};
/**
* get_clk_cfg() - Get clock rate to apply on clock supplier.
@@ -166,8 +166,7 @@ static int get_clk_cfg(unsigned long clk_freq)
*
* Return: frequency, supported by clock supplier, multiple of clk_freq.
*/
-static int get_clk_div_rate(u32 baud,
- u64 sampling_rate, u32 *clk_div)
+static int get_clk_div_rate(u32 baud, u64 sampling_rate, u32 *clk_div)
{
unsigned long ser_clk;
unsigned long desired_clk;
@@ -189,7 +188,7 @@ static int geni_serial_set_clock_rate(struct udevice *dev, u64 rate)
struct clk *clk;
int ret;
- clk = devm_clk_get(dev, "se-clk");
+ clk = devm_clk_get(dev, NULL);
if (!clk)
return -EINVAL;
@@ -234,7 +233,7 @@ static inline u32 geni_se_get_tx_fifo_width(long base)
}
static inline void geni_serial_baud(phys_addr_t base_address, u32 clk_div,
- int baud)
+ int baud)
{
u32 s_clk_cfg = 0;
@@ -245,15 +244,15 @@ static inline void geni_serial_baud(phys_addr_t base_address, u32 clk_div,
writel(s_clk_cfg, base_address + GENI_SER_S_CLK_CFG);
}
-int msm_serial_setbrg(struct udevice *dev, int baud)
+static int msm_serial_setbrg(struct udevice *dev, int baud)
{
struct msm_serial_data *priv = dev_get_priv(dev);
+ u64 clk_rate;
+ u32 clk_div;
priv->baud = baud;
- u32 clk_div;
- u64 clk_rate;
- clk_rate = get_clk_div_rate(baud, UART_OVERSAMPLING, &clk_div);
+ clk_rate = get_clk_div_rate(baud, priv->oversampling, &clk_div);
geni_serial_set_clock_rate(dev, clk_rate);
geni_serial_baud(priv->base, clk_div, baud);
@@ -274,7 +273,7 @@ int msm_serial_setbrg(struct udevice *dev, int baud)
* reached.
*/
static bool qcom_geni_serial_poll_bit(const struct udevice *dev, int offset,
- int field, bool set)
+ int field, bool set)
{
u32 reg;
struct msm_serial_data *priv = dev_get_priv(dev);
@@ -487,6 +486,31 @@ static const struct dm_serial_ops msm_serial_ops = {
.setbrg = msm_serial_setbrg,
};
+static void geni_set_oversampling(struct udevice *dev)
+{
+ struct msm_serial_data *priv = dev_get_priv(dev);
+ struct udevice *parent_dev = dev_get_parent(dev);
+ u32 geni_se_version;
+ int ret;
+
+ priv->oversampling = UART_OVERSAMPLING;
+
+ /*
+ * It could happen that GENI SE IP is missing in the board's device
+ * tree or GENI UART node is a direct child of SoC device tree node.
+ */
+ if (device_get_uclass_id(parent_dev) != UCLASS_MISC)
+ return;
+
+ ret = misc_read(parent_dev, QUP_HW_VER_REG,
+ &geni_se_version, sizeof(geni_se_version));
+ if (ret != sizeof(geni_se_version))
+ return;
+
+ if (geni_se_version >= QUP_SE_VERSION_2_5)
+ priv->oversampling /= 2;
+}
+
static inline void geni_serial_init(struct udevice *dev)
{
struct msm_serial_data *priv = dev_get_priv(dev);
@@ -530,6 +554,8 @@ static int msm_serial_probe(struct udevice *dev)
{
struct msm_serial_data *priv = dev_get_priv(dev);
+ geni_set_oversampling(dev);
+
/* No need to reinitialize the UART after relocation */
if (gd->flags & GD_FLG_RELOC)
return 0;
@@ -554,7 +580,9 @@ static int msm_serial_ofdata_to_platdata(struct udevice *dev)
}
static const struct udevice_id msm_serial_ids[] = {
- {.compatible = "qcom,msm-geni-uart"}, {}};
+ { .compatible = "qcom,geni-debug-uart" },
+ { }
+};
U_BOOT_DRIVER(serial_msm_geni) = {
.name = "serial_msm_geni",
@@ -564,6 +592,7 @@ U_BOOT_DRIVER(serial_msm_geni) = {
.priv_auto = sizeof(struct msm_serial_data),
.probe = msm_serial_probe,
.ops = &msm_serial_ops,
+ .flags = DM_FLAG_PRE_RELOC,
};
#ifdef CONFIG_DEBUG_UART_MSM_GENI