Merge tag 'riscv-for-linus-6.7-rc1' of git://git.kernel.org/pub/scm/linux/kernel...
[linux-2.6-microblaze.git] / drivers / mfd / intel-m10-bmc-pmci.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * MAX10 BMC Platform Management Component Interface (PMCI) based
4  * interface.
5  *
6  * Copyright (C) 2020-2023 Intel Corporation.
7  */
8
9 #include <linux/bitfield.h>
10 #include <linux/device.h>
11 #include <linux/dfl.h>
12 #include <linux/mfd/core.h>
13 #include <linux/mfd/intel-m10-bmc.h>
14 #include <linux/minmax.h>
15 #include <linux/module.h>
16 #include <linux/regmap.h>
17
18 struct m10bmc_pmci_device {
19         void __iomem *base;
20         struct intel_m10bmc m10bmc;
21         struct mutex flash_mutex;       /* protects flash_busy and serializes flash read/read */
22         bool flash_busy;
23 };
24
25 /*
26  * Intel FGPA indirect register access via hardware controller/bridge.
27  */
28 #define INDIRECT_CMD_OFF        0
29 #define INDIRECT_CMD_CLR        0
30 #define INDIRECT_CMD_RD         BIT(0)
31 #define INDIRECT_CMD_WR         BIT(1)
32 #define INDIRECT_CMD_ACK        BIT(2)
33
34 #define INDIRECT_ADDR_OFF       0x4
35 #define INDIRECT_RD_OFF         0x8
36 #define INDIRECT_WR_OFF         0xc
37
38 #define INDIRECT_INT_US         1
39 #define INDIRECT_TIMEOUT_US     10000
40
41 struct indirect_ctx {
42         void __iomem *base;
43         struct device *dev;
44 };
45
46 static int indirect_clear_cmd(struct indirect_ctx *ctx)
47 {
48         unsigned int cmd;
49         int ret;
50
51         writel(INDIRECT_CMD_CLR, ctx->base + INDIRECT_CMD_OFF);
52
53         ret = readl_poll_timeout(ctx->base + INDIRECT_CMD_OFF, cmd,
54                                  cmd == INDIRECT_CMD_CLR,
55                                  INDIRECT_INT_US, INDIRECT_TIMEOUT_US);
56         if (ret)
57                 dev_err(ctx->dev, "timed out waiting clear cmd (residual cmd=0x%x)\n", cmd);
58
59         return ret;
60 }
61
62 static int indirect_reg_read(void *context, unsigned int reg, unsigned int *val)
63 {
64         struct indirect_ctx *ctx = context;
65         unsigned int cmd, ack, tmpval;
66         int ret, ret2;
67
68         cmd = readl(ctx->base + INDIRECT_CMD_OFF);
69         if (cmd != INDIRECT_CMD_CLR)
70                 dev_warn(ctx->dev, "residual cmd 0x%x on read entry\n", cmd);
71
72         writel(reg, ctx->base + INDIRECT_ADDR_OFF);
73         writel(INDIRECT_CMD_RD, ctx->base + INDIRECT_CMD_OFF);
74
75         ret = readl_poll_timeout(ctx->base + INDIRECT_CMD_OFF, ack,
76                                  (ack & INDIRECT_CMD_ACK) == INDIRECT_CMD_ACK,
77                                  INDIRECT_INT_US, INDIRECT_TIMEOUT_US);
78         if (ret)
79                 dev_err(ctx->dev, "read timed out on reg 0x%x ack 0x%x\n", reg, ack);
80         else
81                 tmpval = readl(ctx->base + INDIRECT_RD_OFF);
82
83         ret2 = indirect_clear_cmd(ctx);
84
85         if (ret)
86                 return ret;
87         if (ret2)
88                 return ret2;
89
90         *val = tmpval;
91         return 0;
92 }
93
94 static int indirect_reg_write(void *context, unsigned int reg, unsigned int val)
95 {
96         struct indirect_ctx *ctx = context;
97         unsigned int cmd, ack;
98         int ret, ret2;
99
100         cmd = readl(ctx->base + INDIRECT_CMD_OFF);
101         if (cmd != INDIRECT_CMD_CLR)
102                 dev_warn(ctx->dev, "residual cmd 0x%x on write entry\n", cmd);
103
104         writel(val, ctx->base + INDIRECT_WR_OFF);
105         writel(reg, ctx->base + INDIRECT_ADDR_OFF);
106         writel(INDIRECT_CMD_WR, ctx->base + INDIRECT_CMD_OFF);
107
108         ret = readl_poll_timeout(ctx->base + INDIRECT_CMD_OFF, ack,
109                                  (ack & INDIRECT_CMD_ACK) == INDIRECT_CMD_ACK,
110                                  INDIRECT_INT_US, INDIRECT_TIMEOUT_US);
111         if (ret)
112                 dev_err(ctx->dev, "write timed out on reg 0x%x ack 0x%x\n", reg, ack);
113
114         ret2 = indirect_clear_cmd(ctx);
115
116         if (ret)
117                 return ret;
118         return ret2;
119 }
120
121 static void pmci_write_fifo(void __iomem *base, const u32 *buf, size_t count)
122 {
123         while (count--)
124                 writel(*buf++, base);
125 }
126
127 static void pmci_read_fifo(void __iomem *base, u32 *buf, size_t count)
128 {
129         while (count--)
130                 *buf++ = readl(base);
131 }
132
133 static u32 pmci_get_write_space(struct m10bmc_pmci_device *pmci)
134 {
135         u32 val;
136         int ret;
137
138         ret = read_poll_timeout(readl, val,
139                                 FIELD_GET(M10BMC_N6000_FLASH_FIFO_SPACE, val) ==
140                                 M10BMC_N6000_FIFO_MAX_WORDS,
141                                 M10BMC_FLASH_INT_US, M10BMC_FLASH_TIMEOUT_US,
142                                 false, pmci->base + M10BMC_N6000_FLASH_CTRL);
143         if (ret == -ETIMEDOUT)
144                 return 0;
145
146         return FIELD_GET(M10BMC_N6000_FLASH_FIFO_SPACE, val) * M10BMC_N6000_FIFO_WORD_SIZE;
147 }
148
149 static int pmci_flash_bulk_write(struct intel_m10bmc *m10bmc, const u8 *buf, u32 size)
150 {
151         struct m10bmc_pmci_device *pmci = container_of(m10bmc, struct m10bmc_pmci_device, m10bmc);
152         u32 blk_size, offset = 0, write_count;
153
154         while (size) {
155                 blk_size = min(pmci_get_write_space(pmci), size);
156                 if (blk_size == 0) {
157                         dev_err(m10bmc->dev, "get FIFO available size fail\n");
158                         return -EIO;
159                 }
160
161                 if (size < M10BMC_N6000_FIFO_WORD_SIZE)
162                         break;
163
164                 write_count = blk_size / M10BMC_N6000_FIFO_WORD_SIZE;
165                 pmci_write_fifo(pmci->base + M10BMC_N6000_FLASH_FIFO,
166                                 (u32 *)(buf + offset), write_count);
167
168                 size -= blk_size;
169                 offset += blk_size;
170         }
171
172         /* Handle remainder (less than M10BMC_N6000_FIFO_WORD_SIZE bytes) */
173         if (size) {
174                 u32 tmp = 0;
175
176                 memcpy(&tmp, buf + offset, size);
177                 pmci_write_fifo(pmci->base + M10BMC_N6000_FLASH_FIFO, &tmp, 1);
178         }
179
180         return 0;
181 }
182
183 static int pmci_flash_bulk_read(struct intel_m10bmc *m10bmc, u8 *buf, u32 addr, u32 size)
184 {
185         struct m10bmc_pmci_device *pmci = container_of(m10bmc, struct m10bmc_pmci_device, m10bmc);
186         u32 blk_size, offset = 0, val, full_read_count, read_count;
187         int ret;
188
189         while (size) {
190                 blk_size = min_t(u32, size, M10BMC_N6000_READ_BLOCK_SIZE);
191                 full_read_count = blk_size / M10BMC_N6000_FIFO_WORD_SIZE;
192
193                 read_count = full_read_count;
194                 if (full_read_count * M10BMC_N6000_FIFO_WORD_SIZE < blk_size)
195                         read_count++;
196
197                 writel(addr + offset, pmci->base + M10BMC_N6000_FLASH_ADDR);
198                 writel(FIELD_PREP(M10BMC_N6000_FLASH_READ_COUNT, read_count) |
199                        M10BMC_N6000_FLASH_RD_MODE,
200                        pmci->base + M10BMC_N6000_FLASH_CTRL);
201
202                 ret = readl_poll_timeout((pmci->base + M10BMC_N6000_FLASH_CTRL), val,
203                                          !(val & M10BMC_N6000_FLASH_BUSY),
204                                          M10BMC_FLASH_INT_US, M10BMC_FLASH_TIMEOUT_US);
205                 if (ret) {
206                         dev_err(m10bmc->dev, "read timed out on reading flash 0x%xn", val);
207                         return ret;
208                 }
209
210                 pmci_read_fifo(pmci->base + M10BMC_N6000_FLASH_FIFO,
211                                (u32 *)(buf + offset), full_read_count);
212
213                 size -= blk_size;
214                 offset += blk_size;
215
216                 if (full_read_count < read_count)
217                         break;
218
219                 writel(0, pmci->base + M10BMC_N6000_FLASH_CTRL);
220         }
221
222         /* Handle remainder (less than M10BMC_N6000_FIFO_WORD_SIZE bytes) */
223         if (size) {
224                 u32 tmp;
225
226                 pmci_read_fifo(pmci->base + M10BMC_N6000_FLASH_FIFO, &tmp, 1);
227                 memcpy(buf + offset, &tmp, size);
228
229                 writel(0, pmci->base + M10BMC_N6000_FLASH_CTRL);
230         }
231
232         return 0;
233 }
234
235 static int m10bmc_pmci_set_flash_host_mux(struct intel_m10bmc *m10bmc, bool request)
236 {
237         u32 ctrl;
238         int ret;
239
240         ret = regmap_update_bits(m10bmc->regmap, M10BMC_N6000_FLASH_MUX_CTRL,
241                                  M10BMC_N6000_FLASH_HOST_REQUEST,
242                                  FIELD_PREP(M10BMC_N6000_FLASH_HOST_REQUEST, request));
243         if (ret)
244                 return ret;
245
246         return regmap_read_poll_timeout(m10bmc->regmap,
247                                         M10BMC_N6000_FLASH_MUX_CTRL, ctrl,
248                                         request ?
249                                         (get_flash_mux(ctrl) == M10BMC_N6000_FLASH_MUX_HOST) :
250                                         (get_flash_mux(ctrl) != M10BMC_N6000_FLASH_MUX_HOST),
251                                         M10BMC_FLASH_INT_US, M10BMC_FLASH_TIMEOUT_US);
252 }
253
254 static int m10bmc_pmci_flash_read(struct intel_m10bmc *m10bmc, u8 *buf, u32 addr, u32 size)
255 {
256         struct m10bmc_pmci_device *pmci = container_of(m10bmc, struct m10bmc_pmci_device, m10bmc);
257         int ret, ret2;
258
259         mutex_lock(&pmci->flash_mutex);
260         if (pmci->flash_busy) {
261                 ret = -EBUSY;
262                 goto unlock;
263         }
264
265         ret = m10bmc_pmci_set_flash_host_mux(m10bmc, true);
266         if (ret)
267                 goto mux_fail;
268
269         ret = pmci_flash_bulk_read(m10bmc, buf, addr, size);
270
271 mux_fail:
272         ret2 = m10bmc_pmci_set_flash_host_mux(m10bmc, false);
273
274 unlock:
275         mutex_unlock(&pmci->flash_mutex);
276         if (ret)
277                 return ret;
278         return ret2;
279 }
280
281 static int m10bmc_pmci_flash_write(struct intel_m10bmc *m10bmc, const u8 *buf, u32 offset, u32 size)
282 {
283         struct m10bmc_pmci_device *pmci = container_of(m10bmc, struct m10bmc_pmci_device, m10bmc);
284         int ret;
285
286         mutex_lock(&pmci->flash_mutex);
287         WARN_ON_ONCE(!pmci->flash_busy);
288         /* On write, firmware manages flash MUX */
289         ret = pmci_flash_bulk_write(m10bmc, buf + offset, size);
290         mutex_unlock(&pmci->flash_mutex);
291
292         return ret;
293 }
294
295 static int m10bmc_pmci_flash_lock(struct intel_m10bmc *m10bmc)
296 {
297         struct m10bmc_pmci_device *pmci = container_of(m10bmc, struct m10bmc_pmci_device, m10bmc);
298         int ret = 0;
299
300         mutex_lock(&pmci->flash_mutex);
301         if (pmci->flash_busy) {
302                 ret = -EBUSY;
303                 goto unlock;
304         }
305
306         pmci->flash_busy = true;
307
308 unlock:
309         mutex_unlock(&pmci->flash_mutex);
310         return ret;
311 }
312
313 static void m10bmc_pmci_flash_unlock(struct intel_m10bmc *m10bmc)
314 {
315         struct m10bmc_pmci_device *pmci = container_of(m10bmc, struct m10bmc_pmci_device, m10bmc);
316
317         mutex_lock(&pmci->flash_mutex);
318         WARN_ON_ONCE(!pmci->flash_busy);
319         pmci->flash_busy = false;
320         mutex_unlock(&pmci->flash_mutex);
321 }
322
323 static const struct intel_m10bmc_flash_bulk_ops m10bmc_pmci_flash_bulk_ops = {
324         .read = m10bmc_pmci_flash_read,
325         .write = m10bmc_pmci_flash_write,
326         .lock_write = m10bmc_pmci_flash_lock,
327         .unlock_write = m10bmc_pmci_flash_unlock,
328 };
329
330 static const struct regmap_range m10bmc_pmci_regmap_range[] = {
331         regmap_reg_range(M10BMC_N6000_SYS_BASE, M10BMC_N6000_SYS_END),
332 };
333
334 static const struct regmap_access_table m10bmc_pmci_access_table = {
335         .yes_ranges     = m10bmc_pmci_regmap_range,
336         .n_yes_ranges   = ARRAY_SIZE(m10bmc_pmci_regmap_range),
337 };
338
339 static struct regmap_config m10bmc_pmci_regmap_config = {
340         .reg_bits = 32,
341         .reg_stride = 4,
342         .val_bits = 32,
343         .wr_table = &m10bmc_pmci_access_table,
344         .rd_table = &m10bmc_pmci_access_table,
345         .reg_read = &indirect_reg_read,
346         .reg_write = &indirect_reg_write,
347         .max_register = M10BMC_N6000_SYS_END,
348 };
349
350 static struct mfd_cell m10bmc_pmci_n6000_bmc_subdevs[] = {
351         { .name = "n6000bmc-hwmon" },
352         { .name = "n6000bmc-sec-update" },
353 };
354
355 static const struct m10bmc_csr_map m10bmc_n6000_csr_map = {
356         .base = M10BMC_N6000_SYS_BASE,
357         .build_version = M10BMC_N6000_BUILD_VER,
358         .fw_version = NIOS2_N6000_FW_VERSION,
359         .mac_low = M10BMC_N6000_MAC_LOW,
360         .mac_high = M10BMC_N6000_MAC_HIGH,
361         .doorbell = M10BMC_N6000_DOORBELL,
362         .auth_result = M10BMC_N6000_AUTH_RESULT,
363         .bmc_prog_addr = M10BMC_N6000_BMC_PROG_ADDR,
364         .bmc_reh_addr = M10BMC_N6000_BMC_REH_ADDR,
365         .bmc_magic = M10BMC_N6000_BMC_PROG_MAGIC,
366         .sr_prog_addr = M10BMC_N6000_SR_PROG_ADDR,
367         .sr_reh_addr = M10BMC_N6000_SR_REH_ADDR,
368         .sr_magic = M10BMC_N6000_SR_PROG_MAGIC,
369         .pr_prog_addr = M10BMC_N6000_PR_PROG_ADDR,
370         .pr_reh_addr = M10BMC_N6000_PR_REH_ADDR,
371         .pr_magic = M10BMC_N6000_PR_PROG_MAGIC,
372         .rsu_update_counter = M10BMC_N6000_STAGING_FLASH_COUNT,
373 };
374
375 static const struct intel_m10bmc_platform_info m10bmc_pmci_n6000 = {
376         .cells = m10bmc_pmci_n6000_bmc_subdevs,
377         .n_cells = ARRAY_SIZE(m10bmc_pmci_n6000_bmc_subdevs),
378         .csr_map = &m10bmc_n6000_csr_map,
379 };
380
381 static int m10bmc_pmci_probe(struct dfl_device *ddev)
382 {
383         struct device *dev = &ddev->dev;
384         struct m10bmc_pmci_device *pmci;
385         struct indirect_ctx *ctx;
386         int ret;
387
388         pmci = devm_kzalloc(dev, sizeof(*pmci), GFP_KERNEL);
389         if (!pmci)
390                 return -ENOMEM;
391
392         pmci->m10bmc.flash_bulk_ops = &m10bmc_pmci_flash_bulk_ops;
393         pmci->m10bmc.dev = dev;
394
395         pmci->base = devm_ioremap_resource(dev, &ddev->mmio_res);
396         if (IS_ERR(pmci->base))
397                 return PTR_ERR(pmci->base);
398
399         ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
400         if (!ctx)
401                 return -ENOMEM;
402
403         mutex_init(&pmci->flash_mutex);
404
405         ctx->base = pmci->base + M10BMC_N6000_INDIRECT_BASE;
406         ctx->dev = dev;
407         indirect_clear_cmd(ctx);
408         pmci->m10bmc.regmap = devm_regmap_init(dev, NULL, ctx, &m10bmc_pmci_regmap_config);
409
410         if (IS_ERR(pmci->m10bmc.regmap)) {
411                 ret = PTR_ERR(pmci->m10bmc.regmap);
412                 goto destroy_mutex;
413         }
414
415         ret = m10bmc_dev_init(&pmci->m10bmc, &m10bmc_pmci_n6000);
416         if (ret)
417                 goto destroy_mutex;
418         return 0;
419
420 destroy_mutex:
421         mutex_destroy(&pmci->flash_mutex);
422         return ret;
423 }
424
425 static void m10bmc_pmci_remove(struct dfl_device *ddev)
426 {
427         struct intel_m10bmc *m10bmc = dev_get_drvdata(&ddev->dev);
428         struct m10bmc_pmci_device *pmci = container_of(m10bmc, struct m10bmc_pmci_device, m10bmc);
429
430         mutex_destroy(&pmci->flash_mutex);
431 }
432
433 #define FME_FEATURE_ID_M10BMC_PMCI      0x12
434
435 static const struct dfl_device_id m10bmc_pmci_ids[] = {
436         { FME_ID, FME_FEATURE_ID_M10BMC_PMCI },
437         { }
438 };
439 MODULE_DEVICE_TABLE(dfl, m10bmc_pmci_ids);
440
441 static struct dfl_driver m10bmc_pmci_driver = {
442         .drv    = {
443                 .name       = "intel-m10-bmc",
444                 .dev_groups = m10bmc_dev_groups,
445         },
446         .id_table = m10bmc_pmci_ids,
447         .probe    = m10bmc_pmci_probe,
448         .remove   = m10bmc_pmci_remove,
449 };
450
451 module_dfl_driver(m10bmc_pmci_driver);
452
453 MODULE_DESCRIPTION("MAX10 BMC PMCI-based interface");
454 MODULE_AUTHOR("Intel Corporation");
455 MODULE_LICENSE("GPL");
456 MODULE_IMPORT_NS(INTEL_M10_BMC_CORE);