Message ID | 20210302074405.18998-2-zajec5@gmail.com (mailing list archive) |
---|---|
State | Superseded |
Headers | show |
Series | [stblinux.git,1/2] dt-bindings: firmware: add Broadcom's NVRAM memory mapping | expand |
On 3/1/21 11:44 PM, Rafał Miłecki wrote: > From: Rafał Miłecki <rafal@milecki.pl> > > Add support for platform device providing mapping resource. This allows > reading NVRAM based on DT mapping binding. It's required for devices > that boot depending on NVRAM stored setup and provides early access to > NVRAM data. > > Signed-off-by: Rafał Miłecki <rafal@milecki.pl> > --- > bcm47xx_nvram driver was originally added through MIPS tree, but this > change doesn't affect BCM47XX (MIPS) as it doesn't use DT. It targets > ARCH_BCM_5301X so I suggest this goes through the stblinux.git tree. Can you see if this change can be replaced by the nvmem-rmem work that Nicolas recently did to support something similar for the Raspberry Pi 4: https://lkml.org/lkml/2021/1/29/235 > --- > drivers/firmware/broadcom/bcm47xx_nvram.c | 55 +++++++++++++++++++++++ > 1 file changed, 55 insertions(+) > > diff --git a/drivers/firmware/broadcom/bcm47xx_nvram.c b/drivers/firmware/broadcom/bcm47xx_nvram.c > index 835ece9c00f1..d5d19dd1b9e1 100644 > --- a/drivers/firmware/broadcom/bcm47xx_nvram.c > +++ b/drivers/firmware/broadcom/bcm47xx_nvram.c > @@ -13,6 +13,7 @@ > #include <linux/kernel.h> > #include <linux/string.h> > #include <linux/mtd/mtd.h> > +#include <linux/platform_device.h> > #include <linux/bcm47xx_nvram.h> > > #define NVRAM_MAGIC 0x48534C46 /* 'FLSH' */ > @@ -162,6 +163,60 @@ static int nvram_init(void) > return -ENXIO; > } > > +static int brcm_nvram_probe(struct platform_device *pdev) > +{ > + struct nvram_header __iomem *header; > + struct device *dev = &pdev->dev; > + struct resource *res; > + void __iomem *mmio; > + size_t copy_len; > + > + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); > + if (!res) { > + dev_err(dev, "Failed to get resource\n"); > + return -ENODEV; > + } > + > + mmio = ioremap(res->start, resource_size(res)); > + if (!mmio) > + return -ENOMEM; > + > + header = (struct nvram_header *)mmio; > + copy_len = DIV_ROUND_UP(sizeof(*header) + header->len, 4); > + if (header->magic != NVRAM_MAGIC) { > + dev_err(dev, "No NVRAM found at %pR\n", res); > + return -EPROTO; > + } else if (copy_len > resource_size(res)) { > + dev_err(dev, "NVRAM size exceeds %pR\n", res); > + return -ERANGE; > + } else if (copy_len >= NVRAM_SPACE) { > + dev_err(dev, "NVRAM size exceeds buffer size %d\n", NVRAM_SPACE); > + return -ENOMEM; > + } > + > + __ioread32_copy(nvram_buf, mmio, copy_len); > + nvram_buf[NVRAM_SPACE - 1] = '\0'; > + > + iounmap(mmio); > + > + return 0; > +} > + > +static const struct of_device_id brcm_nvram_of_match[] = { > + { .compatible = "brcm,nvram "}, > + {}, > +}; > + > +static struct platform_driver brcm_nvram_driver = { > + .driver = { > + .name = "brcm_nvram", > + .of_match_table = brcm_nvram_of_match, > + }, > + .probe = brcm_nvram_probe, > +}; > + > +module_platform_driver(brcm_nvram_driver); > + > int bcm47xx_nvram_getenv(const char *name, char *val, size_t val_len) > { > char *var, *value, *end, *eq; >
On 02.03.2021 17:59, Florian Fainelli wrote: > On 3/1/21 11:44 PM, Rafał Miłecki wrote: >> From: Rafał Miłecki <rafal@milecki.pl> >> >> Add support for platform device providing mapping resource. This allows >> reading NVRAM based on DT mapping binding. It's required for devices >> that boot depending on NVRAM stored setup and provides early access to >> NVRAM data. >> >> Signed-off-by: Rafał Miłecki <rafal@milecki.pl> >> --- >> bcm47xx_nvram driver was originally added through MIPS tree, but this >> change doesn't affect BCM47XX (MIPS) as it doesn't use DT. It targets >> ARCH_BCM_5301X so I suggest this goes through the stblinux.git tree. > > Can you see if this change can be replaced by the nvmem-rmem work that > Nicolas recently did to support something similar for the Raspberry Pi 4: > > https://lkml.org/lkml/2021/1/29/235 I don't think it fits my case. It's a reserved memory binding/driver which refers to the system memory. In NVRAM case we need to do a mapping. I think it's different? nvmem-rmem registers NVMEM device without providing any cells. It also doesn't understand NVRAM data structure. I guess nvmem-rmem only exposes NVMEM for user-space access. I need to access NVRAM to e.g. detect boot parameters in kernel code. I was thinking for a moment about treating NVRAM like a NVMEM but NVRAM doesn't seem to fit current design and kernel API. NVMEM assumes that every cell has a specific offset and size. Reading NVRAM should be based on string keys (nof offsets). See nvmem_reg_read_t for details. This won't make a huge difference I think, but for a slightly cleaner design I could probably have NVRAM devices without cells and make it setup NVRAM. Let me see if I can code that.
diff --git a/drivers/firmware/broadcom/bcm47xx_nvram.c b/drivers/firmware/broadcom/bcm47xx_nvram.c index 835ece9c00f1..d5d19dd1b9e1 100644 --- a/drivers/firmware/broadcom/bcm47xx_nvram.c +++ b/drivers/firmware/broadcom/bcm47xx_nvram.c @@ -13,6 +13,7 @@ #include <linux/kernel.h> #include <linux/string.h> #include <linux/mtd/mtd.h> +#include <linux/platform_device.h> #include <linux/bcm47xx_nvram.h> #define NVRAM_MAGIC 0x48534C46 /* 'FLSH' */ @@ -162,6 +163,60 @@ static int nvram_init(void) return -ENXIO; } +static int brcm_nvram_probe(struct platform_device *pdev) +{ + struct nvram_header __iomem *header; + struct device *dev = &pdev->dev; + struct resource *res; + void __iomem *mmio; + size_t copy_len; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(dev, "Failed to get resource\n"); + return -ENODEV; + } + + mmio = ioremap(res->start, resource_size(res)); + if (!mmio) + return -ENOMEM; + + header = (struct nvram_header *)mmio; + copy_len = DIV_ROUND_UP(sizeof(*header) + header->len, 4); + if (header->magic != NVRAM_MAGIC) { + dev_err(dev, "No NVRAM found at %pR\n", res); + return -EPROTO; + } else if (copy_len > resource_size(res)) { + dev_err(dev, "NVRAM size exceeds %pR\n", res); + return -ERANGE; + } else if (copy_len >= NVRAM_SPACE) { + dev_err(dev, "NVRAM size exceeds buffer size %d\n", NVRAM_SPACE); + return -ENOMEM; + } + + __ioread32_copy(nvram_buf, mmio, copy_len); + nvram_buf[NVRAM_SPACE - 1] = '\0'; + + iounmap(mmio); + + return 0; +} + +static const struct of_device_id brcm_nvram_of_match[] = { + { .compatible = "brcm,nvram "}, + {}, +}; + +static struct platform_driver brcm_nvram_driver = { + .driver = { + .name = "brcm_nvram", + .of_match_table = brcm_nvram_of_match, + }, + .probe = brcm_nvram_probe, +}; + +module_platform_driver(brcm_nvram_driver); + int bcm47xx_nvram_getenv(const char *name, char *val, size_t val_len) { char *var, *value, *end, *eq;