spi: bcm-qspi: Handle lack of MSPI_REV offset
authorFlorian Fainelli <f.fainelli@gmail.com>
Mon, 20 Apr 2020 19:08:47 +0000 (15:08 -0400)
committerMark Brown <broonie@kernel.org>
Tue, 21 Apr 2020 18:48:06 +0000 (19:48 +0100)
Older MIPS chips have a QSPI/MSPI controller that does not have the
MSPI_REV offset, reading from that offset will cause a bus error. Match
their compatible string and do not perform a read from that register in
that case.

Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
Signed-off-by: Kamal Dasu <kdasu.kdev@gmail.com>
Link: https://lore.kernel.org/r/20200420190853.45614-4-kdasu.kdev@gmail.com
Signed-off-by: Mark Brown <broonie@kernel.org>
drivers/spi/spi-bcm-qspi.c

index 23d295f..1f157c3 100644 (file)
@@ -91,6 +91,7 @@
 #define MSPI_MSPI_STATUS                       0x020
 #define MSPI_CPTQP                             0x024
 #define MSPI_SPCR3                             0x028
+#define MSPI_REV                               0x02c
 #define MSPI_TXRAM                             0x040
 #define MSPI_RXRAM                             0x0c0
 #define MSPI_CDRAM                             0x140
@@ -217,6 +218,8 @@ struct bcm_qspi {
        struct bcm_qspi_dev_id *dev_ids;
        struct completion mspi_done;
        struct completion bspi_done;
+       u8 mspi_maj_rev;
+       u8 mspi_min_rev;
 };
 
 static inline bool has_bspi(struct bcm_qspi *qspi)
@@ -1190,8 +1193,35 @@ static const struct spi_controller_mem_ops bcm_qspi_mem_ops = {
        .exec_op = bcm_qspi_exec_mem_op,
 };
 
+struct bcm_qspi_data {
+       bool    has_mspi_rev;
+};
+
+static const struct bcm_qspi_data bcm_qspi_no_rev_data = {
+       .has_mspi_rev   = false,
+};
+
+static const struct bcm_qspi_data bcm_qspi_rev_data = {
+       .has_mspi_rev   = true,
+};
+
 static const struct of_device_id bcm_qspi_of_match[] = {
-       { .compatible = "brcm,spi-bcm-qspi" },
+       {
+               .compatible = "brcm,spi-bcm7425-qspi",
+               .data = &bcm_qspi_no_rev_data,
+       },
+       {
+               .compatible = "brcm,spi-bcm7429-qspi",
+               .data = &bcm_qspi_no_rev_data,
+       },
+       {
+               .compatible = "brcm,spi-bcm7435-qspi",
+               .data = &bcm_qspi_no_rev_data,
+       },
+       {
+               .compatible = "brcm,spi-bcm-qspi",
+               .data = &bcm_qspi_rev_data,
+       },
        {},
 };
 MODULE_DEVICE_TABLE(of, bcm_qspi_of_match);
@@ -1199,12 +1229,15 @@ MODULE_DEVICE_TABLE(of, bcm_qspi_of_match);
 int bcm_qspi_probe(struct platform_device *pdev,
                   struct bcm_qspi_soc_intc *soc_intc)
 {
+       const struct of_device_id *of_id = NULL;
+       const struct bcm_qspi_data *data;
        struct device *dev = &pdev->dev;
        struct bcm_qspi *qspi;
        struct spi_master *master;
        struct resource *res;
        int irq, ret = 0, num_ints = 0;
        u32 val;
+       u32 rev = 0;
        const char *name = NULL;
        int num_irqs = ARRAY_SIZE(qspi_irq_tab);
 
@@ -1212,9 +1245,12 @@ int bcm_qspi_probe(struct platform_device *pdev,
        if (!dev->of_node)
                return -ENODEV;
 
-       if (!of_match_node(bcm_qspi_of_match, dev->of_node))
+       of_id = of_match_node(bcm_qspi_of_match, dev->of_node);
+       if (!of_id)
                return -ENODEV;
 
+       data = of_id->data;
+
        master = spi_alloc_master(dev, sizeof(struct bcm_qspi));
        if (!master) {
                dev_err(dev, "error allocating spi_master\n");
@@ -1351,6 +1387,16 @@ int bcm_qspi_probe(struct platform_device *pdev,
        qspi->base_clk = clk_get_rate(qspi->clk);
        qspi->max_speed_hz = qspi->base_clk / (QSPI_SPBR_MIN * 2);
 
+       if (data->has_mspi_rev) {
+               rev = bcm_qspi_read(qspi, MSPI, MSPI_REV);
+               /* some older revs do not have a MSPI_REV register */
+               if ((rev & 0xff) == 0xff)
+                       rev = 0;
+       }
+
+       qspi->mspi_maj_rev = (rev >> 4) & 0xf;
+       qspi->mspi_min_rev = rev & 0xf;
+
        bcm_qspi_hw_init(qspi);
        init_completion(&qspi->mspi_done);
        init_completion(&qspi->bspi_done);