ath79/mikrotik: use routerbootpart partitions
[oweals/openwrt.git] / target / linux / layerscape / patches-5.4 / 817-spi-0001-spi-spi-fsl-qspi-dynamically-alloc-AHB-memory-for-QS.patch
1 From e1cf48a13626d0c42c5191dc4852f4dc271de010 Mon Sep 17 00:00:00 2001
2 From: Han Xu <han.xu@nxp.com>
3 Date: Tue, 9 Jul 2019 16:21:14 -0500
4 Subject: [PATCH] spi: spi-fsl-qspi: dynamically alloc AHB memory for QSPI
5
6 dynamically alloc AHB memory for QSPI controller.
7
8 Signed-off-by: Han Xu <han.xu@nxp.com>
9 [rebase]
10 Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
11 ---
12  drivers/spi/spi-fsl-qspi.c | 60 +++++++++++++++++++++++++++++++++-------------
13  1 file changed, 43 insertions(+), 17 deletions(-)
14
15 --- a/drivers/spi/spi-fsl-qspi.c
16 +++ b/drivers/spi/spi-fsl-qspi.c
17 @@ -192,6 +192,8 @@
18   */
19  #define QUADSPI_QUIRK_USE_TDH_SETTING  BIT(5)
20  
21 +#define QUADSPI_MIN_IOMAP              SZ_4M
22 +
23  struct fsl_qspi_devtype_data {
24         unsigned int rxfifo;
25         unsigned int txfifo;
26 @@ -254,6 +256,9 @@ struct fsl_qspi {
27         void __iomem *iobase;
28         void __iomem *ahb_addr;
29         u32 memmap_phy;
30 +       u32 memmap_phy_size;
31 +       u32 memmap_start;
32 +       u32 memmap_len;
33         struct clk *clk, *clk_en;
34         struct device *dev;
35         struct completion c;
36 @@ -537,11 +542,34 @@ static void fsl_qspi_select_mem(struct f
37         fsl_qspi_invalidate(q);
38  }
39  
40 -static void fsl_qspi_read_ahb(struct fsl_qspi *q, const struct spi_mem_op *op)
41 +static int fsl_qspi_read_ahb(struct fsl_qspi *q, const struct spi_mem_op *op)
42  {
43 +       u32 start = op->addr.val + q->selected * q->memmap_phy_size / 4;
44 +       u32 len = op->data.nbytes;
45 +
46 +       /* if necessary, ioremap before AHB read */
47 +       if ((!q->ahb_addr) || start < q->memmap_start ||
48 +           start + len > q->memmap_start + q->memmap_len) {
49 +               if (q->ahb_addr) {
50 +                       iounmap(q->ahb_addr);
51 +               }
52 +
53 +               q->memmap_start = start;
54 +               q->memmap_len = len > QUADSPI_MIN_IOMAP ?
55 +                               len : QUADSPI_MIN_IOMAP;
56 +
57 +               q->ahb_addr = ioremap_wc(q->memmap_phy + q->memmap_start,
58 +                                        q->memmap_len);
59 +               if (!q->ahb_addr) {
60 +                       dev_err(q->dev, "failed to alloc memory\n");
61 +                       return -ENOMEM;
62 +               }
63 +       }
64 +
65         memcpy_fromio(op->data.buf.in,
66 -                     q->ahb_addr + q->selected * q->devtype_data->ahb_buf_size,
67 -                     op->data.nbytes);
68 +                     q->ahb_addr + start - q->memmap_start, len);
69 +
70 +       return 0;
71  }
72  
73  static void fsl_qspi_fill_txfifo(struct fsl_qspi *q,
74 @@ -646,7 +674,7 @@ static int fsl_qspi_exec_op(struct spi_m
75                 addr_offset = q->memmap_phy;
76  
77         qspi_writel(q,
78 -                   q->selected * q->devtype_data->ahb_buf_size + addr_offset,
79 +                   q->selected * q->memmap_phy_size / 4 + addr_offset,
80                     base + QUADSPI_SFAR);
81  
82         qspi_writel(q, qspi_readl(q, base + QUADSPI_MCR) |
83 @@ -665,7 +693,7 @@ static int fsl_qspi_exec_op(struct spi_m
84          */
85         if (op->data.nbytes > (q->devtype_data->rxfifo - 4) &&
86             op->data.dir == SPI_MEM_DATA_IN) {
87 -               fsl_qspi_read_ahb(q, op);
88 +               err = fsl_qspi_read_ahb(q, op);
89         } else {
90                 qspi_writel(q, QUADSPI_RBCT_WMRK_MASK |
91                             QUADSPI_RBCT_RXBRD_USEIPS, base + QUADSPI_RBCT);
92 @@ -763,16 +791,16 @@ static int fsl_qspi_default_setup(struct
93          * In HW there can be a maximum of four chips on two buses with
94          * two chip selects on each bus. We use four chip selects in SW
95          * to differentiate between the four chips.
96 -        * We use ahb_buf_size for each chip and set SFA1AD, SFA2AD, SFB1AD,
97 -        * SFB2AD accordingly.
98 +        * We divide the total memory region size equally for each chip
99 +        * and set SFA1AD, SFA2AD, SFB1AD, SFB2AD accordingly.
100          */
101 -       qspi_writel(q, q->devtype_data->ahb_buf_size + addr_offset,
102 +       qspi_writel(q, q->memmap_phy_size / 4 + addr_offset,
103                     base + QUADSPI_SFA1AD);
104 -       qspi_writel(q, q->devtype_data->ahb_buf_size * 2 + addr_offset,
105 +       qspi_writel(q, q->memmap_phy_size / 4 * 2 + addr_offset,
106                     base + QUADSPI_SFA2AD);
107 -       qspi_writel(q, q->devtype_data->ahb_buf_size * 3 + addr_offset,
108 +       qspi_writel(q, q->memmap_phy_size / 4 * 3 + addr_offset,
109                     base + QUADSPI_SFB1AD);
110 -       qspi_writel(q, q->devtype_data->ahb_buf_size * 4 + addr_offset,
111 +       qspi_writel(q, q->memmap_phy_size / 4 * 4 + addr_offset,
112                     base + QUADSPI_SFB2AD);
113  
114         q->selected = -1;
115 @@ -859,13 +887,8 @@ static int fsl_qspi_probe(struct platfor
116  
117         res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
118                                         "QuadSPI-memory");
119 -       q->ahb_addr = devm_ioremap_resource(dev, res);
120 -       if (IS_ERR(q->ahb_addr)) {
121 -               ret = PTR_ERR(q->ahb_addr);
122 -               goto err_put_ctrl;
123 -       }
124 -
125         q->memmap_phy = res->start;
126 +       q->memmap_phy_size = resource_size(res);
127  
128         /* find the clocks */
129         q->clk_en = devm_clk_get(dev, "qspi_en");
130 @@ -939,6 +962,9 @@ static int fsl_qspi_remove(struct platfo
131  
132         mutex_destroy(&q->lock);
133  
134 +       if (q->ahb_addr)
135 +               iounmap(q->ahb_addr);
136 +
137         return 0;
138  }
139