497-mtd-mtdconcat-add-dt-driver-for-concat-devices.patch 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. From e53f712d8eac71f54399b61038ccf87d2cee99d7 Mon Sep 17 00:00:00 2001
  2. From: Bernhard Frauendienst <[email protected]>
  3. Date: Sat, 25 Aug 2018 12:35:22 +0200
  4. Subject: [PATCH 497/497] mtd: mtdconcat: add dt driver for concat devices
  5. Some mtd drivers like physmap variants have support for concatenating
  6. multiple mtd devices, but there is no generic way to define such a
  7. concat device from within the device tree.
  8. This is useful for some SoC boards that use multiple flash chips as
  9. memory banks of a single mtd device, with partitions spanning chip
  10. borders.
  11. This commit adds a driver for creating virtual mtd-concat devices. They
  12. must have a compatible = "mtd-concat" line, and define a list of devices
  13. to concat in the 'devices' property, for example:
  14. flash {
  15. compatible = "mtd-concat";
  16. devices = <&flash0 &flash1>;
  17. partitions {
  18. ...
  19. };
  20. };
  21. The driver is added to the very end of the mtd Makefile to increase the
  22. likelyhood of all child devices already being loaded at the time of
  23. probing, preventing unnecessary deferred probes.
  24. Signed-off-by: Bernhard Frauendienst <[email protected]>
  25. ---
  26. drivers/mtd/Kconfig | 2 +
  27. drivers/mtd/Makefile | 3 +
  28. drivers/mtd/composite/Kconfig | 12 +++
  29. drivers/mtd/composite/Makefile | 6 ++
  30. drivers/mtd/composite/virt_concat.c | 128 ++++++++++++++++++++++++++++
  31. 5 files changed, 151 insertions(+)
  32. create mode 100644 drivers/mtd/composite/Kconfig
  33. create mode 100644 drivers/mtd/composite/Makefile
  34. create mode 100644 drivers/mtd/composite/virt_concat.c
  35. diff --git a/drivers/mtd/Kconfig b/drivers/mtd/Kconfig
  36. index 5a2d71729b9a..de18bc568e3e 100644
  37. --- a/drivers/mtd/Kconfig
  38. +++ b/drivers/mtd/Kconfig
  39. @@ -342,4 +342,6 @@ source "drivers/mtd/spi-nor/Kconfig"
  40. source "drivers/mtd/ubi/Kconfig"
  41. +source "drivers/mtd/composite/Kconfig"
  42. +
  43. endif # MTD
  44. diff --git a/drivers/mtd/Makefile b/drivers/mtd/Makefile
  45. index d6f8f625e1ff..a6c5f134c35d 100644
  46. --- a/drivers/mtd/Makefile
  47. +++ b/drivers/mtd/Makefile
  48. @@ -36,3 +36,6 @@ obj-y += chips/ lpddr/ maps/ devices/ nand/ onenand/ tests/
  49. obj-$(CONFIG_MTD_SPI_NOR) += spi-nor/
  50. obj-$(CONFIG_MTD_UBI) += ubi/
  51. +
  52. +# Composite drivers must be loaded last
  53. +obj-y += composite/
  54. diff --git a/drivers/mtd/composite/Kconfig b/drivers/mtd/composite/Kconfig
  55. new file mode 100644
  56. index 000000000000..0490fc0284bb
  57. --- /dev/null
  58. +++ b/drivers/mtd/composite/Kconfig
  59. @@ -0,0 +1,12 @@
  60. +menu "Composite MTD device drivers"
  61. + depends on MTD!=n
  62. +
  63. +config MTD_VIRT_CONCAT
  64. + tristate "Virtual concat MTD device"
  65. + help
  66. + This driver allows creation of a virtual MTD concat device, which
  67. + concatenates multiple underlying MTD devices to a single device.
  68. + This is required by some SoC boards where multiple memory banks are
  69. + used as one device with partitions spanning across device boundaries.
  70. +
  71. +endmenu
  72. diff --git a/drivers/mtd/composite/Makefile b/drivers/mtd/composite/Makefile
  73. new file mode 100644
  74. index 000000000000..8421a0a30606
  75. --- /dev/null
  76. +++ b/drivers/mtd/composite/Makefile
  77. @@ -0,0 +1,6 @@
  78. +# SPDX-License-Identifier: GPL-2.0
  79. +#
  80. +# linux/drivers/mtd/composite/Makefile
  81. +#
  82. +
  83. +obj-$(CONFIG_MTD_VIRT_CONCAT) += virt_concat.o
  84. diff --git a/drivers/mtd/composite/virt_concat.c b/drivers/mtd/composite/virt_concat.c
  85. new file mode 100644
  86. index 000000000000..bfd432188c35
  87. --- /dev/null
  88. +++ b/drivers/mtd/composite/virt_concat.c
  89. @@ -0,0 +1,128 @@
  90. +// SPDX-License-Identifier: GPL-2.0+
  91. +/*
  92. + * Virtual concat MTD device driver
  93. + *
  94. + * Copyright (C) 2018 Bernhard Frauendienst
  95. + * Author: Bernhard Frauendienst, [email protected]
  96. + */
  97. +
  98. +#include <linux/module.h>
  99. +#include <linux/device.h>
  100. +#include <linux/mtd/concat.h>
  101. +#include <linux/mtd/mtd.h>
  102. +#include <linux/mtd/partitions.h>
  103. +#include <linux/of.h>
  104. +#include <linux/of_platform.h>
  105. +#include <linux/slab.h>
  106. +
  107. +/*
  108. + * struct of_virt_concat - platform device driver data.
  109. + * @cmtd the final mtd_concat device
  110. + * @num_devices the number of devices in @devices
  111. + * @devices points to an array of devices already loaded
  112. + */
  113. +struct of_virt_concat {
  114. + struct mtd_info *cmtd;
  115. + int num_devices;
  116. + struct mtd_info **devices;
  117. +};
  118. +
  119. +static int virt_concat_remove(struct platform_device *pdev)
  120. +{
  121. + struct of_virt_concat *info;
  122. + int i;
  123. +
  124. + info = platform_get_drvdata(pdev);
  125. + if (!info)
  126. + return 0;
  127. +
  128. + // unset data for when this is called after a probe error
  129. + platform_set_drvdata(pdev, NULL);
  130. +
  131. + if (info->cmtd) {
  132. + mtd_device_unregister(info->cmtd);
  133. + mtd_concat_destroy(info->cmtd);
  134. + }
  135. +
  136. + if (info->devices) {
  137. + for (i = 0; i < info->num_devices; i++)
  138. + put_mtd_device(info->devices[i]);
  139. + }
  140. +
  141. + return 0;
  142. +}
  143. +
  144. +static int virt_concat_probe(struct platform_device *pdev)
  145. +{
  146. + struct device_node *node = pdev->dev.of_node;
  147. + struct of_phandle_iterator it;
  148. + struct of_virt_concat *info;
  149. + struct mtd_info *mtd;
  150. + int err = 0, count;
  151. +
  152. + count = of_count_phandle_with_args(node, "devices", NULL);
  153. + if (count <= 0)
  154. + return -EINVAL;
  155. +
  156. + info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
  157. + if (!info)
  158. + return -ENOMEM;
  159. + info->devices = devm_kcalloc(&pdev->dev, count,
  160. + sizeof(*(info->devices)), GFP_KERNEL);
  161. + if (!info->devices) {
  162. + err = -ENOMEM;
  163. + goto err_remove;
  164. + }
  165. +
  166. + platform_set_drvdata(pdev, info);
  167. +
  168. + of_for_each_phandle(&it, err, node, "devices", NULL, 0) {
  169. + mtd = get_mtd_device_by_node(it.node);
  170. + if (IS_ERR(mtd)) {
  171. + of_node_put(it.node);
  172. + err = -EPROBE_DEFER;
  173. + goto err_remove;
  174. + }
  175. +
  176. + info->devices[info->num_devices++] = mtd;
  177. + }
  178. +
  179. + info->cmtd = mtd_concat_create(info->devices, info->num_devices,
  180. + dev_name(&pdev->dev));
  181. + if (!info->cmtd) {
  182. + err = -ENXIO;
  183. + goto err_remove;
  184. + }
  185. +
  186. + info->cmtd->dev.parent = &pdev->dev;
  187. + mtd_set_of_node(info->cmtd, node);
  188. + mtd_device_register(info->cmtd, NULL, 0);
  189. +
  190. + return 0;
  191. +
  192. +err_remove:
  193. + virt_concat_remove(pdev);
  194. +
  195. + return err;
  196. +}
  197. +
  198. +static const struct of_device_id virt_concat_of_match[] = {
  199. + { .compatible = "mtd-concat", },
  200. + { /* sentinel */ }
  201. +};
  202. +MODULE_DEVICE_TABLE(of, virt_concat_of_match);
  203. +
  204. +static struct platform_driver virt_concat_driver = {
  205. + .probe = virt_concat_probe,
  206. + .remove = virt_concat_remove,
  207. + .driver = {
  208. + .name = "virt-mtdconcat",
  209. + .of_match_table = virt_concat_of_match,
  210. + },
  211. +};
  212. +
  213. +module_platform_driver(virt_concat_driver);
  214. +
  215. +MODULE_LICENSE("GPL v2");
  216. +MODULE_AUTHOR("Bernhard Frauendienst <[email protected]>");
  217. +MODULE_DESCRIPTION("Virtual concat MTD device driver");
  218. --
  219. 2.18.0