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