Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tags 'ib-mfd-extcon-i2c-v6.3' and 'ib-mfd-fpga-hwmon-v6.3-1' into ibs-for-mfd-merged

Immutable branch between MFD, Extcon and I2C due for the v6.3 merge window

Immutable branch between MFD, FPGA and HWMON due for the v6.3 merge window

+1221 -433
+4 -4
Documentation/ABI/testing/sysfs-driver-intel-m10-bmc
··· 1 - What: /sys/bus/spi/devices/.../bmc_version 1 + What: /sys/bus/.../drivers/intel-m10-bmc/.../bmc_version 2 2 Date: June 2020 3 3 KernelVersion: 5.10 4 4 Contact: Xu Yilun <yilun.xu@intel.com> ··· 6 6 MAX10 BMC chip. 7 7 Format: "0x%x". 8 8 9 - What: /sys/bus/spi/devices/.../bmcfw_version 9 + What: /sys/bus/.../drivers/intel-m10-bmc/.../bmcfw_version 10 10 Date: June 2020 11 11 KernelVersion: 5.10 12 12 Contact: Xu Yilun <yilun.xu@intel.com> ··· 14 14 BMC chip. 15 15 Format: "0x%x". 16 16 17 - What: /sys/bus/spi/devices/.../mac_address 17 + What: /sys/bus/.../drivers/intel-m10-bmc/.../mac_address 18 18 Date: January 2021 19 19 KernelVersion: 5.12 20 20 Contact: Russ Weight <russell.h.weight@intel.com> ··· 25 25 space. 26 26 Format: "%02x:%02x:%02x:%02x:%02x:%02x". 27 27 28 - What: /sys/bus/spi/devices/.../mac_count 28 + What: /sys/bus/.../drivers/intel-m10-bmc/.../mac_count 29 29 Date: January 2021 30 30 KernelVersion: 5.12 31 31 Contact: Russ Weight <russell.h.weight@intel.com>
+1 -1
MAINTAINERS
··· 10576 10576 F: Documentation/ABI/testing/sysfs-driver-intel-m10-bmc 10577 10577 F: Documentation/hwmon/intel-m10-bmc-hwmon.rst 10578 10578 F: drivers/hwmon/intel-m10-bmc-hwmon.c 10579 - F: drivers/mfd/intel-m10-bmc.c 10579 + F: drivers/mfd/intel-m10-bmc* 10580 10580 F: include/linux/mfd/intel-m10-bmc.h 10581 10581 10582 10582 INTEL MENLOW THERMAL DRIVER
+1 -1
drivers/fpga/Kconfig
··· 246 246 247 247 config FPGA_M10_BMC_SEC_UPDATE 248 248 tristate "Intel MAX10 BMC Secure Update driver" 249 - depends on MFD_INTEL_M10_BMC 249 + depends on MFD_INTEL_M10_BMC_CORE 250 250 select FW_LOADER 251 251 select FW_UPLOAD 252 252 help
+273 -142
drivers/fpga/intel-m10-bmc-sec-update.c
··· 14 14 #include <linux/platform_device.h> 15 15 #include <linux/slab.h> 16 16 17 + struct m10bmc_sec; 18 + 19 + struct m10bmc_sec_ops { 20 + int (*rsu_status)(struct m10bmc_sec *sec); 21 + }; 22 + 17 23 struct m10bmc_sec { 18 24 struct device *dev; 19 25 struct intel_m10bmc *m10bmc; ··· 27 21 char *fw_name; 28 22 u32 fw_name_id; 29 23 bool cancel_request; 24 + const struct m10bmc_sec_ops *ops; 30 25 }; 31 26 32 27 static DEFINE_XARRAY_ALLOC(fw_upload_xa); ··· 38 31 #define REH_MAGIC GENMASK(15, 0) 39 32 #define REH_SHA_NUM_BYTES GENMASK(31, 16) 40 33 34 + static int m10bmc_sec_write(struct m10bmc_sec *sec, const u8 *buf, u32 offset, u32 size) 35 + { 36 + struct intel_m10bmc *m10bmc = sec->m10bmc; 37 + unsigned int stride = regmap_get_reg_stride(m10bmc->regmap); 38 + u32 write_count = size / stride; 39 + u32 leftover_offset = write_count * stride; 40 + u32 leftover_size = size - leftover_offset; 41 + u32 leftover_tmp = 0; 42 + int ret; 43 + 44 + if (sec->m10bmc->flash_bulk_ops) 45 + return sec->m10bmc->flash_bulk_ops->write(m10bmc, buf, offset, size); 46 + 47 + if (WARN_ON_ONCE(stride > sizeof(leftover_tmp))) 48 + return -EINVAL; 49 + 50 + ret = regmap_bulk_write(m10bmc->regmap, M10BMC_STAGING_BASE + offset, 51 + buf + offset, write_count); 52 + if (ret) 53 + return ret; 54 + 55 + /* If size is not aligned to stride, handle the remainder bytes with regmap_write() */ 56 + if (leftover_size) { 57 + memcpy(&leftover_tmp, buf + leftover_offset, leftover_size); 58 + ret = regmap_write(m10bmc->regmap, M10BMC_STAGING_BASE + offset + leftover_offset, 59 + leftover_tmp); 60 + if (ret) 61 + return ret; 62 + } 63 + 64 + return 0; 65 + } 66 + 67 + static int m10bmc_sec_read(struct m10bmc_sec *sec, u8 *buf, u32 addr, u32 size) 68 + { 69 + struct intel_m10bmc *m10bmc = sec->m10bmc; 70 + unsigned int stride = regmap_get_reg_stride(m10bmc->regmap); 71 + u32 read_count = size / stride; 72 + u32 leftover_offset = read_count * stride; 73 + u32 leftover_size = size - leftover_offset; 74 + u32 leftover_tmp; 75 + int ret; 76 + 77 + if (sec->m10bmc->flash_bulk_ops) 78 + return sec->m10bmc->flash_bulk_ops->read(m10bmc, buf, addr, size); 79 + 80 + if (WARN_ON_ONCE(stride > sizeof(leftover_tmp))) 81 + return -EINVAL; 82 + 83 + ret = regmap_bulk_read(m10bmc->regmap, addr, buf, read_count); 84 + if (ret) 85 + return ret; 86 + 87 + /* If size is not aligned to stride, handle the remainder bytes with regmap_read() */ 88 + if (leftover_size) { 89 + ret = regmap_read(m10bmc->regmap, addr + leftover_offset, &leftover_tmp); 90 + if (ret) 91 + return ret; 92 + memcpy(buf + leftover_offset, &leftover_tmp, leftover_size); 93 + } 94 + 95 + return 0; 96 + } 97 + 98 + 41 99 static ssize_t 42 100 show_root_entry_hash(struct device *dev, u32 exp_magic, 43 101 u32 prog_addr, u32 reh_addr, char *buf) ··· 110 38 struct m10bmc_sec *sec = dev_get_drvdata(dev); 111 39 int sha_num_bytes, i, ret, cnt = 0; 112 40 u8 hash[REH_SHA384_SIZE]; 113 - unsigned int stride; 114 41 u32 magic; 115 42 116 - stride = regmap_get_reg_stride(sec->m10bmc->regmap); 117 - ret = m10bmc_raw_read(sec->m10bmc, prog_addr, &magic); 43 + ret = m10bmc_sec_read(sec, (u8 *)&magic, prog_addr, sizeof(magic)); 118 44 if (ret) 119 45 return ret; 120 46 ··· 120 50 return sysfs_emit(buf, "hash not programmed\n"); 121 51 122 52 sha_num_bytes = FIELD_GET(REH_SHA_NUM_BYTES, magic) / 8; 123 - if ((sha_num_bytes % stride) || 124 - (sha_num_bytes != REH_SHA256_SIZE && 125 - sha_num_bytes != REH_SHA384_SIZE)) { 53 + if (sha_num_bytes != REH_SHA256_SIZE && 54 + sha_num_bytes != REH_SHA384_SIZE) { 126 55 dev_err(sec->dev, "%s bad sha num bytes %d\n", __func__, 127 56 sha_num_bytes); 128 57 return -EINVAL; 129 58 } 130 59 131 - ret = regmap_bulk_read(sec->m10bmc->regmap, reh_addr, 132 - hash, sha_num_bytes / stride); 60 + ret = m10bmc_sec_read(sec, hash, reh_addr, sha_num_bytes); 133 61 if (ret) { 134 - dev_err(dev, "failed to read root entry hash: %x cnt %x: %d\n", 135 - reh_addr, sha_num_bytes / stride, ret); 62 + dev_err(dev, "failed to read root entry hash\n"); 136 63 return ret; 137 64 } 138 65 ··· 140 73 return cnt; 141 74 } 142 75 143 - #define DEVICE_ATTR_SEC_REH_RO(_name, _magic, _prog_addr, _reh_addr) \ 76 + #define DEVICE_ATTR_SEC_REH_RO(_name) \ 144 77 static ssize_t _name##_root_entry_hash_show(struct device *dev, \ 145 78 struct device_attribute *attr, \ 146 79 char *buf) \ 147 - { return show_root_entry_hash(dev, _magic, _prog_addr, _reh_addr, buf); } \ 80 + { \ 81 + struct m10bmc_sec *sec = dev_get_drvdata(dev); \ 82 + const struct m10bmc_csr_map *csr_map = sec->m10bmc->info->csr_map; \ 83 + \ 84 + return show_root_entry_hash(dev, csr_map->_name##_magic, \ 85 + csr_map->_name##_prog_addr, \ 86 + csr_map->_name##_reh_addr, \ 87 + buf); \ 88 + } \ 148 89 static DEVICE_ATTR_RO(_name##_root_entry_hash) 149 90 150 - DEVICE_ATTR_SEC_REH_RO(bmc, BMC_PROG_MAGIC, BMC_PROG_ADDR, BMC_REH_ADDR); 151 - DEVICE_ATTR_SEC_REH_RO(sr, SR_PROG_MAGIC, SR_PROG_ADDR, SR_REH_ADDR); 152 - DEVICE_ATTR_SEC_REH_RO(pr, PR_PROG_MAGIC, PR_PROG_ADDR, PR_REH_ADDR); 91 + DEVICE_ATTR_SEC_REH_RO(bmc); 92 + DEVICE_ATTR_SEC_REH_RO(sr); 93 + DEVICE_ATTR_SEC_REH_RO(pr); 153 94 154 95 #define CSK_BIT_LEN 128U 155 96 #define CSK_32ARRAY_SIZE DIV_ROUND_UP(CSK_BIT_LEN, 32) ··· 165 90 static ssize_t 166 91 show_canceled_csk(struct device *dev, u32 addr, char *buf) 167 92 { 168 - unsigned int i, stride, size = CSK_32ARRAY_SIZE * sizeof(u32); 93 + unsigned int i, size = CSK_32ARRAY_SIZE * sizeof(u32); 169 94 struct m10bmc_sec *sec = dev_get_drvdata(dev); 170 95 DECLARE_BITMAP(csk_map, CSK_BIT_LEN); 171 96 __le32 csk_le32[CSK_32ARRAY_SIZE]; 172 97 u32 csk32[CSK_32ARRAY_SIZE]; 173 98 int ret; 174 99 175 - stride = regmap_get_reg_stride(sec->m10bmc->regmap); 176 - if (size % stride) { 177 - dev_err(sec->dev, 178 - "CSK vector size (0x%x) not aligned to stride (0x%x)\n", 179 - size, stride); 180 - WARN_ON_ONCE(1); 181 - return -EINVAL; 182 - } 183 - 184 - ret = regmap_bulk_read(sec->m10bmc->regmap, addr, csk_le32, 185 - size / stride); 100 + ret = m10bmc_sec_read(sec, (u8 *)&csk_le32, addr, size); 186 101 if (ret) { 187 - dev_err(sec->dev, "failed to read CSK vector: %x cnt %x: %d\n", 188 - addr, size / stride, ret); 102 + dev_err(sec->dev, "failed to read CSK vector\n"); 189 103 return ret; 190 104 } 191 105 ··· 186 122 return bitmap_print_to_pagebuf(1, buf, csk_map, CSK_BIT_LEN); 187 123 } 188 124 189 - #define DEVICE_ATTR_SEC_CSK_RO(_name, _addr) \ 125 + #define DEVICE_ATTR_SEC_CSK_RO(_name) \ 190 126 static ssize_t _name##_canceled_csks_show(struct device *dev, \ 191 127 struct device_attribute *attr, \ 192 128 char *buf) \ 193 - { return show_canceled_csk(dev, _addr, buf); } \ 129 + { \ 130 + struct m10bmc_sec *sec = dev_get_drvdata(dev); \ 131 + const struct m10bmc_csr_map *csr_map = sec->m10bmc->info->csr_map; \ 132 + \ 133 + return show_canceled_csk(dev, \ 134 + csr_map->_name##_prog_addr + CSK_VEC_OFFSET, \ 135 + buf); \ 136 + } \ 194 137 static DEVICE_ATTR_RO(_name##_canceled_csks) 195 138 196 139 #define CSK_VEC_OFFSET 0x34 197 140 198 - DEVICE_ATTR_SEC_CSK_RO(bmc, BMC_PROG_ADDR + CSK_VEC_OFFSET); 199 - DEVICE_ATTR_SEC_CSK_RO(sr, SR_PROG_ADDR + CSK_VEC_OFFSET); 200 - DEVICE_ATTR_SEC_CSK_RO(pr, PR_PROG_ADDR + CSK_VEC_OFFSET); 141 + DEVICE_ATTR_SEC_CSK_RO(bmc); 142 + DEVICE_ATTR_SEC_CSK_RO(sr); 143 + DEVICE_ATTR_SEC_CSK_RO(pr); 201 144 202 145 #define FLASH_COUNT_SIZE 4096 /* count stored as inverted bit vector */ 203 146 ··· 212 141 struct device_attribute *attr, char *buf) 213 142 { 214 143 struct m10bmc_sec *sec = dev_get_drvdata(dev); 215 - unsigned int stride, num_bits; 144 + const struct m10bmc_csr_map *csr_map = sec->m10bmc->info->csr_map; 145 + unsigned int num_bits; 216 146 u8 *flash_buf; 217 147 int cnt, ret; 218 148 219 - stride = regmap_get_reg_stride(sec->m10bmc->regmap); 220 149 num_bits = FLASH_COUNT_SIZE * 8; 221 - 222 - if (FLASH_COUNT_SIZE % stride) { 223 - dev_err(sec->dev, 224 - "FLASH_COUNT_SIZE (0x%x) not aligned to stride (0x%x)\n", 225 - FLASH_COUNT_SIZE, stride); 226 - WARN_ON_ONCE(1); 227 - return -EINVAL; 228 - } 229 150 230 151 flash_buf = kmalloc(FLASH_COUNT_SIZE, GFP_KERNEL); 231 152 if (!flash_buf) 232 153 return -ENOMEM; 233 154 234 - ret = regmap_bulk_read(sec->m10bmc->regmap, STAGING_FLASH_COUNT, 235 - flash_buf, FLASH_COUNT_SIZE / stride); 155 + ret = m10bmc_sec_read(sec, flash_buf, csr_map->rsu_update_counter, 156 + FLASH_COUNT_SIZE); 236 157 if (ret) { 237 - dev_err(sec->dev, 238 - "failed to read flash count: %x cnt %x: %d\n", 239 - STAGING_FLASH_COUNT, FLASH_COUNT_SIZE / stride, ret); 158 + dev_err(sec->dev, "failed to read flash count\n"); 240 159 goto exit_free; 241 160 } 242 161 cnt = num_bits - bitmap_weight((unsigned long *)flash_buf, num_bits); ··· 261 200 262 201 static void log_error_regs(struct m10bmc_sec *sec, u32 doorbell) 263 202 { 203 + const struct m10bmc_csr_map *csr_map = sec->m10bmc->info->csr_map; 264 204 u32 auth_result; 265 205 266 - dev_err(sec->dev, "RSU error status: 0x%08x\n", doorbell); 206 + dev_err(sec->dev, "Doorbell: 0x%08x\n", doorbell); 267 207 268 - if (!m10bmc_sys_read(sec->m10bmc, M10BMC_AUTH_RESULT, &auth_result)) 208 + if (!m10bmc_sys_read(sec->m10bmc, csr_map->auth_result, &auth_result)) 269 209 dev_err(sec->dev, "RSU auth result: 0x%08x\n", auth_result); 210 + } 211 + 212 + static int m10bmc_sec_n3000_rsu_status(struct m10bmc_sec *sec) 213 + { 214 + const struct m10bmc_csr_map *csr_map = sec->m10bmc->info->csr_map; 215 + u32 doorbell; 216 + int ret; 217 + 218 + ret = m10bmc_sys_read(sec->m10bmc, csr_map->doorbell, &doorbell); 219 + if (ret) 220 + return ret; 221 + 222 + return FIELD_GET(DRBL_RSU_STATUS, doorbell); 223 + } 224 + 225 + static int m10bmc_sec_n6000_rsu_status(struct m10bmc_sec *sec) 226 + { 227 + const struct m10bmc_csr_map *csr_map = sec->m10bmc->info->csr_map; 228 + u32 auth_result; 229 + int ret; 230 + 231 + ret = m10bmc_sys_read(sec->m10bmc, csr_map->auth_result, &auth_result); 232 + if (ret) 233 + return ret; 234 + 235 + return FIELD_GET(AUTH_RESULT_RSU_STATUS, auth_result); 236 + } 237 + 238 + static bool rsu_status_ok(u32 status) 239 + { 240 + return (status == RSU_STAT_NORMAL || 241 + status == RSU_STAT_NIOS_OK || 242 + status == RSU_STAT_USER_OK || 243 + status == RSU_STAT_FACTORY_OK); 244 + } 245 + 246 + static bool rsu_progress_done(u32 progress) 247 + { 248 + return (progress == RSU_PROG_IDLE || 249 + progress == RSU_PROG_RSU_DONE); 250 + } 251 + 252 + static bool rsu_progress_busy(u32 progress) 253 + { 254 + return (progress == RSU_PROG_AUTHENTICATING || 255 + progress == RSU_PROG_COPYING || 256 + progress == RSU_PROG_UPDATE_CANCEL || 257 + progress == RSU_PROG_PROGRAM_KEY_HASH); 258 + } 259 + 260 + static int m10bmc_sec_progress_status(struct m10bmc_sec *sec, u32 *doorbell_reg, 261 + u32 *progress, u32 *status) 262 + { 263 + const struct m10bmc_csr_map *csr_map = sec->m10bmc->info->csr_map; 264 + int ret; 265 + 266 + ret = m10bmc_sys_read(sec->m10bmc, csr_map->doorbell, doorbell_reg); 267 + if (ret) 268 + return ret; 269 + 270 + ret = sec->ops->rsu_status(sec); 271 + if (ret < 0) 272 + return ret; 273 + 274 + *status = ret; 275 + *progress = rsu_prog(*doorbell_reg); 276 + 277 + return 0; 270 278 } 271 279 272 280 static enum fw_upload_err rsu_check_idle(struct m10bmc_sec *sec) 273 281 { 282 + const struct m10bmc_csr_map *csr_map = sec->m10bmc->info->csr_map; 274 283 u32 doorbell; 275 284 int ret; 276 285 277 - ret = m10bmc_sys_read(sec->m10bmc, M10BMC_DOORBELL, &doorbell); 286 + ret = m10bmc_sys_read(sec->m10bmc, csr_map->doorbell, &doorbell); 278 287 if (ret) 279 288 return FW_UPLOAD_ERR_RW_ERROR; 280 289 281 - if (rsu_prog(doorbell) != RSU_PROG_IDLE && 282 - rsu_prog(doorbell) != RSU_PROG_RSU_DONE) { 290 + if (!rsu_progress_done(rsu_prog(doorbell))) { 283 291 log_error_regs(sec, doorbell); 284 292 return FW_UPLOAD_ERR_BUSY; 285 293 } ··· 356 226 return FW_UPLOAD_ERR_NONE; 357 227 } 358 228 359 - static inline bool rsu_start_done(u32 doorbell) 229 + static inline bool rsu_start_done(u32 doorbell_reg, u32 progress, u32 status) 360 230 { 361 - u32 status, progress; 362 - 363 - if (doorbell & DRBL_RSU_REQUEST) 231 + if (doorbell_reg & DRBL_RSU_REQUEST) 364 232 return false; 365 233 366 - status = rsu_stat(doorbell); 367 234 if (status == RSU_STAT_ERASE_FAIL || status == RSU_STAT_WEAROUT) 368 235 return true; 369 236 370 - progress = rsu_prog(doorbell); 371 - if (progress != RSU_PROG_IDLE && progress != RSU_PROG_RSU_DONE) 237 + if (!rsu_progress_done(progress)) 372 238 return true; 373 239 374 240 return false; ··· 372 246 373 247 static enum fw_upload_err rsu_update_init(struct m10bmc_sec *sec) 374 248 { 375 - u32 doorbell, status; 376 - int ret; 249 + const struct m10bmc_csr_map *csr_map = sec->m10bmc->info->csr_map; 250 + u32 doorbell_reg, progress, status; 251 + int ret, err; 377 252 378 253 ret = regmap_update_bits(sec->m10bmc->regmap, 379 - M10BMC_SYS_BASE + M10BMC_DOORBELL, 254 + csr_map->base + csr_map->doorbell, 380 255 DRBL_RSU_REQUEST | DRBL_HOST_STATUS, 381 256 DRBL_RSU_REQUEST | 382 257 FIELD_PREP(DRBL_HOST_STATUS, ··· 385 258 if (ret) 386 259 return FW_UPLOAD_ERR_RW_ERROR; 387 260 388 - ret = regmap_read_poll_timeout(sec->m10bmc->regmap, 389 - M10BMC_SYS_BASE + M10BMC_DOORBELL, 390 - doorbell, 391 - rsu_start_done(doorbell), 392 - NIOS_HANDSHAKE_INTERVAL_US, 393 - NIOS_HANDSHAKE_TIMEOUT_US); 261 + ret = read_poll_timeout(m10bmc_sec_progress_status, err, 262 + err < 0 || rsu_start_done(doorbell_reg, progress, status), 263 + NIOS_HANDSHAKE_INTERVAL_US, 264 + NIOS_HANDSHAKE_TIMEOUT_US, 265 + false, 266 + sec, &doorbell_reg, &progress, &status); 394 267 395 268 if (ret == -ETIMEDOUT) { 396 - log_error_regs(sec, doorbell); 269 + log_error_regs(sec, doorbell_reg); 397 270 return FW_UPLOAD_ERR_TIMEOUT; 398 - } else if (ret) { 271 + } else if (err) { 399 272 return FW_UPLOAD_ERR_RW_ERROR; 400 273 } 401 274 402 - status = rsu_stat(doorbell); 403 275 if (status == RSU_STAT_WEAROUT) { 404 276 dev_warn(sec->dev, "Excessive flash update count detected\n"); 405 277 return FW_UPLOAD_ERR_WEAROUT; 406 278 } else if (status == RSU_STAT_ERASE_FAIL) { 407 - log_error_regs(sec, doorbell); 279 + log_error_regs(sec, doorbell_reg); 408 280 return FW_UPLOAD_ERR_HW_ERROR; 409 281 } 410 282 ··· 412 286 413 287 static enum fw_upload_err rsu_prog_ready(struct m10bmc_sec *sec) 414 288 { 289 + const struct m10bmc_csr_map *csr_map = sec->m10bmc->info->csr_map; 415 290 unsigned long poll_timeout; 416 291 u32 doorbell, progress; 417 292 int ret; 418 293 419 - ret = m10bmc_sys_read(sec->m10bmc, M10BMC_DOORBELL, &doorbell); 294 + ret = m10bmc_sys_read(sec->m10bmc, csr_map->doorbell, &doorbell); 420 295 if (ret) 421 296 return FW_UPLOAD_ERR_RW_ERROR; 422 297 ··· 427 300 if (time_after(jiffies, poll_timeout)) 428 301 break; 429 302 430 - ret = m10bmc_sys_read(sec->m10bmc, M10BMC_DOORBELL, &doorbell); 303 + ret = m10bmc_sys_read(sec->m10bmc, csr_map->doorbell, &doorbell); 431 304 if (ret) 432 305 return FW_UPLOAD_ERR_RW_ERROR; 433 306 } ··· 446 319 447 320 static enum fw_upload_err rsu_send_data(struct m10bmc_sec *sec) 448 321 { 449 - u32 doorbell; 322 + const struct m10bmc_csr_map *csr_map = sec->m10bmc->info->csr_map; 323 + u32 doorbell_reg, status; 450 324 int ret; 451 325 452 326 ret = regmap_update_bits(sec->m10bmc->regmap, 453 - M10BMC_SYS_BASE + M10BMC_DOORBELL, 327 + csr_map->base + csr_map->doorbell, 454 328 DRBL_HOST_STATUS, 455 329 FIELD_PREP(DRBL_HOST_STATUS, 456 330 HOST_STATUS_WRITE_DONE)); ··· 459 331 return FW_UPLOAD_ERR_RW_ERROR; 460 332 461 333 ret = regmap_read_poll_timeout(sec->m10bmc->regmap, 462 - M10BMC_SYS_BASE + M10BMC_DOORBELL, 463 - doorbell, 464 - rsu_prog(doorbell) != RSU_PROG_READY, 334 + csr_map->base + csr_map->doorbell, 335 + doorbell_reg, 336 + rsu_prog(doorbell_reg) != RSU_PROG_READY, 465 337 NIOS_HANDSHAKE_INTERVAL_US, 466 338 NIOS_HANDSHAKE_TIMEOUT_US); 467 339 468 340 if (ret == -ETIMEDOUT) { 469 - log_error_regs(sec, doorbell); 341 + log_error_regs(sec, doorbell_reg); 470 342 return FW_UPLOAD_ERR_TIMEOUT; 471 343 } else if (ret) { 472 344 return FW_UPLOAD_ERR_RW_ERROR; 473 345 } 474 346 475 - switch (rsu_stat(doorbell)) { 476 - case RSU_STAT_NORMAL: 477 - case RSU_STAT_NIOS_OK: 478 - case RSU_STAT_USER_OK: 479 - case RSU_STAT_FACTORY_OK: 480 - break; 481 - default: 482 - log_error_regs(sec, doorbell); 347 + ret = sec->ops->rsu_status(sec); 348 + if (ret < 0) 349 + return ret; 350 + status = ret; 351 + 352 + if (!rsu_status_ok(status)) { 353 + log_error_regs(sec, doorbell_reg); 483 354 return FW_UPLOAD_ERR_HW_ERROR; 484 355 } 485 356 486 357 return FW_UPLOAD_ERR_NONE; 487 358 } 488 359 489 - static int rsu_check_complete(struct m10bmc_sec *sec, u32 *doorbell) 360 + static int rsu_check_complete(struct m10bmc_sec *sec, u32 *doorbell_reg) 490 361 { 491 - if (m10bmc_sys_read(sec->m10bmc, M10BMC_DOORBELL, doorbell)) 362 + u32 progress, status; 363 + 364 + if (m10bmc_sec_progress_status(sec, doorbell_reg, &progress, &status)) 492 365 return -EIO; 493 366 494 - switch (rsu_stat(*doorbell)) { 495 - case RSU_STAT_NORMAL: 496 - case RSU_STAT_NIOS_OK: 497 - case RSU_STAT_USER_OK: 498 - case RSU_STAT_FACTORY_OK: 499 - break; 500 - default: 367 + if (!rsu_status_ok(status)) 501 368 return -EINVAL; 502 - } 503 369 504 - switch (rsu_prog(*doorbell)) { 505 - case RSU_PROG_IDLE: 506 - case RSU_PROG_RSU_DONE: 370 + if (rsu_progress_done(progress)) 507 371 return 0; 508 - case RSU_PROG_AUTHENTICATING: 509 - case RSU_PROG_COPYING: 510 - case RSU_PROG_UPDATE_CANCEL: 511 - case RSU_PROG_PROGRAM_KEY_HASH: 372 + 373 + if (rsu_progress_busy(progress)) 512 374 return -EAGAIN; 513 - default: 514 - return -EINVAL; 515 - } 375 + 376 + return -EINVAL; 516 377 } 517 378 518 379 static enum fw_upload_err rsu_cancel(struct m10bmc_sec *sec) 519 380 { 381 + const struct m10bmc_csr_map *csr_map = sec->m10bmc->info->csr_map; 520 382 u32 doorbell; 521 383 int ret; 522 384 523 - ret = m10bmc_sys_read(sec->m10bmc, M10BMC_DOORBELL, &doorbell); 385 + ret = m10bmc_sys_read(sec->m10bmc, csr_map->doorbell, &doorbell); 524 386 if (ret) 525 387 return FW_UPLOAD_ERR_RW_ERROR; 526 388 ··· 518 400 return FW_UPLOAD_ERR_BUSY; 519 401 520 402 ret = regmap_update_bits(sec->m10bmc->regmap, 521 - M10BMC_SYS_BASE + M10BMC_DOORBELL, 403 + csr_map->base + csr_map->doorbell, 522 404 DRBL_HOST_STATUS, 523 405 FIELD_PREP(DRBL_HOST_STATUS, 524 406 HOST_STATUS_ABORT_RSU)); ··· 539 421 if (!size || size > M10BMC_STAGING_SIZE) 540 422 return FW_UPLOAD_ERR_INVALID_SIZE; 541 423 424 + if (sec->m10bmc->flash_bulk_ops) 425 + if (sec->m10bmc->flash_bulk_ops->lock_write(sec->m10bmc)) 426 + return FW_UPLOAD_ERR_BUSY; 427 + 542 428 ret = rsu_check_idle(sec); 543 429 if (ret != FW_UPLOAD_ERR_NONE) 544 - return ret; 430 + goto unlock_flash; 545 431 546 432 ret = rsu_update_init(sec); 547 433 if (ret != FW_UPLOAD_ERR_NONE) 548 - return ret; 434 + goto unlock_flash; 549 435 550 436 ret = rsu_prog_ready(sec); 551 437 if (ret != FW_UPLOAD_ERR_NONE) 552 - return ret; 438 + goto unlock_flash; 553 439 554 - if (sec->cancel_request) 555 - return rsu_cancel(sec); 440 + if (sec->cancel_request) { 441 + ret = rsu_cancel(sec); 442 + goto unlock_flash; 443 + } 556 444 557 445 return FW_UPLOAD_ERR_NONE; 446 + 447 + unlock_flash: 448 + if (sec->m10bmc->flash_bulk_ops) 449 + sec->m10bmc->flash_bulk_ops->unlock_write(sec->m10bmc); 450 + return ret; 558 451 } 559 452 560 453 #define WRITE_BLOCK_SIZE 0x4000 /* Default write-block size is 0x4000 bytes */ 561 454 562 - static enum fw_upload_err m10bmc_sec_write(struct fw_upload *fwl, const u8 *data, 563 - u32 offset, u32 size, u32 *written) 455 + static enum fw_upload_err m10bmc_sec_fw_write(struct fw_upload *fwl, const u8 *data, 456 + u32 offset, u32 size, u32 *written) 564 457 { 565 458 struct m10bmc_sec *sec = fwl->dd_handle; 566 - u32 blk_size, doorbell, extra_offset; 567 - unsigned int stride, extra = 0; 459 + const struct m10bmc_csr_map *csr_map = sec->m10bmc->info->csr_map; 460 + struct intel_m10bmc *m10bmc = sec->m10bmc; 461 + u32 blk_size, doorbell; 568 462 int ret; 569 463 570 - stride = regmap_get_reg_stride(sec->m10bmc->regmap); 571 464 if (sec->cancel_request) 572 465 return rsu_cancel(sec); 573 466 574 - ret = m10bmc_sys_read(sec->m10bmc, M10BMC_DOORBELL, &doorbell); 467 + ret = m10bmc_sys_read(m10bmc, csr_map->doorbell, &doorbell); 575 468 if (ret) { 576 469 return FW_UPLOAD_ERR_RW_ERROR; 577 470 } else if (rsu_prog(doorbell) != RSU_PROG_READY) { ··· 590 461 return FW_UPLOAD_ERR_HW_ERROR; 591 462 } 592 463 593 - WARN_ON_ONCE(WRITE_BLOCK_SIZE % stride); 464 + WARN_ON_ONCE(WRITE_BLOCK_SIZE % regmap_get_reg_stride(m10bmc->regmap)); 594 465 blk_size = min_t(u32, WRITE_BLOCK_SIZE, size); 595 - ret = regmap_bulk_write(sec->m10bmc->regmap, 596 - M10BMC_STAGING_BASE + offset, 597 - (void *)data + offset, 598 - blk_size / stride); 466 + ret = m10bmc_sec_write(sec, data, offset, blk_size); 599 467 if (ret) 600 468 return FW_UPLOAD_ERR_RW_ERROR; 601 - 602 - /* 603 - * If blk_size is not aligned to stride, then handle the extra 604 - * bytes with regmap_write. 605 - */ 606 - if (blk_size % stride) { 607 - extra_offset = offset + ALIGN_DOWN(blk_size, stride); 608 - memcpy(&extra, (u8 *)(data + extra_offset), blk_size % stride); 609 - ret = regmap_write(sec->m10bmc->regmap, 610 - M10BMC_STAGING_BASE + extra_offset, extra); 611 - if (ret) 612 - return FW_UPLOAD_ERR_RW_ERROR; 613 - } 614 469 615 470 *written = blk_size; 616 471 return FW_UPLOAD_ERR_NONE; ··· 652 539 struct m10bmc_sec *sec = fwl->dd_handle; 653 540 654 541 (void)rsu_cancel(sec); 542 + 543 + if (sec->m10bmc->flash_bulk_ops) 544 + sec->m10bmc->flash_bulk_ops->unlock_write(sec->m10bmc); 655 545 } 656 546 657 547 static const struct fw_upload_ops m10bmc_ops = { 658 548 .prepare = m10bmc_sec_prepare, 659 - .write = m10bmc_sec_write, 549 + .write = m10bmc_sec_fw_write, 660 550 .poll_complete = m10bmc_sec_poll_complete, 661 551 .cancel = m10bmc_sec_cancel, 662 552 .cleanup = m10bmc_sec_cleanup, 553 + }; 554 + 555 + static const struct m10bmc_sec_ops m10sec_n3000_ops = { 556 + .rsu_status = m10bmc_sec_n3000_rsu_status, 557 + }; 558 + 559 + static const struct m10bmc_sec_ops m10sec_n6000_ops = { 560 + .rsu_status = m10bmc_sec_n6000_rsu_status, 663 561 }; 664 562 665 563 #define SEC_UPDATE_LEN_MAX 32 ··· 688 564 689 565 sec->dev = &pdev->dev; 690 566 sec->m10bmc = dev_get_drvdata(pdev->dev.parent); 567 + sec->ops = (struct m10bmc_sec_ops *)platform_get_device_id(pdev)->driver_data; 691 568 dev_set_drvdata(&pdev->dev, sec); 692 569 693 570 ret = xa_alloc(&fw_upload_xa, &sec->fw_name_id, sec, ··· 729 604 static const struct platform_device_id intel_m10bmc_sec_ids[] = { 730 605 { 731 606 .name = "n3000bmc-sec-update", 607 + .driver_data = (kernel_ulong_t)&m10sec_n3000_ops, 732 608 }, 733 609 { 734 610 .name = "d5005bmc-sec-update", 611 + .driver_data = (kernel_ulong_t)&m10sec_n3000_ops, 612 + }, 613 + { 614 + .name = "n6000bmc-sec-update", 615 + .driver_data = (kernel_ulong_t)&m10sec_n6000_ops, 735 616 }, 736 617 { } 737 618 };
+1 -1
drivers/hwmon/Kconfig
··· 2341 2341 2342 2342 config SENSORS_INTEL_M10_BMC_HWMON 2343 2343 tristate "Intel MAX10 BMC Hardware Monitoring" 2344 - depends on MFD_INTEL_M10_BMC 2344 + depends on MFD_INTEL_M10_BMC_CORE 2345 2345 help 2346 2346 This driver provides support for the hardware monitoring functionality 2347 2347 on Intel MAX10 BMC chip.
+25 -7
drivers/mfd/Kconfig
··· 2224 2224 If you have an SGI Origin, Octane, or a PCI IOC3 card, 2225 2225 then say Y. Otherwise say N. 2226 2226 2227 - config MFD_INTEL_M10_BMC 2228 - tristate "Intel MAX 10 Board Management Controller" 2229 - depends on SPI_MASTER 2230 - select REGMAP_SPI_AVMM 2231 - select MFD_CORE 2227 + config MFD_INTEL_M10_BMC_CORE 2228 + tristate 2229 + select MFD_CORE 2230 + select REGMAP 2231 + default n 2232 + 2233 + config MFD_INTEL_M10_BMC_SPI 2234 + tristate "Intel MAX 10 Board Management Controller with SPI" 2235 + depends on SPI_MASTER 2236 + select MFD_INTEL_M10_BMC_CORE 2237 + select REGMAP_SPI_AVMM 2238 + help 2239 + Support for the Intel MAX 10 board management controller using the 2240 + SPI interface. 2241 + 2242 + This driver provides common support for accessing the device, 2243 + additional drivers must be enabled in order to use the functionality 2244 + of the device. 2245 + 2246 + config MFD_INTEL_M10_BMC_PMCI 2247 + tristate "Intel MAX 10 Board Management Controller with PMCI" 2248 + depends on FPGA_DFL 2249 + select MFD_INTEL_M10_BMC_CORE 2250 + select REGMAP 2232 2251 help 2233 - Support for the Intel MAX 10 board management controller using the 2234 - SPI interface. 2252 + Support for the Intel MAX 10 board management controller via PMCI. 2235 2253 2236 2254 This driver provides common support for accessing the device, 2237 2255 additional drivers must be enabled in order to use the functionality
+4 -1
drivers/mfd/Makefile
··· 269 269 obj-$(CONFIG_SGI_MFD_IOC3) += ioc3.o 270 270 obj-$(CONFIG_MFD_SIMPLE_MFD_I2C) += simple-mfd-i2c.o 271 271 obj-$(CONFIG_MFD_SMPRO) += smpro-core.o 272 - obj-$(CONFIG_MFD_INTEL_M10_BMC) += intel-m10-bmc.o 272 + 273 + obj-$(CONFIG_MFD_INTEL_M10_BMC_CORE) += intel-m10-bmc-core.o 274 + obj-$(CONFIG_MFD_INTEL_M10_BMC_SPI) += intel-m10-bmc-spi.o 275 + obj-$(CONFIG_MFD_INTEL_M10_BMC_PMCI) += intel-m10-bmc-pmci.o 273 276 274 277 obj-$(CONFIG_MFD_ATC260X) += atc260x-core.o 275 278 obj-$(CONFIG_MFD_ATC260X_I2C) += atc260x-i2c.o
+122
drivers/mfd/intel-m10-bmc-core.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Intel MAX 10 Board Management Controller chip - common code 4 + * 5 + * Copyright (C) 2018-2020 Intel Corporation. All rights reserved. 6 + */ 7 + 8 + #include <linux/bitfield.h> 9 + #include <linux/device.h> 10 + #include <linux/dev_printk.h> 11 + #include <linux/mfd/core.h> 12 + #include <linux/mfd/intel-m10-bmc.h> 13 + #include <linux/module.h> 14 + 15 + static ssize_t bmc_version_show(struct device *dev, 16 + struct device_attribute *attr, char *buf) 17 + { 18 + struct intel_m10bmc *ddata = dev_get_drvdata(dev); 19 + unsigned int val; 20 + int ret; 21 + 22 + ret = m10bmc_sys_read(ddata, ddata->info->csr_map->build_version, &val); 23 + if (ret) 24 + return ret; 25 + 26 + return sprintf(buf, "0x%x\n", val); 27 + } 28 + static DEVICE_ATTR_RO(bmc_version); 29 + 30 + static ssize_t bmcfw_version_show(struct device *dev, 31 + struct device_attribute *attr, char *buf) 32 + { 33 + struct intel_m10bmc *ddata = dev_get_drvdata(dev); 34 + unsigned int val; 35 + int ret; 36 + 37 + ret = m10bmc_sys_read(ddata, ddata->info->csr_map->fw_version, &val); 38 + if (ret) 39 + return ret; 40 + 41 + return sprintf(buf, "0x%x\n", val); 42 + } 43 + static DEVICE_ATTR_RO(bmcfw_version); 44 + 45 + static ssize_t mac_address_show(struct device *dev, 46 + struct device_attribute *attr, char *buf) 47 + { 48 + struct intel_m10bmc *ddata = dev_get_drvdata(dev); 49 + unsigned int macaddr_low, macaddr_high; 50 + int ret; 51 + 52 + ret = m10bmc_sys_read(ddata, ddata->info->csr_map->mac_low, &macaddr_low); 53 + if (ret) 54 + return ret; 55 + 56 + ret = m10bmc_sys_read(ddata, ddata->info->csr_map->mac_high, &macaddr_high); 57 + if (ret) 58 + return ret; 59 + 60 + return sysfs_emit(buf, "%02x:%02x:%02x:%02x:%02x:%02x\n", 61 + (u8)FIELD_GET(M10BMC_N3000_MAC_BYTE1, macaddr_low), 62 + (u8)FIELD_GET(M10BMC_N3000_MAC_BYTE2, macaddr_low), 63 + (u8)FIELD_GET(M10BMC_N3000_MAC_BYTE3, macaddr_low), 64 + (u8)FIELD_GET(M10BMC_N3000_MAC_BYTE4, macaddr_low), 65 + (u8)FIELD_GET(M10BMC_N3000_MAC_BYTE5, macaddr_high), 66 + (u8)FIELD_GET(M10BMC_N3000_MAC_BYTE6, macaddr_high)); 67 + } 68 + static DEVICE_ATTR_RO(mac_address); 69 + 70 + static ssize_t mac_count_show(struct device *dev, 71 + struct device_attribute *attr, char *buf) 72 + { 73 + struct intel_m10bmc *ddata = dev_get_drvdata(dev); 74 + unsigned int macaddr_high; 75 + int ret; 76 + 77 + ret = m10bmc_sys_read(ddata, ddata->info->csr_map->mac_high, &macaddr_high); 78 + if (ret) 79 + return ret; 80 + 81 + return sysfs_emit(buf, "%u\n", (u8)FIELD_GET(M10BMC_N3000_MAC_COUNT, macaddr_high)); 82 + } 83 + static DEVICE_ATTR_RO(mac_count); 84 + 85 + static struct attribute *m10bmc_attrs[] = { 86 + &dev_attr_bmc_version.attr, 87 + &dev_attr_bmcfw_version.attr, 88 + &dev_attr_mac_address.attr, 89 + &dev_attr_mac_count.attr, 90 + NULL, 91 + }; 92 + 93 + static const struct attribute_group m10bmc_group = { 94 + .attrs = m10bmc_attrs, 95 + }; 96 + 97 + const struct attribute_group *m10bmc_dev_groups[] = { 98 + &m10bmc_group, 99 + NULL, 100 + }; 101 + EXPORT_SYMBOL_GPL(m10bmc_dev_groups); 102 + 103 + int m10bmc_dev_init(struct intel_m10bmc *m10bmc, const struct intel_m10bmc_platform_info *info) 104 + { 105 + int ret; 106 + 107 + m10bmc->info = info; 108 + dev_set_drvdata(m10bmc->dev, m10bmc); 109 + 110 + ret = devm_mfd_add_devices(m10bmc->dev, PLATFORM_DEVID_AUTO, 111 + info->cells, info->n_cells, 112 + NULL, 0, NULL); 113 + if (ret) 114 + dev_err(m10bmc->dev, "Failed to register sub-devices: %d\n", ret); 115 + 116 + return ret; 117 + } 118 + EXPORT_SYMBOL_GPL(m10bmc_dev_init); 119 + 120 + MODULE_DESCRIPTION("Intel MAX 10 BMC core driver"); 121 + MODULE_AUTHOR("Intel Corporation"); 122 + MODULE_LICENSE("GPL v2");
+455
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");
+168
drivers/mfd/intel-m10-bmc-spi.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Intel MAX 10 Board Management Controller chip 4 + * 5 + * Copyright (C) 2018-2020 Intel Corporation. All rights reserved. 6 + */ 7 + #include <linux/bitfield.h> 8 + #include <linux/dev_printk.h> 9 + #include <linux/init.h> 10 + #include <linux/mfd/core.h> 11 + #include <linux/mfd/intel-m10-bmc.h> 12 + #include <linux/module.h> 13 + #include <linux/regmap.h> 14 + #include <linux/spi/spi.h> 15 + 16 + static const struct regmap_range m10bmc_regmap_range[] = { 17 + regmap_reg_range(M10BMC_N3000_LEGACY_BUILD_VER, M10BMC_N3000_LEGACY_BUILD_VER), 18 + regmap_reg_range(M10BMC_N3000_SYS_BASE, M10BMC_N3000_SYS_END), 19 + regmap_reg_range(M10BMC_N3000_FLASH_BASE, M10BMC_N3000_FLASH_END), 20 + }; 21 + 22 + static const struct regmap_access_table m10bmc_access_table = { 23 + .yes_ranges = m10bmc_regmap_range, 24 + .n_yes_ranges = ARRAY_SIZE(m10bmc_regmap_range), 25 + }; 26 + 27 + static struct regmap_config intel_m10bmc_regmap_config = { 28 + .reg_bits = 32, 29 + .val_bits = 32, 30 + .reg_stride = 4, 31 + .wr_table = &m10bmc_access_table, 32 + .rd_table = &m10bmc_access_table, 33 + .max_register = M10BMC_N3000_MEM_END, 34 + }; 35 + 36 + static int check_m10bmc_version(struct intel_m10bmc *ddata) 37 + { 38 + unsigned int v; 39 + int ret; 40 + 41 + /* 42 + * This check is to filter out the very old legacy BMC versions. In the 43 + * old BMC chips, the BMC version info is stored in the old version 44 + * register (M10BMC_N3000_LEGACY_BUILD_VER), so its read out value would have 45 + * not been M10BMC_N3000_VER_LEGACY_INVALID (0xffffffff). But in new BMC 46 + * chips that the driver supports, the value of this register should be 47 + * M10BMC_N3000_VER_LEGACY_INVALID. 48 + */ 49 + ret = m10bmc_raw_read(ddata, M10BMC_N3000_LEGACY_BUILD_VER, &v); 50 + if (ret) 51 + return -ENODEV; 52 + 53 + if (v != M10BMC_N3000_VER_LEGACY_INVALID) { 54 + dev_err(ddata->dev, "bad version M10BMC detected\n"); 55 + return -ENODEV; 56 + } 57 + 58 + return 0; 59 + } 60 + 61 + static int intel_m10_bmc_spi_probe(struct spi_device *spi) 62 + { 63 + const struct spi_device_id *id = spi_get_device_id(spi); 64 + const struct intel_m10bmc_platform_info *info; 65 + struct device *dev = &spi->dev; 66 + struct intel_m10bmc *ddata; 67 + int ret; 68 + 69 + ddata = devm_kzalloc(dev, sizeof(*ddata), GFP_KERNEL); 70 + if (!ddata) 71 + return -ENOMEM; 72 + 73 + info = (struct intel_m10bmc_platform_info *)id->driver_data; 74 + ddata->dev = dev; 75 + 76 + ddata->regmap = devm_regmap_init_spi_avmm(spi, &intel_m10bmc_regmap_config); 77 + if (IS_ERR(ddata->regmap)) { 78 + ret = PTR_ERR(ddata->regmap); 79 + dev_err(dev, "Failed to allocate regmap: %d\n", ret); 80 + return ret; 81 + } 82 + 83 + spi_set_drvdata(spi, ddata); 84 + 85 + ret = check_m10bmc_version(ddata); 86 + if (ret) { 87 + dev_err(dev, "Failed to identify m10bmc hardware\n"); 88 + return ret; 89 + } 90 + 91 + return m10bmc_dev_init(ddata, info); 92 + } 93 + 94 + static const struct m10bmc_csr_map m10bmc_n3000_csr_map = { 95 + .base = M10BMC_N3000_SYS_BASE, 96 + .build_version = M10BMC_N3000_BUILD_VER, 97 + .fw_version = NIOS2_N3000_FW_VERSION, 98 + .mac_low = M10BMC_N3000_MAC_LOW, 99 + .mac_high = M10BMC_N3000_MAC_HIGH, 100 + .doorbell = M10BMC_N3000_DOORBELL, 101 + .auth_result = M10BMC_N3000_AUTH_RESULT, 102 + .bmc_prog_addr = M10BMC_N3000_BMC_PROG_ADDR, 103 + .bmc_reh_addr = M10BMC_N3000_BMC_REH_ADDR, 104 + .bmc_magic = M10BMC_N3000_BMC_PROG_MAGIC, 105 + .sr_prog_addr = M10BMC_N3000_SR_PROG_ADDR, 106 + .sr_reh_addr = M10BMC_N3000_SR_REH_ADDR, 107 + .sr_magic = M10BMC_N3000_SR_PROG_MAGIC, 108 + .pr_prog_addr = M10BMC_N3000_PR_PROG_ADDR, 109 + .pr_reh_addr = M10BMC_N3000_PR_REH_ADDR, 110 + .pr_magic = M10BMC_N3000_PR_PROG_MAGIC, 111 + .rsu_update_counter = M10BMC_N3000_STAGING_FLASH_COUNT, 112 + }; 113 + 114 + static struct mfd_cell m10bmc_d5005_subdevs[] = { 115 + { .name = "d5005bmc-hwmon" }, 116 + { .name = "d5005bmc-sec-update" }, 117 + }; 118 + 119 + static struct mfd_cell m10bmc_pacn3000_subdevs[] = { 120 + { .name = "n3000bmc-hwmon" }, 121 + { .name = "n3000bmc-retimer" }, 122 + { .name = "n3000bmc-sec-update" }, 123 + }; 124 + 125 + static struct mfd_cell m10bmc_n5010_subdevs[] = { 126 + { .name = "n5010bmc-hwmon" }, 127 + }; 128 + 129 + static const struct intel_m10bmc_platform_info m10bmc_spi_n3000 = { 130 + .cells = m10bmc_pacn3000_subdevs, 131 + .n_cells = ARRAY_SIZE(m10bmc_pacn3000_subdevs), 132 + .csr_map = &m10bmc_n3000_csr_map, 133 + }; 134 + 135 + static const struct intel_m10bmc_platform_info m10bmc_spi_d5005 = { 136 + .cells = m10bmc_d5005_subdevs, 137 + .n_cells = ARRAY_SIZE(m10bmc_d5005_subdevs), 138 + .csr_map = &m10bmc_n3000_csr_map, 139 + }; 140 + 141 + static const struct intel_m10bmc_platform_info m10bmc_spi_n5010 = { 142 + .cells = m10bmc_n5010_subdevs, 143 + .n_cells = ARRAY_SIZE(m10bmc_n5010_subdevs), 144 + .csr_map = &m10bmc_n3000_csr_map, 145 + }; 146 + 147 + static const struct spi_device_id m10bmc_spi_id[] = { 148 + { "m10-n3000", (kernel_ulong_t)&m10bmc_spi_n3000 }, 149 + { "m10-d5005", (kernel_ulong_t)&m10bmc_spi_d5005 }, 150 + { "m10-n5010", (kernel_ulong_t)&m10bmc_spi_n5010 }, 151 + { } 152 + }; 153 + MODULE_DEVICE_TABLE(spi, m10bmc_spi_id); 154 + 155 + static struct spi_driver intel_m10bmc_spi_driver = { 156 + .driver = { 157 + .name = "intel-m10-bmc", 158 + .dev_groups = m10bmc_dev_groups, 159 + }, 160 + .probe = intel_m10_bmc_spi_probe, 161 + .id_table = m10bmc_spi_id, 162 + }; 163 + module_spi_driver(intel_m10bmc_spi_driver); 164 + 165 + MODULE_DESCRIPTION("Intel MAX 10 BMC SPI bus interface"); 166 + MODULE_AUTHOR("Intel Corporation"); 167 + MODULE_LICENSE("GPL v2"); 168 + MODULE_ALIAS("spi:intel-m10-bmc");
-238
drivers/mfd/intel-m10-bmc.c
··· 1 - // SPDX-License-Identifier: GPL-2.0 2 - /* 3 - * Intel MAX 10 Board Management Controller chip 4 - * 5 - * Copyright (C) 2018-2020 Intel Corporation. All rights reserved. 6 - */ 7 - #include <linux/bitfield.h> 8 - #include <linux/init.h> 9 - #include <linux/mfd/core.h> 10 - #include <linux/mfd/intel-m10-bmc.h> 11 - #include <linux/module.h> 12 - #include <linux/mutex.h> 13 - #include <linux/regmap.h> 14 - #include <linux/spi/spi.h> 15 - 16 - enum m10bmc_type { 17 - M10_N3000, 18 - M10_D5005, 19 - M10_N5010, 20 - }; 21 - 22 - static struct mfd_cell m10bmc_d5005_subdevs[] = { 23 - { .name = "d5005bmc-hwmon" }, 24 - { .name = "d5005bmc-sec-update" } 25 - }; 26 - 27 - static struct mfd_cell m10bmc_pacn3000_subdevs[] = { 28 - { .name = "n3000bmc-hwmon" }, 29 - { .name = "n3000bmc-retimer" }, 30 - { .name = "n3000bmc-sec-update" }, 31 - }; 32 - 33 - static struct mfd_cell m10bmc_n5010_subdevs[] = { 34 - { .name = "n5010bmc-hwmon" }, 35 - }; 36 - 37 - static const struct regmap_range m10bmc_regmap_range[] = { 38 - regmap_reg_range(M10BMC_LEGACY_BUILD_VER, M10BMC_LEGACY_BUILD_VER), 39 - regmap_reg_range(M10BMC_SYS_BASE, M10BMC_SYS_END), 40 - regmap_reg_range(M10BMC_FLASH_BASE, M10BMC_FLASH_END), 41 - }; 42 - 43 - static const struct regmap_access_table m10bmc_access_table = { 44 - .yes_ranges = m10bmc_regmap_range, 45 - .n_yes_ranges = ARRAY_SIZE(m10bmc_regmap_range), 46 - }; 47 - 48 - static struct regmap_config intel_m10bmc_regmap_config = { 49 - .reg_bits = 32, 50 - .val_bits = 32, 51 - .reg_stride = 4, 52 - .wr_table = &m10bmc_access_table, 53 - .rd_table = &m10bmc_access_table, 54 - .max_register = M10BMC_MEM_END, 55 - }; 56 - 57 - static ssize_t bmc_version_show(struct device *dev, 58 - struct device_attribute *attr, char *buf) 59 - { 60 - struct intel_m10bmc *ddata = dev_get_drvdata(dev); 61 - unsigned int val; 62 - int ret; 63 - 64 - ret = m10bmc_sys_read(ddata, M10BMC_BUILD_VER, &val); 65 - if (ret) 66 - return ret; 67 - 68 - return sprintf(buf, "0x%x\n", val); 69 - } 70 - static DEVICE_ATTR_RO(bmc_version); 71 - 72 - static ssize_t bmcfw_version_show(struct device *dev, 73 - struct device_attribute *attr, char *buf) 74 - { 75 - struct intel_m10bmc *ddata = dev_get_drvdata(dev); 76 - unsigned int val; 77 - int ret; 78 - 79 - ret = m10bmc_sys_read(ddata, NIOS2_FW_VERSION, &val); 80 - if (ret) 81 - return ret; 82 - 83 - return sprintf(buf, "0x%x\n", val); 84 - } 85 - static DEVICE_ATTR_RO(bmcfw_version); 86 - 87 - static ssize_t mac_address_show(struct device *dev, 88 - struct device_attribute *attr, char *buf) 89 - { 90 - struct intel_m10bmc *max10 = dev_get_drvdata(dev); 91 - unsigned int macaddr_low, macaddr_high; 92 - int ret; 93 - 94 - ret = m10bmc_sys_read(max10, M10BMC_MAC_LOW, &macaddr_low); 95 - if (ret) 96 - return ret; 97 - 98 - ret = m10bmc_sys_read(max10, M10BMC_MAC_HIGH, &macaddr_high); 99 - if (ret) 100 - return ret; 101 - 102 - return sysfs_emit(buf, "%02x:%02x:%02x:%02x:%02x:%02x\n", 103 - (u8)FIELD_GET(M10BMC_MAC_BYTE1, macaddr_low), 104 - (u8)FIELD_GET(M10BMC_MAC_BYTE2, macaddr_low), 105 - (u8)FIELD_GET(M10BMC_MAC_BYTE3, macaddr_low), 106 - (u8)FIELD_GET(M10BMC_MAC_BYTE4, macaddr_low), 107 - (u8)FIELD_GET(M10BMC_MAC_BYTE5, macaddr_high), 108 - (u8)FIELD_GET(M10BMC_MAC_BYTE6, macaddr_high)); 109 - } 110 - static DEVICE_ATTR_RO(mac_address); 111 - 112 - static ssize_t mac_count_show(struct device *dev, 113 - struct device_attribute *attr, char *buf) 114 - { 115 - struct intel_m10bmc *max10 = dev_get_drvdata(dev); 116 - unsigned int macaddr_high; 117 - int ret; 118 - 119 - ret = m10bmc_sys_read(max10, M10BMC_MAC_HIGH, &macaddr_high); 120 - if (ret) 121 - return ret; 122 - 123 - return sysfs_emit(buf, "%u\n", 124 - (u8)FIELD_GET(M10BMC_MAC_COUNT, macaddr_high)); 125 - } 126 - static DEVICE_ATTR_RO(mac_count); 127 - 128 - static struct attribute *m10bmc_attrs[] = { 129 - &dev_attr_bmc_version.attr, 130 - &dev_attr_bmcfw_version.attr, 131 - &dev_attr_mac_address.attr, 132 - &dev_attr_mac_count.attr, 133 - NULL, 134 - }; 135 - ATTRIBUTE_GROUPS(m10bmc); 136 - 137 - static int check_m10bmc_version(struct intel_m10bmc *ddata) 138 - { 139 - unsigned int v; 140 - int ret; 141 - 142 - /* 143 - * This check is to filter out the very old legacy BMC versions. In the 144 - * old BMC chips, the BMC version info is stored in the old version 145 - * register (M10BMC_LEGACY_BUILD_VER), so its read out value would have 146 - * not been M10BMC_VER_LEGACY_INVALID (0xffffffff). But in new BMC 147 - * chips that the driver supports, the value of this register should be 148 - * M10BMC_VER_LEGACY_INVALID. 149 - */ 150 - ret = m10bmc_raw_read(ddata, M10BMC_LEGACY_BUILD_VER, &v); 151 - if (ret) 152 - return -ENODEV; 153 - 154 - if (v != M10BMC_VER_LEGACY_INVALID) { 155 - dev_err(ddata->dev, "bad version M10BMC detected\n"); 156 - return -ENODEV; 157 - } 158 - 159 - return 0; 160 - } 161 - 162 - static int intel_m10_bmc_spi_probe(struct spi_device *spi) 163 - { 164 - const struct spi_device_id *id = spi_get_device_id(spi); 165 - struct device *dev = &spi->dev; 166 - struct mfd_cell *cells; 167 - struct intel_m10bmc *ddata; 168 - int ret, n_cell; 169 - 170 - ddata = devm_kzalloc(dev, sizeof(*ddata), GFP_KERNEL); 171 - if (!ddata) 172 - return -ENOMEM; 173 - 174 - ddata->dev = dev; 175 - 176 - ddata->regmap = 177 - devm_regmap_init_spi_avmm(spi, &intel_m10bmc_regmap_config); 178 - if (IS_ERR(ddata->regmap)) { 179 - ret = PTR_ERR(ddata->regmap); 180 - dev_err(dev, "Failed to allocate regmap: %d\n", ret); 181 - return ret; 182 - } 183 - 184 - spi_set_drvdata(spi, ddata); 185 - 186 - ret = check_m10bmc_version(ddata); 187 - if (ret) { 188 - dev_err(dev, "Failed to identify m10bmc hardware\n"); 189 - return ret; 190 - } 191 - 192 - switch (id->driver_data) { 193 - case M10_N3000: 194 - cells = m10bmc_pacn3000_subdevs; 195 - n_cell = ARRAY_SIZE(m10bmc_pacn3000_subdevs); 196 - break; 197 - case M10_D5005: 198 - cells = m10bmc_d5005_subdevs; 199 - n_cell = ARRAY_SIZE(m10bmc_d5005_subdevs); 200 - break; 201 - case M10_N5010: 202 - cells = m10bmc_n5010_subdevs; 203 - n_cell = ARRAY_SIZE(m10bmc_n5010_subdevs); 204 - break; 205 - default: 206 - return -ENODEV; 207 - } 208 - 209 - ret = devm_mfd_add_devices(dev, PLATFORM_DEVID_AUTO, cells, n_cell, 210 - NULL, 0, NULL); 211 - if (ret) 212 - dev_err(dev, "Failed to register sub-devices: %d\n", ret); 213 - 214 - return ret; 215 - } 216 - 217 - static const struct spi_device_id m10bmc_spi_id[] = { 218 - { "m10-n3000", M10_N3000 }, 219 - { "m10-d5005", M10_D5005 }, 220 - { "m10-n5010", M10_N5010 }, 221 - { } 222 - }; 223 - MODULE_DEVICE_TABLE(spi, m10bmc_spi_id); 224 - 225 - static struct spi_driver intel_m10bmc_spi_driver = { 226 - .driver = { 227 - .name = "intel-m10-bmc", 228 - .dev_groups = m10bmc_groups, 229 - }, 230 - .probe = intel_m10_bmc_spi_probe, 231 - .id_table = m10bmc_spi_id, 232 - }; 233 - module_spi_driver(intel_m10bmc_spi_driver); 234 - 235 - MODULE_DESCRIPTION("Intel MAX 10 BMC Device Driver"); 236 - MODULE_AUTHOR("Intel Corporation"); 237 - MODULE_LICENSE("GPL v2"); 238 - MODULE_ALIAS("spi:intel-m10-bmc");
+167 -38
include/linux/mfd/intel-m10-bmc.h
··· 7 7 #ifndef __MFD_INTEL_M10_BMC_H 8 8 #define __MFD_INTEL_M10_BMC_H 9 9 10 + #include <linux/bitfield.h> 11 + #include <linux/bits.h> 12 + #include <linux/dev_printk.h> 10 13 #include <linux/regmap.h> 11 14 12 - #define M10BMC_LEGACY_BUILD_VER 0x300468 13 - #define M10BMC_SYS_BASE 0x300800 14 - #define M10BMC_SYS_END 0x300fff 15 - #define M10BMC_FLASH_BASE 0x10000000 16 - #define M10BMC_FLASH_END 0x1fffffff 17 - #define M10BMC_MEM_END M10BMC_FLASH_END 15 + #define M10BMC_N3000_LEGACY_BUILD_VER 0x300468 16 + #define M10BMC_N3000_SYS_BASE 0x300800 17 + #define M10BMC_N3000_SYS_END 0x300fff 18 + #define M10BMC_N3000_FLASH_BASE 0x10000000 19 + #define M10BMC_N3000_FLASH_END 0x1fffffff 20 + #define M10BMC_N3000_MEM_END M10BMC_N3000_FLASH_END 18 21 19 22 #define M10BMC_STAGING_BASE 0x18000000 20 23 #define M10BMC_STAGING_SIZE 0x3800000 21 24 22 25 /* Register offset of system registers */ 23 - #define NIOS2_FW_VERSION 0x0 24 - #define M10BMC_MAC_LOW 0x10 25 - #define M10BMC_MAC_BYTE4 GENMASK(7, 0) 26 - #define M10BMC_MAC_BYTE3 GENMASK(15, 8) 27 - #define M10BMC_MAC_BYTE2 GENMASK(23, 16) 28 - #define M10BMC_MAC_BYTE1 GENMASK(31, 24) 29 - #define M10BMC_MAC_HIGH 0x14 30 - #define M10BMC_MAC_BYTE6 GENMASK(7, 0) 31 - #define M10BMC_MAC_BYTE5 GENMASK(15, 8) 32 - #define M10BMC_MAC_COUNT GENMASK(23, 16) 33 - #define M10BMC_TEST_REG 0x3c 34 - #define M10BMC_BUILD_VER 0x68 35 - #define M10BMC_VER_MAJOR_MSK GENMASK(23, 16) 36 - #define M10BMC_VER_PCB_INFO_MSK GENMASK(31, 24) 37 - #define M10BMC_VER_LEGACY_INVALID 0xffffffff 26 + #define NIOS2_N3000_FW_VERSION 0x0 27 + #define M10BMC_N3000_MAC_LOW 0x10 28 + #define M10BMC_N3000_MAC_BYTE4 GENMASK(7, 0) 29 + #define M10BMC_N3000_MAC_BYTE3 GENMASK(15, 8) 30 + #define M10BMC_N3000_MAC_BYTE2 GENMASK(23, 16) 31 + #define M10BMC_N3000_MAC_BYTE1 GENMASK(31, 24) 32 + #define M10BMC_N3000_MAC_HIGH 0x14 33 + #define M10BMC_N3000_MAC_BYTE6 GENMASK(7, 0) 34 + #define M10BMC_N3000_MAC_BYTE5 GENMASK(15, 8) 35 + #define M10BMC_N3000_MAC_COUNT GENMASK(23, 16) 36 + #define M10BMC_N3000_TEST_REG 0x3c 37 + #define M10BMC_N3000_BUILD_VER 0x68 38 + #define M10BMC_N3000_VER_MAJOR_MSK GENMASK(23, 16) 39 + #define M10BMC_N3000_VER_PCB_INFO_MSK GENMASK(31, 24) 40 + #define M10BMC_N3000_VER_LEGACY_INVALID 0xffffffff 38 41 39 42 /* Secure update doorbell register, in system register region */ 40 - #define M10BMC_DOORBELL 0x400 43 + #define M10BMC_N3000_DOORBELL 0x400 41 44 42 45 /* Authorization Result register, in system register region */ 43 - #define M10BMC_AUTH_RESULT 0x404 46 + #define M10BMC_N3000_AUTH_RESULT 0x404 44 47 45 48 /* Doorbell register fields */ 46 49 #define DRBL_RSU_REQUEST BIT(0) ··· 91 88 #define HOST_STATUS_ABORT_RSU 0x2 92 89 93 90 #define rsu_prog(doorbell) FIELD_GET(DRBL_RSU_PROGRESS, doorbell) 94 - #define rsu_stat(doorbell) FIELD_GET(DRBL_RSU_STATUS, doorbell) 95 91 96 92 /* interval 100ms and timeout 5s */ 97 93 #define NIOS_HANDSHAKE_INTERVAL_US (100 * 1000) ··· 105 103 #define RSU_COMPLETE_TIMEOUT_MS (40 * 60 * 1000) 106 104 107 105 /* Addresses for security related data in FLASH */ 108 - #define BMC_REH_ADDR 0x17ffc004 109 - #define BMC_PROG_ADDR 0x17ffc000 110 - #define BMC_PROG_MAGIC 0x5746 106 + #define M10BMC_N3000_BMC_REH_ADDR 0x17ffc004 107 + #define M10BMC_N3000_BMC_PROG_ADDR 0x17ffc000 108 + #define M10BMC_N3000_BMC_PROG_MAGIC 0x5746 111 109 112 - #define SR_REH_ADDR 0x17ffd004 113 - #define SR_PROG_ADDR 0x17ffd000 114 - #define SR_PROG_MAGIC 0x5253 110 + #define M10BMC_N3000_SR_REH_ADDR 0x17ffd004 111 + #define M10BMC_N3000_SR_PROG_ADDR 0x17ffd000 112 + #define M10BMC_N3000_SR_PROG_MAGIC 0x5253 115 113 116 - #define PR_REH_ADDR 0x17ffe004 117 - #define PR_PROG_ADDR 0x17ffe000 118 - #define PR_PROG_MAGIC 0x5250 114 + #define M10BMC_N3000_PR_REH_ADDR 0x17ffe004 115 + #define M10BMC_N3000_PR_PROG_ADDR 0x17ffe000 116 + #define M10BMC_N3000_PR_PROG_MAGIC 0x5250 119 117 120 118 /* Address of 4KB inverted bit vector containing staging area FLASH count */ 121 - #define STAGING_FLASH_COUNT 0x17ffb000 119 + #define M10BMC_N3000_STAGING_FLASH_COUNT 0x17ffb000 120 + 121 + #define M10BMC_N6000_INDIRECT_BASE 0x400 122 + 123 + #define M10BMC_N6000_SYS_BASE 0x0 124 + #define M10BMC_N6000_SYS_END 0xfff 125 + 126 + #define M10BMC_N6000_DOORBELL 0x1c0 127 + #define M10BMC_N6000_AUTH_RESULT 0x1c4 128 + #define AUTH_RESULT_RSU_STATUS GENMASK(23, 16) 129 + 130 + #define M10BMC_N6000_BUILD_VER 0x0 131 + #define NIOS2_N6000_FW_VERSION 0x4 132 + #define M10BMC_N6000_MAC_LOW 0x20 133 + #define M10BMC_N6000_MAC_HIGH (M10BMC_N6000_MAC_LOW + 4) 134 + 135 + /* Addresses for security related data in FLASH */ 136 + #define M10BMC_N6000_BMC_REH_ADDR 0x7ffc004 137 + #define M10BMC_N6000_BMC_PROG_ADDR 0x7ffc000 138 + #define M10BMC_N6000_BMC_PROG_MAGIC 0x5746 139 + 140 + #define M10BMC_N6000_SR_REH_ADDR 0x7ffd004 141 + #define M10BMC_N6000_SR_PROG_ADDR 0x7ffd000 142 + #define M10BMC_N6000_SR_PROG_MAGIC 0x5253 143 + 144 + #define M10BMC_N6000_PR_REH_ADDR 0x7ffe004 145 + #define M10BMC_N6000_PR_PROG_ADDR 0x7ffe000 146 + #define M10BMC_N6000_PR_PROG_MAGIC 0x5250 147 + 148 + #define M10BMC_N6000_STAGING_FLASH_COUNT 0x7ff5000 149 + 150 + #define M10BMC_N6000_FLASH_MUX_CTRL 0x1d0 151 + #define M10BMC_N6000_FLASH_MUX_SELECTION GENMASK(2, 0) 152 + #define M10BMC_N6000_FLASH_MUX_IDLE 0 153 + #define M10BMC_N6000_FLASH_MUX_NIOS 1 154 + #define M10BMC_N6000_FLASH_MUX_HOST 2 155 + #define M10BMC_N6000_FLASH_MUX_PFL 4 156 + #define get_flash_mux(mux) FIELD_GET(M10BMC_N6000_FLASH_MUX_SELECTION, mux) 157 + 158 + #define M10BMC_N6000_FLASH_NIOS_REQUEST BIT(4) 159 + #define M10BMC_N6000_FLASH_HOST_REQUEST BIT(5) 160 + 161 + #define M10BMC_N6000_FLASH_CTRL 0x40 162 + #define M10BMC_N6000_FLASH_WR_MODE BIT(0) 163 + #define M10BMC_N6000_FLASH_RD_MODE BIT(1) 164 + #define M10BMC_N6000_FLASH_BUSY BIT(2) 165 + #define M10BMC_N6000_FLASH_FIFO_SPACE GENMASK(13, 4) 166 + #define M10BMC_N6000_FLASH_READ_COUNT GENMASK(25, 16) 167 + 168 + #define M10BMC_N6000_FLASH_ADDR 0x44 169 + #define M10BMC_N6000_FLASH_FIFO 0x800 170 + #define M10BMC_N6000_READ_BLOCK_SIZE 0x800 171 + #define M10BMC_N6000_FIFO_MAX_BYTES 0x800 172 + #define M10BMC_N6000_FIFO_WORD_SIZE 4 173 + #define M10BMC_N6000_FIFO_MAX_WORDS (M10BMC_N6000_FIFO_MAX_BYTES / \ 174 + M10BMC_N6000_FIFO_WORD_SIZE) 175 + 176 + #define M10BMC_FLASH_INT_US 1 177 + #define M10BMC_FLASH_TIMEOUT_US 10000 178 + 179 + /** 180 + * struct m10bmc_csr_map - Intel MAX 10 BMC CSR register map 181 + */ 182 + struct m10bmc_csr_map { 183 + unsigned int base; 184 + unsigned int build_version; 185 + unsigned int fw_version; 186 + unsigned int mac_low; 187 + unsigned int mac_high; 188 + unsigned int doorbell; 189 + unsigned int auth_result; 190 + unsigned int bmc_prog_addr; 191 + unsigned int bmc_reh_addr; 192 + unsigned int bmc_magic; 193 + unsigned int sr_prog_addr; 194 + unsigned int sr_reh_addr; 195 + unsigned int sr_magic; 196 + unsigned int pr_prog_addr; 197 + unsigned int pr_reh_addr; 198 + unsigned int pr_magic; 199 + unsigned int rsu_update_counter; 200 + }; 201 + 202 + /** 203 + * struct intel_m10bmc_platform_info - Intel MAX 10 BMC platform specific information 204 + * @cells: MFD cells 205 + * @n_cells: MFD cells ARRAY_SIZE() 206 + * @csr_map: the mappings for register definition of MAX10 BMC 207 + */ 208 + struct intel_m10bmc_platform_info { 209 + struct mfd_cell *cells; 210 + int n_cells; 211 + const struct m10bmc_csr_map *csr_map; 212 + }; 213 + 214 + struct intel_m10bmc; 215 + 216 + /** 217 + * struct intel_m10bmc_flash_bulk_ops - device specific operations for flash R/W 218 + * @read: read a block of data from flash 219 + * @write: write a block of data to flash 220 + * @lock_write: locks flash access for erase+write 221 + * @unlock_write: unlock flash access 222 + * 223 + * Write must be protected with @lock_write and @unlock_write. While the flash 224 + * is locked, @read returns -EBUSY. 225 + */ 226 + struct intel_m10bmc_flash_bulk_ops { 227 + int (*read)(struct intel_m10bmc *m10bmc, u8 *buf, u32 addr, u32 size); 228 + int (*write)(struct intel_m10bmc *m10bmc, const u8 *buf, u32 offset, u32 size); 229 + int (*lock_write)(struct intel_m10bmc *m10bmc); 230 + void (*unlock_write)(struct intel_m10bmc *m10bmc); 231 + }; 122 232 123 233 /** 124 234 * struct intel_m10bmc - Intel MAX 10 BMC parent driver data structure 125 235 * @dev: this device 126 236 * @regmap: the regmap used to access registers by m10bmc itself 237 + * @info: the platform information for MAX10 BMC 238 + * @flash_bulk_ops: optional device specific operations for flash R/W 127 239 */ 128 240 struct intel_m10bmc { 129 241 struct device *dev; 130 242 struct regmap *regmap; 243 + const struct intel_m10bmc_platform_info *info; 244 + const struct intel_m10bmc_flash_bulk_ops *flash_bulk_ops; 131 245 }; 132 246 133 247 /* ··· 270 152 * The base of the system registers could be configured by HW developers, and 271 153 * in HW SPEC, the base is not added to the addresses of the system registers. 272 154 * 273 - * This macro helps to simplify the accessing of the system registers. And if 155 + * This function helps to simplify the accessing of the system registers. And if 274 156 * the base is reconfigured in HW, SW developers could simply change the 275 - * M10BMC_SYS_BASE accordingly. 157 + * csr_map's base accordingly. 276 158 */ 277 - #define m10bmc_sys_read(m10bmc, offset, val) \ 278 - m10bmc_raw_read(m10bmc, M10BMC_SYS_BASE + (offset), val) 159 + static inline int m10bmc_sys_read(struct intel_m10bmc *m10bmc, unsigned int offset, 160 + unsigned int *val) 161 + { 162 + const struct m10bmc_csr_map *csr_map = m10bmc->info->csr_map; 163 + 164 + return m10bmc_raw_read(m10bmc, csr_map->base + offset, val); 165 + } 166 + 167 + /* 168 + * MAX10 BMC Core support 169 + */ 170 + int m10bmc_dev_init(struct intel_m10bmc *m10bmc, const struct intel_m10bmc_platform_info *info); 171 + extern const struct attribute_group *m10bmc_dev_groups[]; 279 172 280 173 #endif /* __MFD_INTEL_M10_BMC_H */