1 // SPDX-License-Identifier: GPL-2.0-only OR MIT 2 /* 3 * Apple SPMI NVMEM driver 4 * 5 * Copyright The Asahi Linux Contributors 6 */ 7 8 #include <linux/kernel.h> 9 #include <linux/module.h> 10 #include <linux/nvmem-provider.h> 11 #include <linux/of.h> 12 #include <linux/spmi.h> 13 #include <linux/regmap.h> 14 15 static const struct regmap_config apple_spmi_regmap_config = { 16 .reg_bits = 16, 17 .val_bits = 8, 18 .max_register = 0xffff, 19 }; 20 21 static int apple_spmi_nvmem_read(void *priv, unsigned int offset, void *val, 22 size_t bytes) 23 { 24 struct regmap *map = priv; 25 26 return regmap_bulk_read(map, offset, val, bytes); 27 } 28 29 static int apple_spmi_nvmem_write(void *priv, unsigned int offset, void *val, 30 size_t bytes) 31 { 32 struct regmap *map = priv; 33 34 return regmap_bulk_write(map, offset, val, bytes); 35 } 36 37 static int apple_spmi_nvmem_probe(struct spmi_device *sdev) 38 { 39 struct regmap *regmap; 40 struct nvmem_config nvmem_cfg = { 41 .dev = &sdev->dev, 42 .name = "spmi_nvmem", 43 .id = NVMEM_DEVID_AUTO, 44 .word_size = 1, 45 .stride = 1, 46 .size = 0xffff, 47 .reg_read = apple_spmi_nvmem_read, 48 .reg_write = apple_spmi_nvmem_write, 49 }; 50 51 regmap = devm_regmap_init_spmi_ext(sdev, &apple_spmi_regmap_config); 52 if (IS_ERR(regmap)) 53 return PTR_ERR(regmap); 54 55 nvmem_cfg.priv = regmap; 56 57 return PTR_ERR_OR_ZERO(devm_nvmem_register(&sdev->dev, &nvmem_cfg)); 58 } 59 60 static const struct of_device_id apple_spmi_nvmem_id_table[] = { 61 { .compatible = "apple,spmi-nvmem" }, 62 { }, 63 }; 64 MODULE_DEVICE_TABLE(of, apple_spmi_nvmem_id_table); 65 66 static struct spmi_driver apple_spmi_nvmem_driver = { 67 .probe = apple_spmi_nvmem_probe, 68 .driver = { 69 .name = "apple-spmi-nvmem", 70 .of_match_table = apple_spmi_nvmem_id_table, 71 }, 72 }; 73 74 module_spmi_driver(apple_spmi_nvmem_driver); 75 76 MODULE_LICENSE("Dual MIT/GPL"); 77 MODULE_AUTHOR("Hector Martin <marcan@marcan.st>"); 78 MODULE_DESCRIPTION("Apple SPMI NVMEM driver"); 79