Loading Documentation/devicetree/bindings/spi/spi_qsd.txt +3 −1 Original line number Diff line number Diff line Qualcomm Serial Peripheral Interface (SPI) Required properties: - compatible : Should be "qcom,spi-qup-v2". - compatible : Should be "qcom,spi-qup-v2". Should "qcom,qup-v26" for controllers that support spi slave mode. - reg : Offset and length of the register regions for the device - reg-names : Register region names referenced in reg above. Required register resource entries are: Loading Loading @@ -72,6 +73,7 @@ the following properties. clock phase (CPHA) mode - spi-cs-high : (optional) Empty property indicating device requires chip select active high - qcom,slv-ctrl : Set this flag to configure QUP as SPI slave controller. Example: aliases { Loading drivers/spi/spi_qsd.c +91 −13 Original line number Diff line number Diff line Loading @@ -33,6 +33,7 @@ #include <linux/debugfs.h> #include <linux/gpio.h> #include <linux/of.h> #include <linux/of_device.h> #include <linux/of_gpio.h> #include <linux/dma-mapping.h> #include <linux/sched.h> Loading @@ -52,6 +53,7 @@ static int msm_spi_pm_suspend_runtime(struct device *device); static inline void msm_spi_dma_unmap_buffers(struct msm_spi *dd); static int get_local_resources(struct msm_spi *dd); static void put_local_resources(struct msm_spi *dd); static void msm_spi_slv_setup(struct msm_spi *dd); static inline int msm_spi_configure_gsbi(struct msm_spi *dd, struct platform_device *pdev) Loading Loading @@ -84,6 +86,9 @@ static inline int msm_spi_configure_gsbi(struct msm_spi *dd, static inline void msm_spi_register_init(struct msm_spi *dd) { if (dd->pdata->is_slv_ctrl) writel_relaxed(0x00000002, dd->base + SPI_SW_RESET); else writel_relaxed(0x00000001, dd->base + SPI_SW_RESET); msm_spi_set_state(dd, SPI_OP_STATE_RESET); writel_relaxed(0x00000000, dd->base + SPI_OPERATIONAL); Loading Loading @@ -932,6 +937,7 @@ static inline void msm_spi_ack_transfer(struct msm_spi *dd) static inline irqreturn_t msm_spi_qup_irq(int irq, void *dev_id) { u32 op, ret = IRQ_NONE; u32 slv; struct msm_spi *dd = dev_id; if (pm_runtime_suspended(dd->dev)) { Loading @@ -945,7 +951,9 @@ static inline irqreturn_t msm_spi_qup_irq(int irq, void *dev_id) } op = readl_relaxed(dd->base + SPI_OPERATIONAL); slv = readl_relaxed(dd->base + SPI_SLAVE_IRQ_STATUS); writel_relaxed(op, dd->base + SPI_OPERATIONAL); writel_relaxed(slv, dd->base + SPI_SLAVE_IRQ_STATUS); /* * Ensure service flag was cleared before further * processing of interrupt. Loading Loading @@ -1234,7 +1242,10 @@ msm_spi_use_dma(struct msm_spi *dd, struct spi_transfer *tr, u8 bpw) static void msm_spi_set_transfer_mode(struct msm_spi *dd, u8 bpw, u32 read_count) { if (msm_spi_use_dma(dd, dd->cur_transfer, bpw)) { if (dd->pdata->is_slv_ctrl) { dd->tx_mode = SPI_BAM_MODE; dd->rx_mode = SPI_BAM_MODE; } else if (msm_spi_use_dma(dd, dd->cur_transfer, bpw)) { dd->tx_mode = SPI_BAM_MODE; dd->rx_mode = SPI_BAM_MODE; } else { Loading Loading @@ -1353,7 +1364,7 @@ static void get_transfer_length(struct msm_spi *dd) static int msm_spi_process_transfer(struct msm_spi *dd) { u8 bpw; u32 max_speed; u32 max_speed = 0; u32 read_count; u32 timeout; u32 spi_ioc; Loading Loading @@ -1392,7 +1403,7 @@ static int msm_spi_process_transfer(struct msm_spi *dd) DIV_ROUND_UP(max_speed, MSEC_PER_SEC))); read_count = DIV_ROUND_UP(dd->cur_msg_len, dd->bytes_per_word); if (dd->spi->mode & SPI_LOOP) if (dd->spi->mode & SPI_LOOP && !dd->pdata->is_slv_ctrl) int_loopback = 1; if (msm_spi_set_state(dd, SPI_OP_STATE_RESET)) Loading @@ -1414,8 +1425,11 @@ static int msm_spi_process_transfer(struct msm_spi *dd) msm_spi_set_qup_io_modes(dd); msm_spi_set_spi_config(dd, bpw); msm_spi_set_qup_config(dd, bpw); if (!dd->pdata->is_slv_ctrl) spi_ioc = msm_spi_set_spi_io_control(dd); msm_spi_set_qup_op_mask(dd); if (dd->pdata->is_slv_ctrl) msm_spi_slv_setup(dd); /* The output fifo interrupt handler will handle all writes after the first. Restricting this to one write avoids contention Loading Loading @@ -1482,12 +1496,20 @@ transfer_end: dd->rx_mode = SPI_MODE_NONE; msm_spi_set_state(dd, SPI_OP_STATE_RESET); if (!dd->cur_transfer->cs_change) if (!dd->cur_transfer->cs_change && !dd->pdata->is_slv_ctrl) writel_relaxed(spi_ioc & ~SPI_IO_C_MX_CS_MODE, dd->base + SPI_IO_CONTROL); return status; } static int msm_spi_slv_abort(struct spi_master *spi) { struct msm_spi *dd = spi_master_get_devdata(spi); complete_all(&dd->tx_transfer_complete); complete_all(&dd->rx_transfer_complete); return 0; } static inline void msm_spi_set_cs(struct spi_device *spi, bool set_flag) { Loading Loading @@ -1753,6 +1775,32 @@ static int msm_spi_unprepare_transfer_hardware(struct spi_master *master) return 0; } static void msm_spi_slv_setup(struct msm_spi *dd) { u32 spi_config = readl_relaxed(dd->base + SPI_CONFIG); u32 qup_config = readl_relaxed(dd->base + QUP_CONFIG); u32 irq_en = GENMASK(6, 0); qup_config &= ~QUP_CFG_MODE; qup_config |= QUP_CONFIG_SPI_SLAVE; qup_config |= (SPI_EN_EXT_OUT_FLAG | APP_CLK_ON_EN | CORE_CLK_ON_EN | FIFO_CLK_ON_EN | CORE_EX_CLK_ON_EN); spi_config |= SPI_CFG_SLAVE_OP; writel_relaxed(qup_config, dd->base + QUP_CONFIG); writel_relaxed(spi_config, dd->base + SPI_CONFIG); writel_relaxed(irq_en, (dd->base + SPI_SLAVE_IRQ_EN)); if (dd->read_buf && !dd->write_buf) { u32 slv_cfg = readl_relaxed(dd->base + SPI_SLAVE_CONFIG); slv_cfg |= (RX_UNBALANCED_MASK | SPI_S_CGC_EN); writel_relaxed(slv_cfg, (dd->base + SPI_SLAVE_CONFIG)); } /* * Ensure Slave setup completes before returning. */ mb(); } static int msm_spi_setup(struct spi_device *spi) { struct msm_spi *dd; Loading Loading @@ -2248,6 +2296,8 @@ struct msm_spi_platform_data *msm_spi_dt_to_pdata( &pdata->rt_priority, DT_OPT, DT_BOOL, 0}, {"qcom,shared", &pdata->is_shared, DT_OPT, DT_BOOL, 0}, {"qcom,slv-ctrl", &pdata->is_slv_ctrl, DT_OPT, DT_BOOL, 0}, {NULL, NULL, 0, 0, 0}, }; Loading Loading @@ -2451,6 +2501,12 @@ err_clk_get: return rc; } static const struct of_device_id msm_spi_dt_match[] = { { .compatible = "qcom,spi-qup-v2", }, { .compatible = "qcom,qup-v26", }, {} }; static int msm_spi_probe(struct platform_device *pdev) { struct spi_master *master; Loading Loading @@ -2481,6 +2537,9 @@ static int msm_spi_probe(struct platform_device *pdev) dd = spi_master_get_devdata(master); if (pdev->dev.of_node) { const struct of_device_id *dev_id; enum msm_spi_qup_version ver; dd->qup_ver = SPI_QUP_VERSION_BFAM; master->dev.of_node = pdev->dev.of_node; pdata = msm_spi_dt_to_pdata(pdev, dd); Loading @@ -2495,6 +2554,17 @@ static int msm_spi_probe(struct platform_device *pdev) "using default bus_num %d\n", pdev->id); else master->bus_num = pdev->id = rc; dev_id = of_match_device(msm_spi_dt_match, &pdev->dev); if (dev_id) ver = SPI_QUP_VERSION_SPI_SLV; else ver = SPI_QUP_VERSION_BFAM; if (ver >= SPI_QUP_VERSION_SPI_SLV) dd->slv_support = true; else dd->slv_support = false; } else { pdata = pdev->dev.platform_data; dd->qup_ver = SPI_QUP_VERSION_NONE; Loading Loading @@ -2553,6 +2623,21 @@ static int msm_spi_probe(struct platform_device *pdev) } spi_dma_mask(&pdev->dev); if (pdata && pdata->is_slv_ctrl) { if (!dd->slv_support) { rc = -ENXIO; dev_err(&pdev->dev, "QUP ver %d, no slv support\n", dd->qup_ver); goto err_probe_res; } master->slave = true; master->set_cs = NULL; master->setup = NULL; master->slave_abort = msm_spi_slv_abort; } skip_dma_resources: spin_lock_init(&dd->queue_lock); Loading Loading @@ -2753,13 +2838,6 @@ static int msm_spi_remove(struct platform_device *pdev) return 0; } static struct of_device_id msm_spi_dt_match[] = { { .compatible = "qcom,spi-qup-v2", }, {} }; static const struct dev_pm_ops msm_spi_dev_pm_ops = { SET_SYSTEM_SLEEP_PM_OPS(msm_spi_suspend, msm_spi_resume) SET_RUNTIME_PM_OPS(msm_spi_pm_suspend_runtime, Loading drivers/spi/spi_qsd.h +29 −0 Original line number Diff line number Diff line Loading @@ -38,6 +38,7 @@ #define QUP_MX_WRITE_CNT_CURRENT 0x0154 #define QUP_CONFIG_SPI_MODE 0x0100 #define QUP_CONFIG_SPI_SLAVE 0x0400 #endif #define GSBI_CTRL_REG 0x0 Loading Loading @@ -72,17 +73,26 @@ #define SPI_OUTPUT_FIFO QSD_REG(0x0100) QUP_REG(0x0110) #define SPI_INPUT_FIFO QSD_REG(0x0200) QUP_REG(0x0218) #define SPI_STATE QSD_REG(SPI_OPERATIONAL) QUP_REG(0x0004) #define SPI_SLAVE_IRQ_STATUS (0x0330) #define SPI_SLAVE_IRQ_EN (0x0334) #define SPI_SLAVE_CONFIG (0x0338) /* QUP_CONFIG fields */ #define SPI_CFG_N 0x0000001F #define SPI_NO_INPUT 0x00000080 #define SPI_NO_OUTPUT 0x00000040 #define SPI_EN_EXT_OUT_FLAG 0x00010000 #define QUP_CFG_MODE 0x00000F00 #define APP_CLK_ON_EN BIT(12) #define CORE_CLK_ON_EN BIT(13) #define FIFO_CLK_ON_EN BIT(14) #define CORE_EX_CLK_ON_EN BIT(15) /* SPI_CONFIG fields */ #define SPI_CFG_LOOPBACK 0x00000100 #define SPI_CFG_INPUT_FIRST 0x00000200 #define SPI_CFG_HS_MODE 0x00000400 #define SPI_CFG_SLAVE_OP 0x00000020 /* SPI_IO_CONTROL fields */ #define SPI_IO_C_FORCE_CS 0x00000800 Loading Loading @@ -128,6 +138,23 @@ #define SPI_OP_STATE_CLEAR_BITS 0x2 /* SPI SLAVE IRQ_STATUS/EN fields */ #define CS_N_ASSERT BIT(0) #define CS_N_DEASSERT BIT(1) #define CS_N_ETXT BIT(2) #define TX_UNDERFLOW BIT(3) #define RX_OVERFLOW_WAIT_EOT BIT(4) #define RX_OVERFLOW_NO_EOT BIT(5) #define CS_N_ERXT BIT(6) /* SPI_SLAVE_CONFIG Fields */ #define RX_N_SHIFT BIT(0) #define PAUSE_ON_ERR_DIS BIT(1) #define SPI_S_CGC_EN BIT(2) #define RX_UNBALANCED_MASK BIT(3) #define SLAVE_DIS_RESET_ST BIT(4) #define SLAVE_AUTO_PAUSE_EOT BIT(7) #define SPI_PINCTRL_STATE_DEFAULT "spi_default" #define SPI_PINCTRL_STATE_SLEEP "spi_sleep" Loading Loading @@ -177,6 +204,7 @@ enum msm_spi_state { enum msm_spi_qup_version { SPI_QUP_VERSION_NONE = 0x0, SPI_QUP_VERSION_BFAM = 0x2, SPI_QUP_VERSION_SPI_SLV = 0x26, }; enum msm_spi_pipe_direction { Loading Loading @@ -376,6 +404,7 @@ struct msm_spi { struct pinctrl_state *pins_sleep; bool is_init_complete; bool pack_words; bool slv_support; }; /* Forward declaration */ Loading include/linux/spi/qcom-spi.h +2 −0 Original line number Diff line number Diff line Loading @@ -48,9 +48,11 @@ struct msm_spi_platform_data { u32 infinite_mode; bool ver_reg_exists; bool use_bam; bool slv_test; u32 bam_consumer_pipe_index; u32 bam_producer_pipe_index; bool rt_priority; bool use_pinctrl; bool is_shared; bool is_slv_ctrl; }; Loading
Documentation/devicetree/bindings/spi/spi_qsd.txt +3 −1 Original line number Diff line number Diff line Qualcomm Serial Peripheral Interface (SPI) Required properties: - compatible : Should be "qcom,spi-qup-v2". - compatible : Should be "qcom,spi-qup-v2". Should "qcom,qup-v26" for controllers that support spi slave mode. - reg : Offset and length of the register regions for the device - reg-names : Register region names referenced in reg above. Required register resource entries are: Loading Loading @@ -72,6 +73,7 @@ the following properties. clock phase (CPHA) mode - spi-cs-high : (optional) Empty property indicating device requires chip select active high - qcom,slv-ctrl : Set this flag to configure QUP as SPI slave controller. Example: aliases { Loading
drivers/spi/spi_qsd.c +91 −13 Original line number Diff line number Diff line Loading @@ -33,6 +33,7 @@ #include <linux/debugfs.h> #include <linux/gpio.h> #include <linux/of.h> #include <linux/of_device.h> #include <linux/of_gpio.h> #include <linux/dma-mapping.h> #include <linux/sched.h> Loading @@ -52,6 +53,7 @@ static int msm_spi_pm_suspend_runtime(struct device *device); static inline void msm_spi_dma_unmap_buffers(struct msm_spi *dd); static int get_local_resources(struct msm_spi *dd); static void put_local_resources(struct msm_spi *dd); static void msm_spi_slv_setup(struct msm_spi *dd); static inline int msm_spi_configure_gsbi(struct msm_spi *dd, struct platform_device *pdev) Loading Loading @@ -84,6 +86,9 @@ static inline int msm_spi_configure_gsbi(struct msm_spi *dd, static inline void msm_spi_register_init(struct msm_spi *dd) { if (dd->pdata->is_slv_ctrl) writel_relaxed(0x00000002, dd->base + SPI_SW_RESET); else writel_relaxed(0x00000001, dd->base + SPI_SW_RESET); msm_spi_set_state(dd, SPI_OP_STATE_RESET); writel_relaxed(0x00000000, dd->base + SPI_OPERATIONAL); Loading Loading @@ -932,6 +937,7 @@ static inline void msm_spi_ack_transfer(struct msm_spi *dd) static inline irqreturn_t msm_spi_qup_irq(int irq, void *dev_id) { u32 op, ret = IRQ_NONE; u32 slv; struct msm_spi *dd = dev_id; if (pm_runtime_suspended(dd->dev)) { Loading @@ -945,7 +951,9 @@ static inline irqreturn_t msm_spi_qup_irq(int irq, void *dev_id) } op = readl_relaxed(dd->base + SPI_OPERATIONAL); slv = readl_relaxed(dd->base + SPI_SLAVE_IRQ_STATUS); writel_relaxed(op, dd->base + SPI_OPERATIONAL); writel_relaxed(slv, dd->base + SPI_SLAVE_IRQ_STATUS); /* * Ensure service flag was cleared before further * processing of interrupt. Loading Loading @@ -1234,7 +1242,10 @@ msm_spi_use_dma(struct msm_spi *dd, struct spi_transfer *tr, u8 bpw) static void msm_spi_set_transfer_mode(struct msm_spi *dd, u8 bpw, u32 read_count) { if (msm_spi_use_dma(dd, dd->cur_transfer, bpw)) { if (dd->pdata->is_slv_ctrl) { dd->tx_mode = SPI_BAM_MODE; dd->rx_mode = SPI_BAM_MODE; } else if (msm_spi_use_dma(dd, dd->cur_transfer, bpw)) { dd->tx_mode = SPI_BAM_MODE; dd->rx_mode = SPI_BAM_MODE; } else { Loading Loading @@ -1353,7 +1364,7 @@ static void get_transfer_length(struct msm_spi *dd) static int msm_spi_process_transfer(struct msm_spi *dd) { u8 bpw; u32 max_speed; u32 max_speed = 0; u32 read_count; u32 timeout; u32 spi_ioc; Loading Loading @@ -1392,7 +1403,7 @@ static int msm_spi_process_transfer(struct msm_spi *dd) DIV_ROUND_UP(max_speed, MSEC_PER_SEC))); read_count = DIV_ROUND_UP(dd->cur_msg_len, dd->bytes_per_word); if (dd->spi->mode & SPI_LOOP) if (dd->spi->mode & SPI_LOOP && !dd->pdata->is_slv_ctrl) int_loopback = 1; if (msm_spi_set_state(dd, SPI_OP_STATE_RESET)) Loading @@ -1414,8 +1425,11 @@ static int msm_spi_process_transfer(struct msm_spi *dd) msm_spi_set_qup_io_modes(dd); msm_spi_set_spi_config(dd, bpw); msm_spi_set_qup_config(dd, bpw); if (!dd->pdata->is_slv_ctrl) spi_ioc = msm_spi_set_spi_io_control(dd); msm_spi_set_qup_op_mask(dd); if (dd->pdata->is_slv_ctrl) msm_spi_slv_setup(dd); /* The output fifo interrupt handler will handle all writes after the first. Restricting this to one write avoids contention Loading Loading @@ -1482,12 +1496,20 @@ transfer_end: dd->rx_mode = SPI_MODE_NONE; msm_spi_set_state(dd, SPI_OP_STATE_RESET); if (!dd->cur_transfer->cs_change) if (!dd->cur_transfer->cs_change && !dd->pdata->is_slv_ctrl) writel_relaxed(spi_ioc & ~SPI_IO_C_MX_CS_MODE, dd->base + SPI_IO_CONTROL); return status; } static int msm_spi_slv_abort(struct spi_master *spi) { struct msm_spi *dd = spi_master_get_devdata(spi); complete_all(&dd->tx_transfer_complete); complete_all(&dd->rx_transfer_complete); return 0; } static inline void msm_spi_set_cs(struct spi_device *spi, bool set_flag) { Loading Loading @@ -1753,6 +1775,32 @@ static int msm_spi_unprepare_transfer_hardware(struct spi_master *master) return 0; } static void msm_spi_slv_setup(struct msm_spi *dd) { u32 spi_config = readl_relaxed(dd->base + SPI_CONFIG); u32 qup_config = readl_relaxed(dd->base + QUP_CONFIG); u32 irq_en = GENMASK(6, 0); qup_config &= ~QUP_CFG_MODE; qup_config |= QUP_CONFIG_SPI_SLAVE; qup_config |= (SPI_EN_EXT_OUT_FLAG | APP_CLK_ON_EN | CORE_CLK_ON_EN | FIFO_CLK_ON_EN | CORE_EX_CLK_ON_EN); spi_config |= SPI_CFG_SLAVE_OP; writel_relaxed(qup_config, dd->base + QUP_CONFIG); writel_relaxed(spi_config, dd->base + SPI_CONFIG); writel_relaxed(irq_en, (dd->base + SPI_SLAVE_IRQ_EN)); if (dd->read_buf && !dd->write_buf) { u32 slv_cfg = readl_relaxed(dd->base + SPI_SLAVE_CONFIG); slv_cfg |= (RX_UNBALANCED_MASK | SPI_S_CGC_EN); writel_relaxed(slv_cfg, (dd->base + SPI_SLAVE_CONFIG)); } /* * Ensure Slave setup completes before returning. */ mb(); } static int msm_spi_setup(struct spi_device *spi) { struct msm_spi *dd; Loading Loading @@ -2248,6 +2296,8 @@ struct msm_spi_platform_data *msm_spi_dt_to_pdata( &pdata->rt_priority, DT_OPT, DT_BOOL, 0}, {"qcom,shared", &pdata->is_shared, DT_OPT, DT_BOOL, 0}, {"qcom,slv-ctrl", &pdata->is_slv_ctrl, DT_OPT, DT_BOOL, 0}, {NULL, NULL, 0, 0, 0}, }; Loading Loading @@ -2451,6 +2501,12 @@ err_clk_get: return rc; } static const struct of_device_id msm_spi_dt_match[] = { { .compatible = "qcom,spi-qup-v2", }, { .compatible = "qcom,qup-v26", }, {} }; static int msm_spi_probe(struct platform_device *pdev) { struct spi_master *master; Loading Loading @@ -2481,6 +2537,9 @@ static int msm_spi_probe(struct platform_device *pdev) dd = spi_master_get_devdata(master); if (pdev->dev.of_node) { const struct of_device_id *dev_id; enum msm_spi_qup_version ver; dd->qup_ver = SPI_QUP_VERSION_BFAM; master->dev.of_node = pdev->dev.of_node; pdata = msm_spi_dt_to_pdata(pdev, dd); Loading @@ -2495,6 +2554,17 @@ static int msm_spi_probe(struct platform_device *pdev) "using default bus_num %d\n", pdev->id); else master->bus_num = pdev->id = rc; dev_id = of_match_device(msm_spi_dt_match, &pdev->dev); if (dev_id) ver = SPI_QUP_VERSION_SPI_SLV; else ver = SPI_QUP_VERSION_BFAM; if (ver >= SPI_QUP_VERSION_SPI_SLV) dd->slv_support = true; else dd->slv_support = false; } else { pdata = pdev->dev.platform_data; dd->qup_ver = SPI_QUP_VERSION_NONE; Loading Loading @@ -2553,6 +2623,21 @@ static int msm_spi_probe(struct platform_device *pdev) } spi_dma_mask(&pdev->dev); if (pdata && pdata->is_slv_ctrl) { if (!dd->slv_support) { rc = -ENXIO; dev_err(&pdev->dev, "QUP ver %d, no slv support\n", dd->qup_ver); goto err_probe_res; } master->slave = true; master->set_cs = NULL; master->setup = NULL; master->slave_abort = msm_spi_slv_abort; } skip_dma_resources: spin_lock_init(&dd->queue_lock); Loading Loading @@ -2753,13 +2838,6 @@ static int msm_spi_remove(struct platform_device *pdev) return 0; } static struct of_device_id msm_spi_dt_match[] = { { .compatible = "qcom,spi-qup-v2", }, {} }; static const struct dev_pm_ops msm_spi_dev_pm_ops = { SET_SYSTEM_SLEEP_PM_OPS(msm_spi_suspend, msm_spi_resume) SET_RUNTIME_PM_OPS(msm_spi_pm_suspend_runtime, Loading
drivers/spi/spi_qsd.h +29 −0 Original line number Diff line number Diff line Loading @@ -38,6 +38,7 @@ #define QUP_MX_WRITE_CNT_CURRENT 0x0154 #define QUP_CONFIG_SPI_MODE 0x0100 #define QUP_CONFIG_SPI_SLAVE 0x0400 #endif #define GSBI_CTRL_REG 0x0 Loading Loading @@ -72,17 +73,26 @@ #define SPI_OUTPUT_FIFO QSD_REG(0x0100) QUP_REG(0x0110) #define SPI_INPUT_FIFO QSD_REG(0x0200) QUP_REG(0x0218) #define SPI_STATE QSD_REG(SPI_OPERATIONAL) QUP_REG(0x0004) #define SPI_SLAVE_IRQ_STATUS (0x0330) #define SPI_SLAVE_IRQ_EN (0x0334) #define SPI_SLAVE_CONFIG (0x0338) /* QUP_CONFIG fields */ #define SPI_CFG_N 0x0000001F #define SPI_NO_INPUT 0x00000080 #define SPI_NO_OUTPUT 0x00000040 #define SPI_EN_EXT_OUT_FLAG 0x00010000 #define QUP_CFG_MODE 0x00000F00 #define APP_CLK_ON_EN BIT(12) #define CORE_CLK_ON_EN BIT(13) #define FIFO_CLK_ON_EN BIT(14) #define CORE_EX_CLK_ON_EN BIT(15) /* SPI_CONFIG fields */ #define SPI_CFG_LOOPBACK 0x00000100 #define SPI_CFG_INPUT_FIRST 0x00000200 #define SPI_CFG_HS_MODE 0x00000400 #define SPI_CFG_SLAVE_OP 0x00000020 /* SPI_IO_CONTROL fields */ #define SPI_IO_C_FORCE_CS 0x00000800 Loading Loading @@ -128,6 +138,23 @@ #define SPI_OP_STATE_CLEAR_BITS 0x2 /* SPI SLAVE IRQ_STATUS/EN fields */ #define CS_N_ASSERT BIT(0) #define CS_N_DEASSERT BIT(1) #define CS_N_ETXT BIT(2) #define TX_UNDERFLOW BIT(3) #define RX_OVERFLOW_WAIT_EOT BIT(4) #define RX_OVERFLOW_NO_EOT BIT(5) #define CS_N_ERXT BIT(6) /* SPI_SLAVE_CONFIG Fields */ #define RX_N_SHIFT BIT(0) #define PAUSE_ON_ERR_DIS BIT(1) #define SPI_S_CGC_EN BIT(2) #define RX_UNBALANCED_MASK BIT(3) #define SLAVE_DIS_RESET_ST BIT(4) #define SLAVE_AUTO_PAUSE_EOT BIT(7) #define SPI_PINCTRL_STATE_DEFAULT "spi_default" #define SPI_PINCTRL_STATE_SLEEP "spi_sleep" Loading Loading @@ -177,6 +204,7 @@ enum msm_spi_state { enum msm_spi_qup_version { SPI_QUP_VERSION_NONE = 0x0, SPI_QUP_VERSION_BFAM = 0x2, SPI_QUP_VERSION_SPI_SLV = 0x26, }; enum msm_spi_pipe_direction { Loading Loading @@ -376,6 +404,7 @@ struct msm_spi { struct pinctrl_state *pins_sleep; bool is_init_complete; bool pack_words; bool slv_support; }; /* Forward declaration */ Loading
include/linux/spi/qcom-spi.h +2 −0 Original line number Diff line number Diff line Loading @@ -48,9 +48,11 @@ struct msm_spi_platform_data { u32 infinite_mode; bool ver_reg_exists; bool use_bam; bool slv_test; u32 bam_consumer_pipe_index; u32 bam_producer_pipe_index; bool rt_priority; bool use_pinctrl; bool is_shared; bool is_slv_ctrl; };