Blame view

drivers/nvdimm/of_pmem.c 2.62 KB
717197608   Oliver O'Halloran   libnvdimm: Add de...
1
2
3
4
5
6
7
8
9
10
  // SPDX-License-Identifier: GPL-2.0+
  
  #define pr_fmt(fmt) "of_pmem: " fmt
  
  #include <linux/of_platform.h>
  #include <linux/of_address.h>
  #include <linux/libnvdimm.h>
  #include <linux/module.h>
  #include <linux/ioport.h>
  #include <linux/slab.h>
717197608   Oliver O'Halloran   libnvdimm: Add de...
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
  struct of_pmem_private {
  	struct nvdimm_bus_descriptor bus_desc;
  	struct nvdimm_bus *bus;
  };
  
  static int of_pmem_region_probe(struct platform_device *pdev)
  {
  	struct of_pmem_private *priv;
  	struct device_node *np;
  	struct nvdimm_bus *bus;
  	bool is_volatile;
  	int i;
  
  	np = dev_of_node(&pdev->dev);
  	if (!np)
  		return -ENXIO;
  
  	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
  	if (!priv)
  		return -ENOMEM;
49bddc73d   Aneesh Kumar K.V   libnvdimm/of_pmem...
31
  	priv->bus_desc.provider_name = kstrdup(pdev->name, GFP_KERNEL);
717197608   Oliver O'Halloran   libnvdimm: Add de...
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
  	priv->bus_desc.module = THIS_MODULE;
  	priv->bus_desc.of_node = np;
  
  	priv->bus = bus = nvdimm_bus_register(&pdev->dev, &priv->bus_desc);
  	if (!bus) {
  		kfree(priv);
  		return -ENODEV;
  	}
  	platform_set_drvdata(pdev, priv);
  
  	is_volatile = !!of_find_property(np, "volatile", NULL);
  	dev_dbg(&pdev->dev, "Registering %s regions from %pOF
  ",
  			is_volatile ? "volatile" : "non-volatile",  np);
  
  	for (i = 0; i < pdev->num_resources; i++) {
  		struct nd_region_desc ndr_desc;
  		struct nd_region *region;
  
  		/*
  		 * NB: libnvdimm copies the data from ndr_desc into it's own
  		 * structures so passing a stack pointer is fine.
  		 */
  		memset(&ndr_desc, 0, sizeof(ndr_desc));
df3f12648   Rob Herring   libnvdimm, of_pme...
56
  		ndr_desc.numa_node = dev_to_node(&pdev->dev);
8fc5c7355   Dan Williams   acpi/nfit, device...
57
  		ndr_desc.target_node = ndr_desc.numa_node;
717197608   Oliver O'Halloran   libnvdimm: Add de...
58
59
60
61
62
63
  		ndr_desc.res = &pdev->resource[i];
  		ndr_desc.of_node = np;
  		set_bit(ND_REGION_PAGEMAP, &ndr_desc.flags);
  
  		if (is_volatile)
  			region = nvdimm_volatile_region_create(bus, &ndr_desc);
338f6dac8   Aneesh Kumar K.V   libnvdimm: Update...
64
65
  		else {
  			set_bit(ND_REGION_PERSIST_MEMCTRL, &ndr_desc.flags);
717197608   Oliver O'Halloran   libnvdimm: Add de...
66
  			region = nvdimm_pmem_region_create(bus, &ndr_desc);
338f6dac8   Aneesh Kumar K.V   libnvdimm: Update...
67
  		}
717197608   Oliver O'Halloran   libnvdimm: Add de...
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
  
  		if (!region)
  			dev_warn(&pdev->dev, "Unable to register region %pR from %pOF
  ",
  					ndr_desc.res, np);
  		else
  			dev_dbg(&pdev->dev, "Registered region %pR from %pOF
  ",
  					ndr_desc.res, np);
  	}
  
  	return 0;
  }
  
  static int of_pmem_region_remove(struct platform_device *pdev)
  {
  	struct of_pmem_private *priv = platform_get_drvdata(pdev);
  
  	nvdimm_bus_unregister(priv->bus);
  	kfree(priv);
  
  	return 0;
  }
  
  static const struct of_device_id of_pmem_region_match[] = {
  	{ .compatible = "pmem-region" },
8c26ab726   Aneesh Kumar K.V   powerpc/pmem: Ini...
94
  	{ .compatible = "pmem-region-v2" },
717197608   Oliver O'Halloran   libnvdimm: Add de...
95
96
97
98
99
100
101
102
  	{ },
  };
  
  static struct platform_driver of_pmem_region_driver = {
  	.probe = of_pmem_region_probe,
  	.remove = of_pmem_region_remove,
  	.driver = {
  		.name = "of_pmem",
717197608   Oliver O'Halloran   libnvdimm: Add de...
103
104
105
106
107
108
109
110
  		.of_match_table = of_pmem_region_match,
  	},
  };
  
  module_platform_driver(of_pmem_region_driver);
  MODULE_DEVICE_TABLE(of, of_pmem_region_match);
  MODULE_LICENSE("GPL");
  MODULE_AUTHOR("IBM Corporation");