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

firmware: meson_sm: Rework driver as a proper platform driver

The secure monitor driver is currently a frankenstein driver which is
registered as a platform driver but its functionality goes through a
global struct accessed by the consumer drivers using exported helper
functions.

Try to tidy up the driver moving the firmware struct into the driver
data and make the consumer drivers referencing the secure-monitor using
a new property in the DT.

Currently only the nvmem driver is using this API so we can fix it in
the same commit.

Reviewed-by: Jerome Brunet <jbrunet@baylibre.com>
Signed-off-by: Carlo Caione <ccaione@baylibre.com>
Signed-off-by: Kevin Hilman <khilman@baylibre.com>

authored by

Carlo Caione and committed by
Kevin Hilman
8cde3c21 47b3c53a

+94 -39
+64 -30
drivers/firmware/meson/meson_sm.c
··· 54 54 void __iomem *sm_shmem_out_base; 55 55 }; 56 56 57 - static struct meson_sm_firmware fw; 58 - 59 57 static u32 meson_sm_get_cmd(const struct meson_sm_chip *chip, 60 58 unsigned int cmd_index) 61 59 { ··· 88 90 /** 89 91 * meson_sm_call - generic SMC32 call to the secure-monitor 90 92 * 93 + * @fw: Pointer to secure-monitor firmware 91 94 * @cmd_index: Index of the SMC32 function ID 92 95 * @ret: Returned value 93 96 * @arg0: SMC32 Argument 0 ··· 99 100 * 100 101 * Return: 0 on success, a negative value on error 101 102 */ 102 - int meson_sm_call(unsigned int cmd_index, u32 *ret, u32 arg0, 103 - u32 arg1, u32 arg2, u32 arg3, u32 arg4) 103 + int meson_sm_call(struct meson_sm_firmware *fw, unsigned int cmd_index, 104 + u32 *ret, u32 arg0, u32 arg1, u32 arg2, u32 arg3, u32 arg4) 104 105 { 105 106 u32 cmd, lret; 106 107 107 - if (!fw.chip) 108 + if (!fw->chip) 108 109 return -ENOENT; 109 110 110 - cmd = meson_sm_get_cmd(fw.chip, cmd_index); 111 + cmd = meson_sm_get_cmd(fw->chip, cmd_index); 111 112 if (!cmd) 112 113 return -EINVAL; 113 114 ··· 123 124 /** 124 125 * meson_sm_call_read - retrieve data from secure-monitor 125 126 * 127 + * @fw: Pointer to secure-monitor firmware 126 128 * @buffer: Buffer to store the retrieved data 127 129 * @bsize: Size of the buffer 128 130 * @cmd_index: Index of the SMC32 function ID ··· 137 137 * When 0 is returned there is no guarantee about the amount of 138 138 * data read and bsize bytes are copied in buffer. 139 139 */ 140 - int meson_sm_call_read(void *buffer, unsigned int bsize, unsigned int cmd_index, 141 - u32 arg0, u32 arg1, u32 arg2, u32 arg3, u32 arg4) 140 + int meson_sm_call_read(struct meson_sm_firmware *fw, void *buffer, 141 + unsigned int bsize, unsigned int cmd_index, u32 arg0, 142 + u32 arg1, u32 arg2, u32 arg3, u32 arg4) 142 143 { 143 144 u32 size; 144 145 int ret; 145 146 146 - if (!fw.chip) 147 + if (!fw->chip) 147 148 return -ENOENT; 148 149 149 - if (!fw.chip->cmd_shmem_out_base) 150 + if (!fw->chip->cmd_shmem_out_base) 150 151 return -EINVAL; 151 152 152 - if (bsize > fw.chip->shmem_size) 153 + if (bsize > fw->chip->shmem_size) 153 154 return -EINVAL; 154 155 155 - if (meson_sm_call(cmd_index, &size, arg0, arg1, arg2, arg3, arg4) < 0) 156 + if (meson_sm_call(fw, cmd_index, &size, arg0, arg1, arg2, arg3, arg4) < 0) 156 157 return -EINVAL; 157 158 158 159 if (size > bsize) ··· 165 164 size = bsize; 166 165 167 166 if (buffer) 168 - memcpy(buffer, fw.sm_shmem_out_base, size); 167 + memcpy(buffer, fw->sm_shmem_out_base, size); 169 168 170 169 return ret; 171 170 } ··· 174 173 /** 175 174 * meson_sm_call_write - send data to secure-monitor 176 175 * 176 + * @fw: Pointer to secure-monitor firmware 177 177 * @buffer: Buffer containing data to send 178 178 * @size: Size of the data to send 179 179 * @cmd_index: Index of the SMC32 function ID ··· 186 184 * 187 185 * Return: size of sent data on success, a negative value on error 188 186 */ 189 - int meson_sm_call_write(void *buffer, unsigned int size, unsigned int cmd_index, 190 - u32 arg0, u32 arg1, u32 arg2, u32 arg3, u32 arg4) 187 + int meson_sm_call_write(struct meson_sm_firmware *fw, void *buffer, 188 + unsigned int size, unsigned int cmd_index, u32 arg0, 189 + u32 arg1, u32 arg2, u32 arg3, u32 arg4) 191 190 { 192 191 u32 written; 193 192 194 - if (!fw.chip) 193 + if (!fw->chip) 195 194 return -ENOENT; 196 195 197 - if (size > fw.chip->shmem_size) 196 + if (size > fw->chip->shmem_size) 198 197 return -EINVAL; 199 198 200 - if (!fw.chip->cmd_shmem_in_base) 199 + if (!fw->chip->cmd_shmem_in_base) 201 200 return -EINVAL; 202 201 203 - memcpy(fw.sm_shmem_in_base, buffer, size); 202 + memcpy(fw->sm_shmem_in_base, buffer, size); 204 203 205 - if (meson_sm_call(cmd_index, &written, arg0, arg1, arg2, arg3, arg4) < 0) 204 + if (meson_sm_call(fw, cmd_index, &written, arg0, arg1, arg2, arg3, arg4) < 0) 206 205 return -EINVAL; 207 206 208 207 if (!written) ··· 213 210 } 214 211 EXPORT_SYMBOL(meson_sm_call_write); 215 212 213 + /** 214 + * meson_sm_get - get pointer to meson_sm_firmware structure. 215 + * 216 + * @sm_node: Pointer to the secure-monitor Device Tree node. 217 + * 218 + * Return: NULL is the secure-monitor device is not ready. 219 + */ 220 + struct meson_sm_firmware *meson_sm_get(struct device_node *sm_node) 221 + { 222 + struct platform_device *pdev = of_find_device_by_node(sm_node); 223 + 224 + if (!pdev) 225 + return NULL; 226 + 227 + return platform_get_drvdata(pdev); 228 + } 229 + EXPORT_SYMBOL_GPL(meson_sm_get); 230 + 216 231 #define SM_CHIP_ID_LENGTH 119 217 232 #define SM_CHIP_ID_OFFSET 4 218 233 #define SM_CHIP_ID_SIZE 12 ··· 238 217 static ssize_t serial_show(struct device *dev, struct device_attribute *attr, 239 218 char *buf) 240 219 { 220 + struct platform_device *pdev = to_platform_device(dev); 221 + struct meson_sm_firmware *fw; 241 222 uint8_t *id_buf; 242 223 int ret; 224 + 225 + fw = platform_get_drvdata(pdev); 243 226 244 227 id_buf = kmalloc(SM_CHIP_ID_LENGTH, GFP_KERNEL); 245 228 if (!id_buf) 246 229 return -ENOMEM; 247 230 248 - ret = meson_sm_call_read(id_buf, SM_CHIP_ID_LENGTH, SM_GET_CHIP_ID, 231 + ret = meson_sm_call_read(fw, id_buf, SM_CHIP_ID_LENGTH, SM_GET_CHIP_ID, 249 232 0, 0, 0, 0, 0); 250 233 if (ret < 0) { 251 234 kfree(id_buf); ··· 293 268 294 269 static int __init meson_sm_probe(struct platform_device *pdev) 295 270 { 271 + struct device *dev = &pdev->dev; 296 272 const struct meson_sm_chip *chip; 273 + struct meson_sm_firmware *fw; 297 274 298 - chip = of_match_device(meson_sm_ids, &pdev->dev)->data; 275 + fw = devm_kzalloc(dev, sizeof(*fw), GFP_KERNEL); 276 + if (!fw) 277 + return -ENOMEM; 278 + 279 + chip = of_match_device(meson_sm_ids, dev)->data; 299 280 300 281 if (chip->cmd_shmem_in_base) { 301 - fw.sm_shmem_in_base = meson_sm_map_shmem(chip->cmd_shmem_in_base, 302 - chip->shmem_size); 303 - if (WARN_ON(!fw.sm_shmem_in_base)) 282 + fw->sm_shmem_in_base = meson_sm_map_shmem(chip->cmd_shmem_in_base, 283 + chip->shmem_size); 284 + if (WARN_ON(!fw->sm_shmem_in_base)) 304 285 goto out; 305 286 } 306 287 307 288 if (chip->cmd_shmem_out_base) { 308 - fw.sm_shmem_out_base = meson_sm_map_shmem(chip->cmd_shmem_out_base, 309 - chip->shmem_size); 310 - if (WARN_ON(!fw.sm_shmem_out_base)) 289 + fw->sm_shmem_out_base = meson_sm_map_shmem(chip->cmd_shmem_out_base, 290 + chip->shmem_size); 291 + if (WARN_ON(!fw->sm_shmem_out_base)) 311 292 goto out_in_base; 312 293 } 313 294 314 - fw.chip = chip; 295 + fw->chip = chip; 296 + 297 + platform_set_drvdata(pdev, fw); 298 + 315 299 pr_info("secure-monitor enabled\n"); 316 300 317 301 if (sysfs_create_group(&pdev->dev.kobj, &meson_sm_sysfs_attr_group)) ··· 329 295 return 0; 330 296 331 297 out_in_base: 332 - iounmap(fw.sm_shmem_in_base); 298 + iounmap(fw->sm_shmem_in_base); 333 299 out: 334 300 return -EINVAL; 335 301 }
+21 -3
drivers/nvmem/meson-efuse.c
··· 17 17 static int meson_efuse_read(void *context, unsigned int offset, 18 18 void *val, size_t bytes) 19 19 { 20 - return meson_sm_call_read((u8 *)val, bytes, SM_EFUSE_READ, offset, 20 + struct meson_sm_firmware *fw = context; 21 + 22 + return meson_sm_call_read(fw, (u8 *)val, bytes, SM_EFUSE_READ, offset, 21 23 bytes, 0, 0, 0); 22 24 } 23 25 24 26 static int meson_efuse_write(void *context, unsigned int offset, 25 27 void *val, size_t bytes) 26 28 { 27 - return meson_sm_call_write((u8 *)val, bytes, SM_EFUSE_WRITE, offset, 29 + struct meson_sm_firmware *fw = context; 30 + 31 + return meson_sm_call_write(fw, (u8 *)val, bytes, SM_EFUSE_WRITE, offset, 28 32 bytes, 0, 0, 0); 29 33 } 30 34 ··· 41 37 static int meson_efuse_probe(struct platform_device *pdev) 42 38 { 43 39 struct device *dev = &pdev->dev; 40 + struct meson_sm_firmware *fw; 41 + struct device_node *sm_np; 44 42 struct nvmem_device *nvmem; 45 43 struct nvmem_config *econfig; 46 44 struct clk *clk; 47 45 unsigned int size; 48 46 int ret; 47 + 48 + sm_np = of_parse_phandle(pdev->dev.of_node, "secure-monitor", 0); 49 + if (!sm_np) { 50 + dev_err(&pdev->dev, "no secure-monitor node\n"); 51 + return -ENODEV; 52 + } 53 + 54 + fw = meson_sm_get(sm_np); 55 + of_node_put(sm_np); 56 + if (!fw) 57 + return -EPROBE_DEFER; 49 58 50 59 clk = devm_clk_get(dev, NULL); 51 60 if (IS_ERR(clk)) { ··· 82 65 return ret; 83 66 } 84 67 85 - if (meson_sm_call(SM_EFUSE_USER_MAX, &size, 0, 0, 0, 0, 0) < 0) { 68 + if (meson_sm_call(fw, SM_EFUSE_USER_MAX, &size, 0, 0, 0, 0, 0) < 0) { 86 69 dev_err(dev, "failed to get max user"); 87 70 return -EINVAL; 88 71 } ··· 98 81 econfig->reg_read = meson_efuse_read; 99 82 econfig->reg_write = meson_efuse_write; 100 83 econfig->size = size; 84 + econfig->priv = fw; 101 85 102 86 nvmem = devm_nvmem_register(&pdev->dev, econfig); 103 87
+9 -6
include/linux/firmware/meson/meson_sm.h
··· 16 16 17 17 struct meson_sm_firmware; 18 18 19 - int meson_sm_call(unsigned int cmd_index, u32 *ret, u32 arg0, u32 arg1, 20 - u32 arg2, u32 arg3, u32 arg4); 21 - int meson_sm_call_write(void *buffer, unsigned int b_size, unsigned int cmd_index, 22 - u32 arg0, u32 arg1, u32 arg2, u32 arg3, u32 arg4); 23 - int meson_sm_call_read(void *buffer, unsigned int bsize, unsigned int cmd_index, 24 - u32 arg0, u32 arg1, u32 arg2, u32 arg3, u32 arg4); 19 + int meson_sm_call(struct meson_sm_firmware *fw, unsigned int cmd_index, 20 + u32 *ret, u32 arg0, u32 arg1, u32 arg2, u32 arg3, u32 arg4); 21 + int meson_sm_call_write(struct meson_sm_firmware *fw, void *buffer, 22 + unsigned int b_size, unsigned int cmd_index, u32 arg0, 23 + u32 arg1, u32 arg2, u32 arg3, u32 arg4); 24 + int meson_sm_call_read(struct meson_sm_firmware *fw, void *buffer, 25 + unsigned int bsize, unsigned int cmd_index, u32 arg0, 26 + u32 arg1, u32 arg2, u32 arg3, u32 arg4); 27 + struct meson_sm_firmware *meson_sm_get(struct device_node *firmware_node); 25 28 26 29 #endif /* _MESON_SM_FW_H_ */