diff options
Diffstat (limited to 'drivers/serial/serial_msm_geni.c')
| -rw-r--r-- | drivers/serial/serial_msm_geni.c | 107 |
1 files changed, 42 insertions, 65 deletions
diff --git a/drivers/serial/serial_msm_geni.c b/drivers/serial/serial_msm_geni.c index 0eb90f82a34..bb5a2cb4d2c 100644 --- a/drivers/serial/serial_msm_geni.c +++ b/drivers/serial/serial_msm_geni.c @@ -10,11 +10,14 @@ #include <asm/io.h> #include <clk.h> #include <dm.h> +#include <dm/device_compat.h> #include <errno.h> #include <linux/delay.h> #include <linux/time.h> #include <misc.h> #include <serial.h> +#include <soc/qcom/qup-fw-load.h> +#include <soc/qcom/geni-se.h> #define UART_OVERSAMPLING 32 #define STALE_TIMEOUT 160 @@ -22,8 +25,6 @@ /* Registers*/ #define GENI_FORCE_DEFAULT_REG 0x20 #define GENI_SER_M_CLK_CFG 0x48 -#define GENI_SER_S_CLK_CFG 0x4C -#define SE_HW_PARAM_0 0xE24 #define SE_GENI_STATUS 0x40 #define SE_GENI_S_CMD0 0x630 #define SE_GENI_S_CMD_CTRL_REG 0x634 @@ -39,7 +40,6 @@ #define SE_GENI_RX_FIFOn 0x780 #define SE_GENI_TX_FIFO_STATUS 0x800 #define SE_GENI_RX_FIFO_STATUS 0x804 -#define SE_GENI_TX_WATERMARK_REG 0x80C #define SE_GENI_TX_PACKING_CFG0 0x260 #define SE_GENI_TX_PACKING_CFG1 0x264 #define SE_GENI_RX_PACKING_CFG0 0x284 @@ -54,59 +54,24 @@ #define SE_UART_RX_TRANS_CFG 0x280 #define SE_UART_RX_PARITY_CFG 0x2a8 -#define M_TX_FIFO_WATERMARK_EN (BIT(30)) #define DEF_TX_WM 2 /* GENI_FORCE_DEFAULT_REG fields */ -#define FORCE_DEFAULT (BIT(0)) - -#define S_CMD_ABORT_EN (BIT(5)) #define UART_START_READ 0x1 -/* GENI_M_CMD_CTRL_REG */ -#define M_GENI_CMD_CANCEL (BIT(2)) -#define M_GENI_CMD_ABORT (BIT(1)) -#define M_GENI_DISABLE (BIT(0)) - -#define M_CMD_ABORT_EN (BIT(5)) -#define M_CMD_DONE_EN (BIT(0)) #define M_CMD_DONE_DISABLE_MASK (~M_CMD_DONE_EN) -#define S_GENI_CMD_ABORT (BIT(1)) - -/* GENI_S_CMD0 fields */ -#define S_OPCODE_MSK (GENMASK(31, 27)) -#define S_PARAMS_MSK (GENMASK(26, 0)) - -/* GENI_STATUS fields */ -#define M_GENI_CMD_ACTIVE (BIT(0)) -#define S_GENI_CMD_ACTIVE (BIT(12)) -#define M_CMD_DONE_EN (BIT(0)) -#define S_CMD_DONE_EN (BIT(0)) - #define M_OPCODE_SHIFT 27 #define S_OPCODE_SHIFT 27 -#define M_TX_FIFO_WATERMARK_EN (BIT(30)) #define UART_START_TX 0x1 #define UART_CTS_MASK (BIT(1)) -#define M_SEC_IRQ_EN (BIT(31)) #define TX_FIFO_WC_MSK (GENMASK(27, 0)) -#define RX_FIFO_WC_MSK (GENMASK(24, 0)) - -#define S_RX_FIFO_WATERMARK_EN (BIT(26)) -#define S_RX_FIFO_LAST_EN (BIT(27)) -#define M_RX_FIFO_WATERMARK_EN (BIT(26)) -#define M_RX_FIFO_LAST_EN (BIT(27)) /* GENI_SER_M_CLK_CFG/GENI_SER_S_CLK_CFG */ -#define SER_CLK_EN (BIT(0)) -#define CLK_DIV_MSK (GENMASK(15, 4)) #define CLK_DIV_SHFT 4 /* SE_HW_PARAM_0 fields */ -#define TX_FIFO_WIDTH_MSK (GENMASK(29, 24)) #define TX_FIFO_WIDTH_SHFT 24 -#define TX_FIFO_DEPTH_MSK (GENMASK(21, 16)) #define TX_FIFO_DEPTH_SHFT 16 /* GENI SE QUP Registers */ @@ -131,6 +96,7 @@ struct msm_serial_data { phys_addr_t base; u32 baud; u32 oversampling; + struct clk *se; }; unsigned long root_freq[] = {7372800, 14745600, 19200000, 29491200, @@ -181,19 +147,6 @@ static int get_clk_div_rate(u32 baud, u64 sampling_rate, u32 *clk_div) return ser_clk; } -static int geni_serial_set_clock_rate(struct udevice *dev, u64 rate) -{ - struct clk *clk; - int ret; - - clk = devm_clk_get(dev, NULL); - if (IS_ERR(clk)) - return PTR_ERR(clk); - - ret = clk_set_rate(clk, rate); - return ret; -} - /** * geni_se_get_tx_fifo_depth() - Get the TX fifo depth of the serial engine * @base: Pointer to the concerned serial engine. @@ -256,7 +209,7 @@ static int msm_serial_setbrg(struct udevice *dev, int baud) pr_err("%s: Couldn't get clock division rate\n", __func__); return -EINVAL; } - ret = geni_serial_set_clock_rate(dev, clk_rate); + ret = clk_set_rate(priv->se, clk_rate); if (ret < 0) { pr_err("%s: Couldn't set clock rate: %d\n", __func__, ret); return ret; @@ -561,6 +514,42 @@ static int msm_serial_probe(struct udevice *dev) { struct msm_serial_data *priv = dev_get_priv(dev); int ret; + u32 proto; + struct clk *clk; + + clk = devm_clk_get(dev, NULL); + if (IS_ERR(clk)) + return PTR_ERR(clk); + priv->se = clk; + + /* Try enable clock */ + ret = clk_enable(clk); + + /* Check if firmware loading is needed (BT UART) */ + proto = readl(priv->base + GENI_FW_REVISION_RO); + proto &= FW_REV_PROTOCOL_MSK; + proto >>= FW_REV_PROTOCOL_SHFT; + + if (proto == GENI_SE_INVALID_PROTO) { + qcom_geni_load_firmware(priv->base, dev); + proto = readl(priv->base + GENI_FW_REVISION_RO); + proto &= FW_REV_PROTOCOL_MSK; + proto >>= FW_REV_PROTOCOL_SHFT; + } + + if (proto != GENI_SE_UART) { + dev_err(dev, "Invalid proto %d\n", proto); + clk_disable(clk); + return -ENXIO; + } + + /* Don't actually probe non-debug UARTs */ + if (ofnode_device_is_compatible(dev_ofnode(dev), "qcom,geni-uart")) + return -ENOENT; + + /* Now handle clock enable return value */ + if (ret) + return ret; ret = geni_set_oversampling(dev); if (ret < 0) @@ -591,6 +580,7 @@ static int msm_serial_ofdata_to_platdata(struct udevice *dev) static const struct udevice_id msm_serial_ids[] = { { .compatible = "qcom,geni-debug-uart" }, + { .compatible = "qcom,geni-uart" }, { } }; @@ -605,19 +595,6 @@ U_BOOT_DRIVER(serial_msm_geni) = { .flags = DM_FLAG_PRE_RELOC | DM_FLAG_DEFAULT_PD_CTRL_OFF, }; -static const struct udevice_id geniqup_ids[] = { - { .compatible = "qcom,geni-se-qup" }, - { } -}; - -U_BOOT_DRIVER(geni_se_qup) = { - .name = "geni-se-qup", - .id = UCLASS_NOP, - .of_match = geniqup_ids, - .bind = dm_scan_fdt_dev, - .flags = DM_FLAG_PRE_RELOC | DM_FLAG_DEFAULT_PD_CTRL_OFF, -}; - #ifdef CONFIG_DEBUG_UART_MSM_GENI static struct msm_serial_data init_serial_data = { |
