0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0020
0021 #include <linux/io.h>
0022 #include <linux/init.h>
0023 #include <linux/kernel.h>
0024 #include <linux/list.h>
0025 #include <linux/module.h>
0026 #include <linux/moduleparam.h>
0027 #include <linux/slab.h>
0028 #include <linux/mtd/mtd.h>
0029 #include <asm/div64.h>
0030 #include <linux/platform_device.h>
0031 #include <linux/of_address.h>
0032 #include <linux/of.h>
0033
0034 struct phram_mtd_list {
0035 struct mtd_info mtd;
0036 struct list_head list;
0037 bool cached;
0038 };
0039
0040 static LIST_HEAD(phram_list);
0041
0042 static int phram_erase(struct mtd_info *mtd, struct erase_info *instr)
0043 {
0044 u_char *start = mtd->priv;
0045
0046 memset(start + instr->addr, 0xff, instr->len);
0047
0048 return 0;
0049 }
0050
0051 static int phram_point(struct mtd_info *mtd, loff_t from, size_t len,
0052 size_t *retlen, void **virt, resource_size_t *phys)
0053 {
0054 *virt = mtd->priv + from;
0055 *retlen = len;
0056 return 0;
0057 }
0058
0059 static int phram_unpoint(struct mtd_info *mtd, loff_t from, size_t len)
0060 {
0061 return 0;
0062 }
0063
0064 static int phram_read(struct mtd_info *mtd, loff_t from, size_t len,
0065 size_t *retlen, u_char *buf)
0066 {
0067 u_char *start = mtd->priv;
0068
0069 memcpy(buf, start + from, len);
0070 *retlen = len;
0071 return 0;
0072 }
0073
0074 static int phram_write(struct mtd_info *mtd, loff_t to, size_t len,
0075 size_t *retlen, const u_char *buf)
0076 {
0077 u_char *start = mtd->priv;
0078
0079 memcpy(start + to, buf, len);
0080 *retlen = len;
0081 return 0;
0082 }
0083
0084 static int phram_map(struct phram_mtd_list *phram, phys_addr_t start, size_t len)
0085 {
0086 void *addr = NULL;
0087
0088 if (phram->cached)
0089 addr = memremap(start, len, MEMREMAP_WB);
0090 else
0091 addr = (void __force *)ioremap(start, len);
0092 if (!addr)
0093 return -EIO;
0094
0095 phram->mtd.priv = addr;
0096
0097 return 0;
0098 }
0099
0100 static void phram_unmap(struct phram_mtd_list *phram)
0101 {
0102 void *addr = phram->mtd.priv;
0103
0104 if (phram->cached) {
0105 memunmap(addr);
0106 return;
0107 }
0108
0109 iounmap((void __iomem *)addr);
0110 }
0111
0112 static void unregister_devices(void)
0113 {
0114 struct phram_mtd_list *this, *safe;
0115
0116 list_for_each_entry_safe(this, safe, &phram_list, list) {
0117 mtd_device_unregister(&this->mtd);
0118 phram_unmap(this);
0119 kfree(this->mtd.name);
0120 kfree(this);
0121 }
0122 }
0123
0124 static int register_device(struct platform_device *pdev, const char *name,
0125 phys_addr_t start, size_t len, uint32_t erasesize)
0126 {
0127 struct device_node *np = pdev ? pdev->dev.of_node : NULL;
0128 bool cached = np ? !of_property_read_bool(np, "no-map") : false;
0129 struct phram_mtd_list *new;
0130 int ret = -ENOMEM;
0131
0132 new = kzalloc(sizeof(*new), GFP_KERNEL);
0133 if (!new)
0134 goto out0;
0135
0136 new->cached = cached;
0137
0138 ret = phram_map(new, start, len);
0139 if (ret) {
0140 pr_err("ioremap failed\n");
0141 goto out1;
0142 }
0143
0144
0145 new->mtd.name = name;
0146 new->mtd.size = len;
0147 new->mtd.flags = MTD_CAP_RAM;
0148 new->mtd._erase = phram_erase;
0149 new->mtd._point = phram_point;
0150 new->mtd._unpoint = phram_unpoint;
0151 new->mtd._read = phram_read;
0152 new->mtd._write = phram_write;
0153 new->mtd.owner = THIS_MODULE;
0154 new->mtd.type = MTD_RAM;
0155 new->mtd.erasesize = erasesize;
0156 new->mtd.writesize = 1;
0157
0158 mtd_set_of_node(&new->mtd, np);
0159
0160 ret = -EAGAIN;
0161 if (mtd_device_register(&new->mtd, NULL, 0)) {
0162 pr_err("Failed to register new device\n");
0163 goto out2;
0164 }
0165
0166 if (pdev)
0167 platform_set_drvdata(pdev, new);
0168 else
0169 list_add_tail(&new->list, &phram_list);
0170
0171 return 0;
0172
0173 out2:
0174 phram_unmap(new);
0175 out1:
0176 kfree(new);
0177 out0:
0178 return ret;
0179 }
0180
0181 static int parse_num64(uint64_t *num64, char *token)
0182 {
0183 size_t len;
0184 int shift = 0;
0185 int ret;
0186
0187 len = strlen(token);
0188
0189 if (len > 2) {
0190 if (token[len - 1] == 'i') {
0191 switch (token[len - 2]) {
0192 case 'G':
0193 shift += 10;
0194 fallthrough;
0195 case 'M':
0196 shift += 10;
0197 fallthrough;
0198 case 'k':
0199 shift += 10;
0200 token[len - 2] = 0;
0201 break;
0202 default:
0203 return -EINVAL;
0204 }
0205 }
0206 }
0207
0208 ret = kstrtou64(token, 0, num64);
0209 *num64 <<= shift;
0210
0211 return ret;
0212 }
0213
0214 static int parse_name(char **pname, const char *token)
0215 {
0216 size_t len;
0217 char *name;
0218
0219 len = strlen(token) + 1;
0220 if (len > 64)
0221 return -ENOSPC;
0222
0223 name = kstrdup(token, GFP_KERNEL);
0224 if (!name)
0225 return -ENOMEM;
0226
0227 *pname = name;
0228 return 0;
0229 }
0230
0231
0232 static inline void kill_final_newline(char *str)
0233 {
0234 char *newline = strrchr(str, '\n');
0235
0236 if (newline && !newline[1])
0237 *newline = 0;
0238 }
0239
0240
0241 #define parse_err(fmt, args...) do { \
0242 pr_err(fmt , ## args); \
0243 return 1; \
0244 } while (0)
0245
0246 #ifndef MODULE
0247 static int phram_init_called;
0248
0249
0250
0251
0252
0253
0254
0255
0256 static char phram_paramline[64 + 20 + 20 + 20];
0257 #endif
0258
0259 static int phram_setup(const char *val)
0260 {
0261 char buf[64 + 20 + 20 + 20], *str = buf;
0262 char *token[4];
0263 char *name;
0264 uint64_t start;
0265 uint64_t len;
0266 uint64_t erasesize = PAGE_SIZE;
0267 uint32_t rem;
0268 int i, ret;
0269
0270 if (strnlen(val, sizeof(buf)) >= sizeof(buf))
0271 parse_err("parameter too long\n");
0272
0273 strcpy(str, val);
0274 kill_final_newline(str);
0275
0276 for (i = 0; i < 4; i++)
0277 token[i] = strsep(&str, ",");
0278
0279 if (str)
0280 parse_err("too many arguments\n");
0281
0282 if (!token[2])
0283 parse_err("not enough arguments\n");
0284
0285 ret = parse_name(&name, token[0]);
0286 if (ret)
0287 return ret;
0288
0289 ret = parse_num64(&start, token[1]);
0290 if (ret) {
0291 parse_err("illegal start address\n");
0292 goto error;
0293 }
0294
0295 ret = parse_num64(&len, token[2]);
0296 if (ret) {
0297 parse_err("illegal device length\n");
0298 goto error;
0299 }
0300
0301 if (token[3]) {
0302 ret = parse_num64(&erasesize, token[3]);
0303 if (ret) {
0304 parse_err("illegal erasesize\n");
0305 goto error;
0306 }
0307 }
0308
0309 if (len == 0 || erasesize == 0 || erasesize > len
0310 || erasesize > UINT_MAX) {
0311 parse_err("illegal erasesize or len\n");
0312 ret = -EINVAL;
0313 goto error;
0314 }
0315
0316 div_u64_rem(len, (uint32_t)erasesize, &rem);
0317 if (rem) {
0318 parse_err("len is not multiple of erasesize\n");
0319 ret = -EINVAL;
0320 goto error;
0321 }
0322
0323 ret = register_device(NULL, name, start, len, (uint32_t)erasesize);
0324 if (ret)
0325 goto error;
0326
0327 pr_info("%s device: %#llx at %#llx for erasesize %#llx\n", name, len, start, erasesize);
0328 return 0;
0329
0330 error:
0331 kfree(name);
0332 return ret;
0333 }
0334
0335 static int phram_param_call(const char *val, const struct kernel_param *kp)
0336 {
0337 #ifdef MODULE
0338 return phram_setup(val);
0339 #else
0340
0341
0342
0343
0344
0345
0346
0347 if (phram_init_called)
0348 return phram_setup(val);
0349
0350
0351
0352
0353
0354
0355
0356
0357
0358
0359 if (strlen(val) >= sizeof(phram_paramline))
0360 return -ENOSPC;
0361 strcpy(phram_paramline, val);
0362
0363 return 0;
0364 #endif
0365 }
0366
0367 module_param_call(phram, phram_param_call, NULL, NULL, 0200);
0368 MODULE_PARM_DESC(phram, "Memory region to map. \"phram=<name>,<start>,<length>[,<erasesize>]\"");
0369
0370 #ifdef CONFIG_OF
0371 static const struct of_device_id phram_of_match[] = {
0372 { .compatible = "phram" },
0373 {}
0374 };
0375 MODULE_DEVICE_TABLE(of, phram_of_match);
0376 #endif
0377
0378 static int phram_probe(struct platform_device *pdev)
0379 {
0380 struct resource *res;
0381
0382 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
0383 if (!res)
0384 return -ENOMEM;
0385
0386
0387 return register_device(pdev, NULL, res->start, resource_size(res),
0388 PAGE_SIZE);
0389 }
0390
0391 static int phram_remove(struct platform_device *pdev)
0392 {
0393 struct phram_mtd_list *phram = platform_get_drvdata(pdev);
0394
0395 mtd_device_unregister(&phram->mtd);
0396 phram_unmap(phram);
0397 kfree(phram);
0398
0399 return 0;
0400 }
0401
0402 static struct platform_driver phram_driver = {
0403 .probe = phram_probe,
0404 .remove = phram_remove,
0405 .driver = {
0406 .name = "phram",
0407 .of_match_table = of_match_ptr(phram_of_match),
0408 },
0409 };
0410
0411 static int __init init_phram(void)
0412 {
0413 int ret;
0414
0415 ret = platform_driver_register(&phram_driver);
0416 if (ret)
0417 return ret;
0418
0419 #ifndef MODULE
0420 if (phram_paramline[0])
0421 ret = phram_setup(phram_paramline);
0422 phram_init_called = 1;
0423 #endif
0424
0425 if (ret)
0426 platform_driver_unregister(&phram_driver);
0427
0428 return ret;
0429 }
0430
0431 static void __exit cleanup_phram(void)
0432 {
0433 unregister_devices();
0434 platform_driver_unregister(&phram_driver);
0435 }
0436
0437 module_init(init_phram);
0438 module_exit(cleanup_phram);
0439
0440 MODULE_LICENSE("GPL");
0441 MODULE_AUTHOR("Joern Engel <joern@wh.fh-wedel.de>");
0442 MODULE_DESCRIPTION("MTD driver for physical RAM");