diff options
author | Stephen Rothwell <sfr@canb.auug.org.au> | 2018-11-21 14:05:22 +1100 |
---|---|---|
committer | Stephen Rothwell <sfr@canb.auug.org.au> | 2018-11-21 14:05:22 +1100 |
commit | 1f47367d21dc532d0a9850507223f9f6d3a7a363 (patch) | |
tree | 7cc9c0ac06f7eeeea3ee7ee33d7cce53e082e1d5 | |
parent | 2e2022dd582c42696828635e995130a4369379f7 (diff) | |
parent | 5035d66cc6297483a3d7e1b1af5cf8b04f089e43 (diff) |
Merge remote-tracking branch 'nvmem/for-next'
-rw-r--r-- | Documentation/devicetree/bindings/nvmem/amlogic-efuse.txt | 3 | ||||
-rw-r--r-- | drivers/nvmem/core.c | 21 | ||||
-rw-r--r-- | drivers/nvmem/meson-efuse.c | 29 | ||||
-rw-r--r-- | include/linux/nvmem-provider.h | 16 |
4 files changed, 68 insertions, 1 deletions
diff --git a/Documentation/devicetree/bindings/nvmem/amlogic-efuse.txt b/Documentation/devicetree/bindings/nvmem/amlogic-efuse.txt index e3298e18de26..2e0723ab3384 100644 --- a/Documentation/devicetree/bindings/nvmem/amlogic-efuse.txt +++ b/Documentation/devicetree/bindings/nvmem/amlogic-efuse.txt @@ -2,6 +2,8 @@ Required properties: - compatible: should be "amlogic,meson-gxbb-efuse" +- clocks: phandle to the efuse peripheral clock provided by the + clock controller. = Data cells = Are child nodes of eFuse, bindings of which as described in @@ -11,6 +13,7 @@ Example: efuse: efuse { compatible = "amlogic,meson-gxbb-efuse"; + clocks = <&clkc CLKID_EFUSE>; #address-cells = <1>; #size-cells = <1>; diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c index 27f67dfa649d..d9fd11033c1c 100644 --- a/drivers/nvmem/core.c +++ b/drivers/nvmem/core.c @@ -28,6 +28,7 @@ struct nvmem_device { size_t size; bool read_only; int flags; + enum nvmem_type type; struct bin_attribute eeprom; struct device *base_dev; struct list_head cells; @@ -83,6 +84,21 @@ static int nvmem_reg_write(struct nvmem_device *nvmem, unsigned int offset, return -EINVAL; } +static ssize_t type_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct nvmem_device *nvmem = to_nvmem_device(dev); + + return sprintf(buf, "%s\n", nvmem_type_str[nvmem->type]); +} + +static DEVICE_ATTR_RO(type); + +static struct attribute *nvmem_attrs[] = { + &dev_attr_type.attr, + NULL, +}; + static ssize_t bin_attr_nvmem_read(struct file *filp, struct kobject *kobj, struct bin_attribute *attr, char *buf, loff_t pos, size_t count) @@ -168,6 +184,7 @@ static struct bin_attribute *nvmem_bin_rw_attributes[] = { static const struct attribute_group nvmem_bin_rw_group = { .bin_attrs = nvmem_bin_rw_attributes, + .attrs = nvmem_attrs, }; static const struct attribute_group *nvmem_rw_dev_groups[] = { @@ -191,6 +208,7 @@ static struct bin_attribute *nvmem_bin_ro_attributes[] = { static const struct attribute_group nvmem_bin_ro_group = { .bin_attrs = nvmem_bin_ro_attributes, + .attrs = nvmem_attrs, }; static const struct attribute_group *nvmem_ro_dev_groups[] = { @@ -215,6 +233,7 @@ static struct bin_attribute *nvmem_bin_rw_root_attributes[] = { static const struct attribute_group nvmem_bin_rw_root_group = { .bin_attrs = nvmem_bin_rw_root_attributes, + .attrs = nvmem_attrs, }; static const struct attribute_group *nvmem_rw_root_dev_groups[] = { @@ -238,6 +257,7 @@ static struct bin_attribute *nvmem_bin_ro_root_attributes[] = { static const struct attribute_group nvmem_bin_ro_root_group = { .bin_attrs = nvmem_bin_ro_root_attributes, + .attrs = nvmem_attrs, }; static const struct attribute_group *nvmem_ro_root_dev_groups[] = { @@ -605,6 +625,7 @@ struct nvmem_device *nvmem_register(const struct nvmem_config *config) nvmem->dev.bus = &nvmem_bus_type; nvmem->dev.parent = config->dev; nvmem->priv = config->priv; + nvmem->type = config->type; nvmem->reg_read = config->reg_read; nvmem->reg_write = config->reg_write; nvmem->dev.of_node = config->dev->of_node; diff --git a/drivers/nvmem/meson-efuse.c b/drivers/nvmem/meson-efuse.c index d769840d1e18..99372768446b 100644 --- a/drivers/nvmem/meson-efuse.c +++ b/drivers/nvmem/meson-efuse.c @@ -14,6 +14,7 @@ * more details. */ +#include <linux/clk.h> #include <linux/module.h> #include <linux/nvmem-provider.h> #include <linux/of.h> @@ -46,10 +47,36 @@ static int meson_efuse_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct nvmem_device *nvmem; struct nvmem_config *econfig; + struct clk *clk; unsigned int size; + int ret; - if (meson_sm_call(SM_EFUSE_USER_MAX, &size, 0, 0, 0, 0, 0) < 0) + clk = devm_clk_get(dev, NULL); + if (IS_ERR(clk)) { + ret = PTR_ERR(clk); + if (ret != -EPROBE_DEFER) + dev_err(dev, "failed to get efuse gate"); + return ret; + } + + ret = clk_prepare_enable(clk); + if (ret) { + dev_err(dev, "failed to enable gate"); + return ret; + } + + ret = devm_add_action_or_reset(dev, + (void(*)(void *))clk_disable_unprepare, + clk); + if (ret) { + dev_err(dev, "failed to add disable callback"); + return ret; + } + + if (meson_sm_call(SM_EFUSE_USER_MAX, &size, 0, 0, 0, 0, 0) < 0) { + dev_err(dev, "failed to get max user"); return -EINVAL; + } econfig = devm_kzalloc(dev, sizeof(*econfig), GFP_KERNEL); if (!econfig) diff --git a/include/linux/nvmem-provider.h b/include/linux/nvmem-provider.h index 1e3283c2af77..00ff92571683 100644 --- a/include/linux/nvmem-provider.h +++ b/include/linux/nvmem-provider.h @@ -19,6 +19,20 @@ typedef int (*nvmem_reg_read_t)(void *priv, unsigned int offset, typedef int (*nvmem_reg_write_t)(void *priv, unsigned int offset, void *val, size_t bytes); +enum nvmem_type { + NVMEM_TYPE_UNKNOWN = 0, + NVMEM_TYPE_EEPROM, + NVMEM_TYPE_OTP, + NVMEM_TYPE_BATTERY_BACKED, +}; + +static const char * const nvmem_type_str[] = { + [NVMEM_TYPE_UNKNOWN] = "Unknown", + [NVMEM_TYPE_EEPROM] = "EEPROM", + [NVMEM_TYPE_OTP] = "OTP", + [NVMEM_TYPE_BATTERY_BACKED] = "Battery backed", +}; + /** * struct nvmem_config - NVMEM device configuration * @@ -28,6 +42,7 @@ typedef int (*nvmem_reg_write_t)(void *priv, unsigned int offset, * @owner: Pointer to exporter module. Used for refcounting. * @cells: Optional array of pre-defined NVMEM cells. * @ncells: Number of elements in cells. + * @type: Type of the nvmem storage * @read_only: Device is read-only. * @root_only: Device is accessibly to root only. * @reg_read: Callback to read data. @@ -51,6 +66,7 @@ struct nvmem_config { struct module *owner; const struct nvmem_cell_info *cells; int ncells; + enum nvmem_type type; bool read_only; bool root_only; nvmem_reg_read_t reg_read; |