···246246247247config FPGA_M10_BMC_SEC_UPDATE248248 tristate "Intel MAX10 BMC Secure Update driver"249249- depends on MFD_INTEL_M10_BMC249249+ depends on MFD_INTEL_M10_BMC_CORE250250 select FW_LOADER251251 select FW_UPLOAD252252 help
+273-142
drivers/fpga/intel-m10-bmc-sec-update.c
···1414#include <linux/platform_device.h>1515#include <linux/slab.h>16161717+struct m10bmc_sec;1818+1919+struct m10bmc_sec_ops {2020+ int (*rsu_status)(struct m10bmc_sec *sec);2121+};2222+1723struct m10bmc_sec {1824 struct device *dev;1925 struct intel_m10bmc *m10bmc;···2721 char *fw_name;2822 u32 fw_name_id;2923 bool cancel_request;2424+ const struct m10bmc_sec_ops *ops;3025};31263227static DEFINE_XARRAY_ALLOC(fw_upload_xa);···3831#define REH_MAGIC GENMASK(15, 0)3932#define REH_SHA_NUM_BYTES GENMASK(31, 16)40333434+static int m10bmc_sec_write(struct m10bmc_sec *sec, const u8 *buf, u32 offset, u32 size)3535+{3636+ struct intel_m10bmc *m10bmc = sec->m10bmc;3737+ unsigned int stride = regmap_get_reg_stride(m10bmc->regmap);3838+ u32 write_count = size / stride;3939+ u32 leftover_offset = write_count * stride;4040+ u32 leftover_size = size - leftover_offset;4141+ u32 leftover_tmp = 0;4242+ int ret;4343+4444+ if (sec->m10bmc->flash_bulk_ops)4545+ return sec->m10bmc->flash_bulk_ops->write(m10bmc, buf, offset, size);4646+4747+ if (WARN_ON_ONCE(stride > sizeof(leftover_tmp)))4848+ return -EINVAL;4949+5050+ ret = regmap_bulk_write(m10bmc->regmap, M10BMC_STAGING_BASE + offset,5151+ buf + offset, write_count);5252+ if (ret)5353+ return ret;5454+5555+ /* If size is not aligned to stride, handle the remainder bytes with regmap_write() */5656+ if (leftover_size) {5757+ memcpy(&leftover_tmp, buf + leftover_offset, leftover_size);5858+ ret = regmap_write(m10bmc->regmap, M10BMC_STAGING_BASE + offset + leftover_offset,5959+ leftover_tmp);6060+ if (ret)6161+ return ret;6262+ }6363+6464+ return 0;6565+}6666+6767+static int m10bmc_sec_read(struct m10bmc_sec *sec, u8 *buf, u32 addr, u32 size)6868+{6969+ struct intel_m10bmc *m10bmc = sec->m10bmc;7070+ unsigned int stride = regmap_get_reg_stride(m10bmc->regmap);7171+ u32 read_count = size / stride;7272+ u32 leftover_offset = read_count * stride;7373+ u32 leftover_size = size - leftover_offset;7474+ u32 leftover_tmp;7575+ int ret;7676+7777+ if (sec->m10bmc->flash_bulk_ops)7878+ return sec->m10bmc->flash_bulk_ops->read(m10bmc, buf, addr, size);7979+8080+ if (WARN_ON_ONCE(stride > sizeof(leftover_tmp)))8181+ return -EINVAL;8282+8383+ ret = regmap_bulk_read(m10bmc->regmap, addr, buf, read_count);8484+ if (ret)8585+ return ret;8686+8787+ /* If size is not aligned to stride, handle the remainder bytes with regmap_read() */8888+ if (leftover_size) {8989+ ret = regmap_read(m10bmc->regmap, addr + leftover_offset, &leftover_tmp);9090+ if (ret)9191+ return ret;9292+ memcpy(buf + leftover_offset, &leftover_tmp, leftover_size);9393+ }9494+9595+ return 0;9696+}9797+9898+4199static ssize_t42100show_root_entry_hash(struct device *dev, u32 exp_magic,43101 u32 prog_addr, u32 reh_addr, char *buf)···11038 struct m10bmc_sec *sec = dev_get_drvdata(dev);11139 int sha_num_bytes, i, ret, cnt = 0;11240 u8 hash[REH_SHA384_SIZE];113113- unsigned int stride;11441 u32 magic;11542116116- stride = regmap_get_reg_stride(sec->m10bmc->regmap);117117- ret = m10bmc_raw_read(sec->m10bmc, prog_addr, &magic);4343+ ret = m10bmc_sec_read(sec, (u8 *)&magic, prog_addr, sizeof(magic));11844 if (ret)11945 return ret;12046···12050 return sysfs_emit(buf, "hash not programmed\n");1215112252 sha_num_bytes = FIELD_GET(REH_SHA_NUM_BYTES, magic) / 8;123123- if ((sha_num_bytes % stride) ||124124- (sha_num_bytes != REH_SHA256_SIZE &&125125- sha_num_bytes != REH_SHA384_SIZE)) {5353+ if (sha_num_bytes != REH_SHA256_SIZE &&5454+ sha_num_bytes != REH_SHA384_SIZE) {12655 dev_err(sec->dev, "%s bad sha num bytes %d\n", __func__,12756 sha_num_bytes);12857 return -EINVAL;12958 }13059131131- ret = regmap_bulk_read(sec->m10bmc->regmap, reh_addr,132132- hash, sha_num_bytes / stride);6060+ ret = m10bmc_sec_read(sec, hash, reh_addr, sha_num_bytes);13361 if (ret) {134134- dev_err(dev, "failed to read root entry hash: %x cnt %x: %d\n",135135- reh_addr, sha_num_bytes / stride, ret);6262+ dev_err(dev, "failed to read root entry hash\n");13663 return ret;13764 }13865···14073 return cnt;14174}14275143143-#define DEVICE_ATTR_SEC_REH_RO(_name, _magic, _prog_addr, _reh_addr) \7676+#define DEVICE_ATTR_SEC_REH_RO(_name) \14477static ssize_t _name##_root_entry_hash_show(struct device *dev, \14578 struct device_attribute *attr, \14679 char *buf) \147147-{ return show_root_entry_hash(dev, _magic, _prog_addr, _reh_addr, buf); } \8080+{ \8181+ struct m10bmc_sec *sec = dev_get_drvdata(dev); \8282+ const struct m10bmc_csr_map *csr_map = sec->m10bmc->info->csr_map; \8383+ \8484+ return show_root_entry_hash(dev, csr_map->_name##_magic, \8585+ csr_map->_name##_prog_addr, \8686+ csr_map->_name##_reh_addr, \8787+ buf); \8888+} \14889static DEVICE_ATTR_RO(_name##_root_entry_hash)14990150150-DEVICE_ATTR_SEC_REH_RO(bmc, BMC_PROG_MAGIC, BMC_PROG_ADDR, BMC_REH_ADDR);151151-DEVICE_ATTR_SEC_REH_RO(sr, SR_PROG_MAGIC, SR_PROG_ADDR, SR_REH_ADDR);152152-DEVICE_ATTR_SEC_REH_RO(pr, PR_PROG_MAGIC, PR_PROG_ADDR, PR_REH_ADDR);9191+DEVICE_ATTR_SEC_REH_RO(bmc);9292+DEVICE_ATTR_SEC_REH_RO(sr);9393+DEVICE_ATTR_SEC_REH_RO(pr);1539415495#define CSK_BIT_LEN 128U15596#define CSK_32ARRAY_SIZE DIV_ROUND_UP(CSK_BIT_LEN, 32)···16590static ssize_t16691show_canceled_csk(struct device *dev, u32 addr, char *buf)16792{168168- unsigned int i, stride, size = CSK_32ARRAY_SIZE * sizeof(u32);9393+ unsigned int i, size = CSK_32ARRAY_SIZE * sizeof(u32);16994 struct m10bmc_sec *sec = dev_get_drvdata(dev);17095 DECLARE_BITMAP(csk_map, CSK_BIT_LEN);17196 __le32 csk_le32[CSK_32ARRAY_SIZE];17297 u32 csk32[CSK_32ARRAY_SIZE];17398 int ret;17499175175- stride = regmap_get_reg_stride(sec->m10bmc->regmap);176176- if (size % stride) {177177- dev_err(sec->dev,178178- "CSK vector size (0x%x) not aligned to stride (0x%x)\n",179179- size, stride);180180- WARN_ON_ONCE(1);181181- return -EINVAL;182182- }183183-184184- ret = regmap_bulk_read(sec->m10bmc->regmap, addr, csk_le32,185185- size / stride);100100+ ret = m10bmc_sec_read(sec, (u8 *)&csk_le32, addr, size);186101 if (ret) {187187- dev_err(sec->dev, "failed to read CSK vector: %x cnt %x: %d\n",188188- addr, size / stride, ret);102102+ dev_err(sec->dev, "failed to read CSK vector\n");189103 return ret;190104 }191105···186122 return bitmap_print_to_pagebuf(1, buf, csk_map, CSK_BIT_LEN);187123}188124189189-#define DEVICE_ATTR_SEC_CSK_RO(_name, _addr) \125125+#define DEVICE_ATTR_SEC_CSK_RO(_name) \190126static ssize_t _name##_canceled_csks_show(struct device *dev, \191127 struct device_attribute *attr, \192128 char *buf) \193193-{ return show_canceled_csk(dev, _addr, buf); } \129129+{ \130130+ struct m10bmc_sec *sec = dev_get_drvdata(dev); \131131+ const struct m10bmc_csr_map *csr_map = sec->m10bmc->info->csr_map; \132132+ \133133+ return show_canceled_csk(dev, \134134+ csr_map->_name##_prog_addr + CSK_VEC_OFFSET, \135135+ buf); \136136+} \194137static DEVICE_ATTR_RO(_name##_canceled_csks)195138196139#define CSK_VEC_OFFSET 0x34197140198198-DEVICE_ATTR_SEC_CSK_RO(bmc, BMC_PROG_ADDR + CSK_VEC_OFFSET);199199-DEVICE_ATTR_SEC_CSK_RO(sr, SR_PROG_ADDR + CSK_VEC_OFFSET);200200-DEVICE_ATTR_SEC_CSK_RO(pr, PR_PROG_ADDR + CSK_VEC_OFFSET);141141+DEVICE_ATTR_SEC_CSK_RO(bmc);142142+DEVICE_ATTR_SEC_CSK_RO(sr);143143+DEVICE_ATTR_SEC_CSK_RO(pr);201144202145#define FLASH_COUNT_SIZE 4096 /* count stored as inverted bit vector */203146···212141 struct device_attribute *attr, char *buf)213142{214143 struct m10bmc_sec *sec = dev_get_drvdata(dev);215215- unsigned int stride, num_bits;144144+ const struct m10bmc_csr_map *csr_map = sec->m10bmc->info->csr_map;145145+ unsigned int num_bits;216146 u8 *flash_buf;217147 int cnt, ret;218148219219- stride = regmap_get_reg_stride(sec->m10bmc->regmap);220149 num_bits = FLASH_COUNT_SIZE * 8;221221-222222- if (FLASH_COUNT_SIZE % stride) {223223- dev_err(sec->dev,224224- "FLASH_COUNT_SIZE (0x%x) not aligned to stride (0x%x)\n",225225- FLASH_COUNT_SIZE, stride);226226- WARN_ON_ONCE(1);227227- return -EINVAL;228228- }229150230151 flash_buf = kmalloc(FLASH_COUNT_SIZE, GFP_KERNEL);231152 if (!flash_buf)232153 return -ENOMEM;233154234234- ret = regmap_bulk_read(sec->m10bmc->regmap, STAGING_FLASH_COUNT,235235- flash_buf, FLASH_COUNT_SIZE / stride);155155+ ret = m10bmc_sec_read(sec, flash_buf, csr_map->rsu_update_counter,156156+ FLASH_COUNT_SIZE);236157 if (ret) {237237- dev_err(sec->dev,238238- "failed to read flash count: %x cnt %x: %d\n",239239- STAGING_FLASH_COUNT, FLASH_COUNT_SIZE / stride, ret);158158+ dev_err(sec->dev, "failed to read flash count\n");240159 goto exit_free;241160 }242161 cnt = num_bits - bitmap_weight((unsigned long *)flash_buf, num_bits);···261200262201static void log_error_regs(struct m10bmc_sec *sec, u32 doorbell)263202{203203+ const struct m10bmc_csr_map *csr_map = sec->m10bmc->info->csr_map;264204 u32 auth_result;265205266266- dev_err(sec->dev, "RSU error status: 0x%08x\n", doorbell);206206+ dev_err(sec->dev, "Doorbell: 0x%08x\n", doorbell);267207268268- if (!m10bmc_sys_read(sec->m10bmc, M10BMC_AUTH_RESULT, &auth_result))208208+ if (!m10bmc_sys_read(sec->m10bmc, csr_map->auth_result, &auth_result))269209 dev_err(sec->dev, "RSU auth result: 0x%08x\n", auth_result);210210+}211211+212212+static int m10bmc_sec_n3000_rsu_status(struct m10bmc_sec *sec)213213+{214214+ const struct m10bmc_csr_map *csr_map = sec->m10bmc->info->csr_map;215215+ u32 doorbell;216216+ int ret;217217+218218+ ret = m10bmc_sys_read(sec->m10bmc, csr_map->doorbell, &doorbell);219219+ if (ret)220220+ return ret;221221+222222+ return FIELD_GET(DRBL_RSU_STATUS, doorbell);223223+}224224+225225+static int m10bmc_sec_n6000_rsu_status(struct m10bmc_sec *sec)226226+{227227+ const struct m10bmc_csr_map *csr_map = sec->m10bmc->info->csr_map;228228+ u32 auth_result;229229+ int ret;230230+231231+ ret = m10bmc_sys_read(sec->m10bmc, csr_map->auth_result, &auth_result);232232+ if (ret)233233+ return ret;234234+235235+ return FIELD_GET(AUTH_RESULT_RSU_STATUS, auth_result);236236+}237237+238238+static bool rsu_status_ok(u32 status)239239+{240240+ return (status == RSU_STAT_NORMAL ||241241+ status == RSU_STAT_NIOS_OK ||242242+ status == RSU_STAT_USER_OK ||243243+ status == RSU_STAT_FACTORY_OK);244244+}245245+246246+static bool rsu_progress_done(u32 progress)247247+{248248+ return (progress == RSU_PROG_IDLE ||249249+ progress == RSU_PROG_RSU_DONE);250250+}251251+252252+static bool rsu_progress_busy(u32 progress)253253+{254254+ return (progress == RSU_PROG_AUTHENTICATING ||255255+ progress == RSU_PROG_COPYING ||256256+ progress == RSU_PROG_UPDATE_CANCEL ||257257+ progress == RSU_PROG_PROGRAM_KEY_HASH);258258+}259259+260260+static int m10bmc_sec_progress_status(struct m10bmc_sec *sec, u32 *doorbell_reg,261261+ u32 *progress, u32 *status)262262+{263263+ const struct m10bmc_csr_map *csr_map = sec->m10bmc->info->csr_map;264264+ int ret;265265+266266+ ret = m10bmc_sys_read(sec->m10bmc, csr_map->doorbell, doorbell_reg);267267+ if (ret)268268+ return ret;269269+270270+ ret = sec->ops->rsu_status(sec);271271+ if (ret < 0)272272+ return ret;273273+274274+ *status = ret;275275+ *progress = rsu_prog(*doorbell_reg);276276+277277+ return 0;270278}271279272280static enum fw_upload_err rsu_check_idle(struct m10bmc_sec *sec)273281{282282+ const struct m10bmc_csr_map *csr_map = sec->m10bmc->info->csr_map;274283 u32 doorbell;275284 int ret;276285277277- ret = m10bmc_sys_read(sec->m10bmc, M10BMC_DOORBELL, &doorbell);286286+ ret = m10bmc_sys_read(sec->m10bmc, csr_map->doorbell, &doorbell);278287 if (ret)279288 return FW_UPLOAD_ERR_RW_ERROR;280289281281- if (rsu_prog(doorbell) != RSU_PROG_IDLE &&282282- rsu_prog(doorbell) != RSU_PROG_RSU_DONE) {290290+ if (!rsu_progress_done(rsu_prog(doorbell))) {283291 log_error_regs(sec, doorbell);284292 return FW_UPLOAD_ERR_BUSY;285293 }···356226 return FW_UPLOAD_ERR_NONE;357227}358228359359-static inline bool rsu_start_done(u32 doorbell)229229+static inline bool rsu_start_done(u32 doorbell_reg, u32 progress, u32 status)360230{361361- u32 status, progress;362362-363363- if (doorbell & DRBL_RSU_REQUEST)231231+ if (doorbell_reg & DRBL_RSU_REQUEST)364232 return false;365233366366- status = rsu_stat(doorbell);367234 if (status == RSU_STAT_ERASE_FAIL || status == RSU_STAT_WEAROUT)368235 return true;369236370370- progress = rsu_prog(doorbell);371371- if (progress != RSU_PROG_IDLE && progress != RSU_PROG_RSU_DONE)237237+ if (!rsu_progress_done(progress))372238 return true;373239374240 return false;···372246373247static enum fw_upload_err rsu_update_init(struct m10bmc_sec *sec)374248{375375- u32 doorbell, status;376376- int ret;249249+ const struct m10bmc_csr_map *csr_map = sec->m10bmc->info->csr_map;250250+ u32 doorbell_reg, progress, status;251251+ int ret, err;377252378253 ret = regmap_update_bits(sec->m10bmc->regmap,379379- M10BMC_SYS_BASE + M10BMC_DOORBELL,254254+ csr_map->base + csr_map->doorbell,380255 DRBL_RSU_REQUEST | DRBL_HOST_STATUS,381256 DRBL_RSU_REQUEST |382257 FIELD_PREP(DRBL_HOST_STATUS,···385258 if (ret)386259 return FW_UPLOAD_ERR_RW_ERROR;387260388388- ret = regmap_read_poll_timeout(sec->m10bmc->regmap,389389- M10BMC_SYS_BASE + M10BMC_DOORBELL,390390- doorbell,391391- rsu_start_done(doorbell),392392- NIOS_HANDSHAKE_INTERVAL_US,393393- NIOS_HANDSHAKE_TIMEOUT_US);261261+ ret = read_poll_timeout(m10bmc_sec_progress_status, err,262262+ err < 0 || rsu_start_done(doorbell_reg, progress, status),263263+ NIOS_HANDSHAKE_INTERVAL_US,264264+ NIOS_HANDSHAKE_TIMEOUT_US,265265+ false,266266+ sec, &doorbell_reg, &progress, &status);394267395268 if (ret == -ETIMEDOUT) {396396- log_error_regs(sec, doorbell);269269+ log_error_regs(sec, doorbell_reg);397270 return FW_UPLOAD_ERR_TIMEOUT;398398- } else if (ret) {271271+ } else if (err) {399272 return FW_UPLOAD_ERR_RW_ERROR;400273 }401274402402- status = rsu_stat(doorbell);403275 if (status == RSU_STAT_WEAROUT) {404276 dev_warn(sec->dev, "Excessive flash update count detected\n");405277 return FW_UPLOAD_ERR_WEAROUT;406278 } else if (status == RSU_STAT_ERASE_FAIL) {407407- log_error_regs(sec, doorbell);279279+ log_error_regs(sec, doorbell_reg);408280 return FW_UPLOAD_ERR_HW_ERROR;409281 }410282···412286413287static enum fw_upload_err rsu_prog_ready(struct m10bmc_sec *sec)414288{289289+ const struct m10bmc_csr_map *csr_map = sec->m10bmc->info->csr_map;415290 unsigned long poll_timeout;416291 u32 doorbell, progress;417292 int ret;418293419419- ret = m10bmc_sys_read(sec->m10bmc, M10BMC_DOORBELL, &doorbell);294294+ ret = m10bmc_sys_read(sec->m10bmc, csr_map->doorbell, &doorbell);420295 if (ret)421296 return FW_UPLOAD_ERR_RW_ERROR;422297···427300 if (time_after(jiffies, poll_timeout))428301 break;429302430430- ret = m10bmc_sys_read(sec->m10bmc, M10BMC_DOORBELL, &doorbell);303303+ ret = m10bmc_sys_read(sec->m10bmc, csr_map->doorbell, &doorbell);431304 if (ret)432305 return FW_UPLOAD_ERR_RW_ERROR;433306 }···446319447320static enum fw_upload_err rsu_send_data(struct m10bmc_sec *sec)448321{449449- u32 doorbell;322322+ const struct m10bmc_csr_map *csr_map = sec->m10bmc->info->csr_map;323323+ u32 doorbell_reg, status;450324 int ret;451325452326 ret = regmap_update_bits(sec->m10bmc->regmap,453453- M10BMC_SYS_BASE + M10BMC_DOORBELL,327327+ csr_map->base + csr_map->doorbell,454328 DRBL_HOST_STATUS,455329 FIELD_PREP(DRBL_HOST_STATUS,456330 HOST_STATUS_WRITE_DONE));···459331 return FW_UPLOAD_ERR_RW_ERROR;460332461333 ret = regmap_read_poll_timeout(sec->m10bmc->regmap,462462- M10BMC_SYS_BASE + M10BMC_DOORBELL,463463- doorbell,464464- rsu_prog(doorbell) != RSU_PROG_READY,334334+ csr_map->base + csr_map->doorbell,335335+ doorbell_reg,336336+ rsu_prog(doorbell_reg) != RSU_PROG_READY,465337 NIOS_HANDSHAKE_INTERVAL_US,466338 NIOS_HANDSHAKE_TIMEOUT_US);467339468340 if (ret == -ETIMEDOUT) {469469- log_error_regs(sec, doorbell);341341+ log_error_regs(sec, doorbell_reg);470342 return FW_UPLOAD_ERR_TIMEOUT;471343 } else if (ret) {472344 return FW_UPLOAD_ERR_RW_ERROR;473345 }474346475475- switch (rsu_stat(doorbell)) {476476- case RSU_STAT_NORMAL:477477- case RSU_STAT_NIOS_OK:478478- case RSU_STAT_USER_OK:479479- case RSU_STAT_FACTORY_OK:480480- break;481481- default:482482- log_error_regs(sec, doorbell);347347+ ret = sec->ops->rsu_status(sec);348348+ if (ret < 0)349349+ return ret;350350+ status = ret;351351+352352+ if (!rsu_status_ok(status)) {353353+ log_error_regs(sec, doorbell_reg);483354 return FW_UPLOAD_ERR_HW_ERROR;484355 }485356486357 return FW_UPLOAD_ERR_NONE;487358}488359489489-static int rsu_check_complete(struct m10bmc_sec *sec, u32 *doorbell)360360+static int rsu_check_complete(struct m10bmc_sec *sec, u32 *doorbell_reg)490361{491491- if (m10bmc_sys_read(sec->m10bmc, M10BMC_DOORBELL, doorbell))362362+ u32 progress, status;363363+364364+ if (m10bmc_sec_progress_status(sec, doorbell_reg, &progress, &status))492365 return -EIO;493366494494- switch (rsu_stat(*doorbell)) {495495- case RSU_STAT_NORMAL:496496- case RSU_STAT_NIOS_OK:497497- case RSU_STAT_USER_OK:498498- case RSU_STAT_FACTORY_OK:499499- break;500500- default:367367+ if (!rsu_status_ok(status))501368 return -EINVAL;502502- }503369504504- switch (rsu_prog(*doorbell)) {505505- case RSU_PROG_IDLE:506506- case RSU_PROG_RSU_DONE:370370+ if (rsu_progress_done(progress))507371 return 0;508508- case RSU_PROG_AUTHENTICATING:509509- case RSU_PROG_COPYING:510510- case RSU_PROG_UPDATE_CANCEL:511511- case RSU_PROG_PROGRAM_KEY_HASH:372372+373373+ if (rsu_progress_busy(progress))512374 return -EAGAIN;513513- default:514514- return -EINVAL;515515- }375375+376376+ return -EINVAL;516377}517378518379static enum fw_upload_err rsu_cancel(struct m10bmc_sec *sec)519380{381381+ const struct m10bmc_csr_map *csr_map = sec->m10bmc->info->csr_map;520382 u32 doorbell;521383 int ret;522384523523- ret = m10bmc_sys_read(sec->m10bmc, M10BMC_DOORBELL, &doorbell);385385+ ret = m10bmc_sys_read(sec->m10bmc, csr_map->doorbell, &doorbell);524386 if (ret)525387 return FW_UPLOAD_ERR_RW_ERROR;526388···518400 return FW_UPLOAD_ERR_BUSY;519401520402 ret = regmap_update_bits(sec->m10bmc->regmap,521521- M10BMC_SYS_BASE + M10BMC_DOORBELL,403403+ csr_map->base + csr_map->doorbell,522404 DRBL_HOST_STATUS,523405 FIELD_PREP(DRBL_HOST_STATUS,524406 HOST_STATUS_ABORT_RSU));···539421 if (!size || size > M10BMC_STAGING_SIZE)540422 return FW_UPLOAD_ERR_INVALID_SIZE;541423424424+ if (sec->m10bmc->flash_bulk_ops)425425+ if (sec->m10bmc->flash_bulk_ops->lock_write(sec->m10bmc))426426+ return FW_UPLOAD_ERR_BUSY;427427+542428 ret = rsu_check_idle(sec);543429 if (ret != FW_UPLOAD_ERR_NONE)544544- return ret;430430+ goto unlock_flash;545431546432 ret = rsu_update_init(sec);547433 if (ret != FW_UPLOAD_ERR_NONE)548548- return ret;434434+ goto unlock_flash;549435550436 ret = rsu_prog_ready(sec);551437 if (ret != FW_UPLOAD_ERR_NONE)552552- return ret;438438+ goto unlock_flash;553439554554- if (sec->cancel_request)555555- return rsu_cancel(sec);440440+ if (sec->cancel_request) {441441+ ret = rsu_cancel(sec);442442+ goto unlock_flash;443443+ }556444557445 return FW_UPLOAD_ERR_NONE;446446+447447+unlock_flash:448448+ if (sec->m10bmc->flash_bulk_ops)449449+ sec->m10bmc->flash_bulk_ops->unlock_write(sec->m10bmc);450450+ return ret;558451}559452560453#define WRITE_BLOCK_SIZE 0x4000 /* Default write-block size is 0x4000 bytes */561454562562-static enum fw_upload_err m10bmc_sec_write(struct fw_upload *fwl, const u8 *data,563563- u32 offset, u32 size, u32 *written)455455+static enum fw_upload_err m10bmc_sec_fw_write(struct fw_upload *fwl, const u8 *data,456456+ u32 offset, u32 size, u32 *written)564457{565458 struct m10bmc_sec *sec = fwl->dd_handle;566566- u32 blk_size, doorbell, extra_offset;567567- unsigned int stride, extra = 0;459459+ const struct m10bmc_csr_map *csr_map = sec->m10bmc->info->csr_map;460460+ struct intel_m10bmc *m10bmc = sec->m10bmc;461461+ u32 blk_size, doorbell;568462 int ret;569463570570- stride = regmap_get_reg_stride(sec->m10bmc->regmap);571464 if (sec->cancel_request)572465 return rsu_cancel(sec);573466574574- ret = m10bmc_sys_read(sec->m10bmc, M10BMC_DOORBELL, &doorbell);467467+ ret = m10bmc_sys_read(m10bmc, csr_map->doorbell, &doorbell);575468 if (ret) {576469 return FW_UPLOAD_ERR_RW_ERROR;577470 } else if (rsu_prog(doorbell) != RSU_PROG_READY) {···590461 return FW_UPLOAD_ERR_HW_ERROR;591462 }592463593593- WARN_ON_ONCE(WRITE_BLOCK_SIZE % stride);464464+ WARN_ON_ONCE(WRITE_BLOCK_SIZE % regmap_get_reg_stride(m10bmc->regmap));594465 blk_size = min_t(u32, WRITE_BLOCK_SIZE, size);595595- ret = regmap_bulk_write(sec->m10bmc->regmap,596596- M10BMC_STAGING_BASE + offset,597597- (void *)data + offset,598598- blk_size / stride);466466+ ret = m10bmc_sec_write(sec, data, offset, blk_size);599467 if (ret)600468 return FW_UPLOAD_ERR_RW_ERROR;601601-602602- /*603603- * If blk_size is not aligned to stride, then handle the extra604604- * bytes with regmap_write.605605- */606606- if (blk_size % stride) {607607- extra_offset = offset + ALIGN_DOWN(blk_size, stride);608608- memcpy(&extra, (u8 *)(data + extra_offset), blk_size % stride);609609- ret = regmap_write(sec->m10bmc->regmap,610610- M10BMC_STAGING_BASE + extra_offset, extra);611611- if (ret)612612- return FW_UPLOAD_ERR_RW_ERROR;613613- }614469615470 *written = blk_size;616471 return FW_UPLOAD_ERR_NONE;···652539 struct m10bmc_sec *sec = fwl->dd_handle;653540654541 (void)rsu_cancel(sec);542542+543543+ if (sec->m10bmc->flash_bulk_ops)544544+ sec->m10bmc->flash_bulk_ops->unlock_write(sec->m10bmc);655545}656546657547static const struct fw_upload_ops m10bmc_ops = {658548 .prepare = m10bmc_sec_prepare,659659- .write = m10bmc_sec_write,549549+ .write = m10bmc_sec_fw_write,660550 .poll_complete = m10bmc_sec_poll_complete,661551 .cancel = m10bmc_sec_cancel,662552 .cleanup = m10bmc_sec_cleanup,553553+};554554+555555+static const struct m10bmc_sec_ops m10sec_n3000_ops = {556556+ .rsu_status = m10bmc_sec_n3000_rsu_status,557557+};558558+559559+static const struct m10bmc_sec_ops m10sec_n6000_ops = {560560+ .rsu_status = m10bmc_sec_n6000_rsu_status,663561};664562665563#define SEC_UPDATE_LEN_MAX 32···688564689565 sec->dev = &pdev->dev;690566 sec->m10bmc = dev_get_drvdata(pdev->dev.parent);567567+ sec->ops = (struct m10bmc_sec_ops *)platform_get_device_id(pdev)->driver_data;691568 dev_set_drvdata(&pdev->dev, sec);692569693570 ret = xa_alloc(&fw_upload_xa, &sec->fw_name_id, sec,···729604static const struct platform_device_id intel_m10bmc_sec_ids[] = {730605 {731606 .name = "n3000bmc-sec-update",607607+ .driver_data = (kernel_ulong_t)&m10sec_n3000_ops,732608 },733609 {734610 .name = "d5005bmc-sec-update",611611+ .driver_data = (kernel_ulong_t)&m10sec_n3000_ops,612612+ },613613+ {614614+ .name = "n6000bmc-sec-update",615615+ .driver_data = (kernel_ulong_t)&m10sec_n6000_ops,735616 },736617 { }737618};
+1-1
drivers/hwmon/Kconfig
···2341234123422342config SENSORS_INTEL_M10_BMC_HWMON23432343 tristate "Intel MAX10 BMC Hardware Monitoring"23442344- depends on MFD_INTEL_M10_BMC23442344+ depends on MFD_INTEL_M10_BMC_CORE23452345 help23462346 This driver provides support for the hardware monitoring functionality23472347 on Intel MAX10 BMC chip.
+25-7
drivers/mfd/Kconfig
···22242224 If you have an SGI Origin, Octane, or a PCI IOC3 card,22252225 then say Y. Otherwise say N.2226222622272227-config MFD_INTEL_M10_BMC22282228- tristate "Intel MAX 10 Board Management Controller"22292229- depends on SPI_MASTER22302230- select REGMAP_SPI_AVMM22312231- select MFD_CORE22272227+config MFD_INTEL_M10_BMC_CORE22282228+ tristate22292229+ select MFD_CORE22302230+ select REGMAP22312231+ default n22322232+22332233+config MFD_INTEL_M10_BMC_SPI22342234+ tristate "Intel MAX 10 Board Management Controller with SPI"22352235+ depends on SPI_MASTER22362236+ select MFD_INTEL_M10_BMC_CORE22372237+ select REGMAP_SPI_AVMM22382238+ help22392239+ Support for the Intel MAX 10 board management controller using the22402240+ SPI interface.22412241+22422242+ This driver provides common support for accessing the device,22432243+ additional drivers must be enabled in order to use the functionality22442244+ of the device.22452245+22462246+config MFD_INTEL_M10_BMC_PMCI22472247+ tristate "Intel MAX 10 Board Management Controller with PMCI"22482248+ depends on FPGA_DFL22492249+ select MFD_INTEL_M10_BMC_CORE22502250+ select REGMAP22322251 help22332233- Support for the Intel MAX 10 board management controller using the22342234- SPI interface.22522252+ Support for the Intel MAX 10 board management controller via PMCI.2235225322362254 This driver provides common support for accessing the device,22372255 additional drivers must be enabled in order to use the functionality