8dd209b91915f8ee96ae2fbea7ca9be2e1783676
[openwrt/staging/xback.git] /
1 From 8d6b6d7e135e9bbfc923d34a45cb0e72695e63ed Mon Sep 17 00:00:00 2001
2 From: Abhishek Sahu <absahu@codeaurora.org>
3 Date: Mon, 25 Sep 2017 13:21:26 +0530
4 Subject: [PATCH 3/7] mtd: nand: qcom: support for command descriptor formation
5
6 1. Add the function for command descriptor preparation which will
7 be used only by BAM DMA and it will form the DMA descriptors
8 containing command elements
9 2. DMA_PREP_CMD flag should be used for forming command DMA
10 descriptors
11
12 Reviewed-by: Archit Taneja <architt@codeaurora.org>
13 Signed-off-by: Abhishek Sahu <absahu@codeaurora.org>
14 Signed-off-by: Boris Brezillon <boris.brezillon@free-electrons.com>
15 ---
16 drivers/mtd/nand/qcom_nandc.c | 108 +++++++++++++++++++++++++++++++++++-------
17 1 file changed, 92 insertions(+), 16 deletions(-)
18
19 --- a/drivers/mtd/nand/qcom_nandc.c
20 +++ b/drivers/mtd/nand/qcom_nandc.c
21 @@ -200,6 +200,14 @@ nandc_set_reg(nandc, NAND_READ_LOCATION_
22 */
23 #define dev_cmd_reg_addr(nandc, reg) ((nandc)->props->dev_cmd_reg_start + (reg))
24
25 +/* Returns the NAND register physical address */
26 +#define nandc_reg_phys(chip, offset) ((chip)->base_phys + (offset))
27 +
28 +/* Returns the dma address for reg read buffer */
29 +#define reg_buf_dma_addr(chip, vaddr) \
30 + ((chip)->reg_read_dma + \
31 + ((uint8_t *)(vaddr) - (uint8_t *)(chip)->reg_read_buf))
32 +
33 #define QPIC_PER_CW_CMD_ELEMENTS 32
34 #define QPIC_PER_CW_CMD_SGL 32
35 #define QPIC_PER_CW_DATA_SGL 8
36 @@ -317,7 +325,8 @@ struct nandc_regs {
37 * controller
38 * @dev: parent device
39 * @base: MMIO base
40 - * @base_dma: physical base address of controller registers
41 + * @base_phys: physical base address of controller registers
42 + * @base_dma: dma base address of controller registers
43 * @core_clk: controller clock
44 * @aon_clk: another controller clock
45 *
46 @@ -350,6 +359,7 @@ struct qcom_nand_controller {
47 struct device *dev;
48
49 void __iomem *base;
50 + phys_addr_t base_phys;
51 dma_addr_t base_dma;
52
53 struct clk *core_clk;
54 @@ -751,6 +761,66 @@ static int prepare_bam_async_desc(struct
55 }
56
57 /*
58 + * Prepares the command descriptor for BAM DMA which will be used for NAND
59 + * register reads and writes. The command descriptor requires the command
60 + * to be formed in command element type so this function uses the command
61 + * element from bam transaction ce array and fills the same with required
62 + * data. A single SGL can contain multiple command elements so
63 + * NAND_BAM_NEXT_SGL will be used for starting the separate SGL
64 + * after the current command element.
65 + */
66 +static int prep_bam_dma_desc_cmd(struct qcom_nand_controller *nandc, bool read,
67 + int reg_off, const void *vaddr,
68 + int size, unsigned int flags)
69 +{
70 + int bam_ce_size;
71 + int i, ret;
72 + struct bam_cmd_element *bam_ce_buffer;
73 + struct bam_transaction *bam_txn = nandc->bam_txn;
74 +
75 + bam_ce_buffer = &bam_txn->bam_ce[bam_txn->bam_ce_pos];
76 +
77 + /* fill the command desc */
78 + for (i = 0; i < size; i++) {
79 + if (read)
80 + bam_prep_ce(&bam_ce_buffer[i],
81 + nandc_reg_phys(nandc, reg_off + 4 * i),
82 + BAM_READ_COMMAND,
83 + reg_buf_dma_addr(nandc,
84 + (__le32 *)vaddr + i));
85 + else
86 + bam_prep_ce_le32(&bam_ce_buffer[i],
87 + nandc_reg_phys(nandc, reg_off + 4 * i),
88 + BAM_WRITE_COMMAND,
89 + *((__le32 *)vaddr + i));
90 + }
91 +
92 + bam_txn->bam_ce_pos += size;
93 +
94 + /* use the separate sgl after this command */
95 + if (flags & NAND_BAM_NEXT_SGL) {
96 + bam_ce_buffer = &bam_txn->bam_ce[bam_txn->bam_ce_start];
97 + bam_ce_size = (bam_txn->bam_ce_pos -
98 + bam_txn->bam_ce_start) *
99 + sizeof(struct bam_cmd_element);
100 + sg_set_buf(&bam_txn->cmd_sgl[bam_txn->cmd_sgl_pos],
101 + bam_ce_buffer, bam_ce_size);
102 + bam_txn->cmd_sgl_pos++;
103 + bam_txn->bam_ce_start = bam_txn->bam_ce_pos;
104 +
105 + if (flags & NAND_BAM_NWD) {
106 + ret = prepare_bam_async_desc(nandc, nandc->cmd_chan,
107 + DMA_PREP_FENCE |
108 + DMA_PREP_CMD);
109 + if (ret)
110 + return ret;
111 + }
112 + }
113 +
114 + return 0;
115 +}
116 +
117 +/*
118 * Prepares the data descriptor for BAM DMA which will be used for NAND
119 * data reads and writes.
120 */
121 @@ -868,19 +938,22 @@ static int read_reg_dma(struct qcom_nand
122 {
123 bool flow_control = false;
124 void *vaddr;
125 - int size;
126
127 - if (first == NAND_READ_ID || first == NAND_FLASH_STATUS)
128 - flow_control = true;
129 + vaddr = nandc->reg_read_buf + nandc->reg_read_pos;
130 + nandc->reg_read_pos += num_regs;
131
132 if (first == NAND_DEV_CMD_VLD || first == NAND_DEV_CMD1)
133 first = dev_cmd_reg_addr(nandc, first);
134
135 - size = num_regs * sizeof(u32);
136 - vaddr = nandc->reg_read_buf + nandc->reg_read_pos;
137 - nandc->reg_read_pos += num_regs;
138 + if (nandc->props->is_bam)
139 + return prep_bam_dma_desc_cmd(nandc, true, first, vaddr,
140 + num_regs, flags);
141 +
142 + if (first == NAND_READ_ID || first == NAND_FLASH_STATUS)
143 + flow_control = true;
144
145 - return prep_adm_dma_desc(nandc, true, first, vaddr, size, flow_control);
146 + return prep_adm_dma_desc(nandc, true, first, vaddr,
147 + num_regs * sizeof(u32), flow_control);
148 }
149
150 /*
151 @@ -897,13 +970,9 @@ static int write_reg_dma(struct qcom_nan
152 bool flow_control = false;
153 struct nandc_regs *regs = nandc->regs;
154 void *vaddr;
155 - int size;
156
157 vaddr = offset_to_nandc_reg(regs, first);
158
159 - if (first == NAND_FLASH_CMD)
160 - flow_control = true;
161 -
162 if (first == NAND_ERASED_CW_DETECT_CFG) {
163 if (flags & NAND_ERASED_CW_SET)
164 vaddr = &regs->erased_cw_detect_cfg_set;
165 @@ -920,10 +989,15 @@ static int write_reg_dma(struct qcom_nan
166 if (first == NAND_DEV_CMD_VLD_RESTORE || first == NAND_DEV_CMD_VLD)
167 first = dev_cmd_reg_addr(nandc, NAND_DEV_CMD_VLD);
168
169 - size = num_regs * sizeof(u32);
170 + if (nandc->props->is_bam)
171 + return prep_bam_dma_desc_cmd(nandc, false, first, vaddr,
172 + num_regs, flags);
173 +
174 + if (first == NAND_FLASH_CMD)
175 + flow_control = true;
176
177 - return prep_adm_dma_desc(nandc, false, first, vaddr, size,
178 - flow_control);
179 + return prep_adm_dma_desc(nandc, false, first, vaddr,
180 + num_regs * sizeof(u32), flow_control);
181 }
182
183 /*
184 @@ -1187,7 +1261,8 @@ static int submit_descs(struct qcom_nand
185 }
186
187 if (bam_txn->cmd_sgl_pos > bam_txn->cmd_sgl_start) {
188 - r = prepare_bam_async_desc(nandc, nandc->cmd_chan, 0);
189 + r = prepare_bam_async_desc(nandc, nandc->cmd_chan,
190 + DMA_PREP_CMD);
191 if (r)
192 return r;
193 }
194 @@ -2722,6 +2797,7 @@ static int qcom_nandc_probe(struct platf
195 if (IS_ERR(nandc->base))
196 return PTR_ERR(nandc->base);
197
198 + nandc->base_phys = res->start;
199 nandc->base_dma = phys_to_dma(dev, (phys_addr_t)res->start);
200
201 nandc->core_clk = devm_clk_get(dev, "core");