1c3600e1fSPatrick Delaunay // SPDX-License-Identifier: GPL-2.0+ 2c3600e1fSPatrick Delaunay /* 3c3600e1fSPatrick Delaunay * Copyright (C) 2018, STMicroelectronics - All Rights Reserved 4c3600e1fSPatrick Delaunay */ 5c3600e1fSPatrick Delaunay 6c3600e1fSPatrick Delaunay #include <common.h> 7c3600e1fSPatrick Delaunay #include <command.h> 8c3600e1fSPatrick Delaunay #include <misc.h> 9c3600e1fSPatrick Delaunay #include <errno.h> 10c3600e1fSPatrick Delaunay #include <dm/device.h> 11c3600e1fSPatrick Delaunay #include <dm/uclass.h> 12c3600e1fSPatrick Delaunay 13c3600e1fSPatrick Delaunay #define STM32MP_OTP_BANK 0 14c3600e1fSPatrick Delaunay 15c3600e1fSPatrick Delaunay /* 16c3600e1fSPatrick Delaunay * The 'fuse' command API 17c3600e1fSPatrick Delaunay */ 18c3600e1fSPatrick Delaunay int fuse_read(u32 bank, u32 word, u32 *val) 19c3600e1fSPatrick Delaunay { 20c3600e1fSPatrick Delaunay int ret = 0; 21c3600e1fSPatrick Delaunay struct udevice *dev; 22c3600e1fSPatrick Delaunay 23c3600e1fSPatrick Delaunay switch (bank) { 24c3600e1fSPatrick Delaunay case STM32MP_OTP_BANK: 25c3600e1fSPatrick Delaunay ret = uclass_get_device_by_driver(UCLASS_MISC, 26c3600e1fSPatrick Delaunay DM_GET_DRIVER(stm32mp_bsec), 27c3600e1fSPatrick Delaunay &dev); 28c3600e1fSPatrick Delaunay if (ret) 29c3600e1fSPatrick Delaunay return ret; 30c3600e1fSPatrick Delaunay ret = misc_read(dev, word * 4 + STM32_BSEC_SHADOW_OFFSET, 31c3600e1fSPatrick Delaunay val, 4); 32*8729b1aeSSimon Glass if (ret < 0) 33*8729b1aeSSimon Glass return ret; 34*8729b1aeSSimon Glass ret = 0; 35c3600e1fSPatrick Delaunay break; 36c3600e1fSPatrick Delaunay 37c3600e1fSPatrick Delaunay default: 38c3600e1fSPatrick Delaunay printf("stm32mp %s: wrong value for bank %i\n", __func__, bank); 39c3600e1fSPatrick Delaunay ret = -EINVAL; 40c3600e1fSPatrick Delaunay break; 41c3600e1fSPatrick Delaunay } 42c3600e1fSPatrick Delaunay 43c3600e1fSPatrick Delaunay return ret; 44c3600e1fSPatrick Delaunay } 45c3600e1fSPatrick Delaunay 46c3600e1fSPatrick Delaunay int fuse_prog(u32 bank, u32 word, u32 val) 47c3600e1fSPatrick Delaunay { 48c3600e1fSPatrick Delaunay struct udevice *dev; 49c3600e1fSPatrick Delaunay int ret; 50c3600e1fSPatrick Delaunay 51c3600e1fSPatrick Delaunay switch (bank) { 52c3600e1fSPatrick Delaunay case STM32MP_OTP_BANK: 53c3600e1fSPatrick Delaunay ret = uclass_get_device_by_driver(UCLASS_MISC, 54c3600e1fSPatrick Delaunay DM_GET_DRIVER(stm32mp_bsec), 55c3600e1fSPatrick Delaunay &dev); 56c3600e1fSPatrick Delaunay if (ret) 57c3600e1fSPatrick Delaunay return ret; 58c3600e1fSPatrick Delaunay ret = misc_write(dev, word * 4 + STM32_BSEC_OTP_OFFSET, 59c3600e1fSPatrick Delaunay &val, 4); 60*8729b1aeSSimon Glass if (ret < 0) 61*8729b1aeSSimon Glass return ret; 62*8729b1aeSSimon Glass ret = 0; 63c3600e1fSPatrick Delaunay break; 64c3600e1fSPatrick Delaunay 65c3600e1fSPatrick Delaunay default: 66c3600e1fSPatrick Delaunay printf("stm32mp %s: wrong value for bank %i\n", __func__, bank); 67c3600e1fSPatrick Delaunay ret = -EINVAL; 68c3600e1fSPatrick Delaunay break; 69c3600e1fSPatrick Delaunay } 70c3600e1fSPatrick Delaunay 71c3600e1fSPatrick Delaunay return ret; 72c3600e1fSPatrick Delaunay } 73c3600e1fSPatrick Delaunay 74c3600e1fSPatrick Delaunay int fuse_sense(u32 bank, u32 word, u32 *val) 75c3600e1fSPatrick Delaunay { 76c3600e1fSPatrick Delaunay struct udevice *dev; 77c3600e1fSPatrick Delaunay int ret; 78c3600e1fSPatrick Delaunay 79c3600e1fSPatrick Delaunay switch (bank) { 80c3600e1fSPatrick Delaunay case STM32MP_OTP_BANK: 81c3600e1fSPatrick Delaunay ret = uclass_get_device_by_driver(UCLASS_MISC, 82c3600e1fSPatrick Delaunay DM_GET_DRIVER(stm32mp_bsec), 83c3600e1fSPatrick Delaunay &dev); 84c3600e1fSPatrick Delaunay if (ret) 85c3600e1fSPatrick Delaunay return ret; 86c3600e1fSPatrick Delaunay ret = misc_read(dev, word * 4 + STM32_BSEC_OTP_OFFSET, val, 4); 87*8729b1aeSSimon Glass if (ret < 0) 88*8729b1aeSSimon Glass return ret; 89*8729b1aeSSimon Glass ret = 0; 90c3600e1fSPatrick Delaunay break; 91c3600e1fSPatrick Delaunay 92c3600e1fSPatrick Delaunay default: 93c3600e1fSPatrick Delaunay printf("stm32mp %s: wrong value for bank %i\n", __func__, bank); 94c3600e1fSPatrick Delaunay ret = -EINVAL; 95c3600e1fSPatrick Delaunay break; 96c3600e1fSPatrick Delaunay } 97c3600e1fSPatrick Delaunay 98c3600e1fSPatrick Delaunay return ret; 99c3600e1fSPatrick Delaunay } 100c3600e1fSPatrick Delaunay 101c3600e1fSPatrick Delaunay int fuse_override(u32 bank, u32 word, u32 val) 102c3600e1fSPatrick Delaunay { 103c3600e1fSPatrick Delaunay struct udevice *dev; 104c3600e1fSPatrick Delaunay int ret; 105c3600e1fSPatrick Delaunay 106c3600e1fSPatrick Delaunay switch (bank) { 107c3600e1fSPatrick Delaunay case STM32MP_OTP_BANK: 108c3600e1fSPatrick Delaunay ret = uclass_get_device_by_driver(UCLASS_MISC, 109c3600e1fSPatrick Delaunay DM_GET_DRIVER(stm32mp_bsec), 110c3600e1fSPatrick Delaunay &dev); 111c3600e1fSPatrick Delaunay if (ret) 112c3600e1fSPatrick Delaunay return ret; 113c3600e1fSPatrick Delaunay ret = misc_write(dev, word * 4 + STM32_BSEC_SHADOW_OFFSET, 114c3600e1fSPatrick Delaunay &val, 4); 115*8729b1aeSSimon Glass if (ret < 0) 116*8729b1aeSSimon Glass return ret; 117*8729b1aeSSimon Glass ret = 0; 118c3600e1fSPatrick Delaunay break; 119c3600e1fSPatrick Delaunay 120c3600e1fSPatrick Delaunay default: 121c3600e1fSPatrick Delaunay printf("stm32mp %s: wrong value for bank %i\n", 122c3600e1fSPatrick Delaunay __func__, bank); 123c3600e1fSPatrick Delaunay ret = -EINVAL; 124c3600e1fSPatrick Delaunay break; 125c3600e1fSPatrick Delaunay } 126c3600e1fSPatrick Delaunay 127c3600e1fSPatrick Delaunay return ret; 128c3600e1fSPatrick Delaunay } 129