Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0+
0002 /*
0003  * Normal mappings of chips in physical memory
0004  *
0005  * Copyright (C) 2003 MontaVista Software Inc.
0006  * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
0007  *
0008  * 031022 - [jsun] add run-time configure and partition setup
0009  *
0010  * Device tree support:
0011  *    Copyright (C) 2006 MontaVista Software Inc.
0012  *    Author: Vitaly Wool <vwool@ru.mvista.com>
0013  *
0014  *    Revised to handle newer style flash binding by:
0015  *    Copyright (C) 2007 David Gibson, IBM Corporation.
0016  *
0017  * GPIO address extension:
0018  *    Handle the case where a flash device is mostly addressed using physical
0019  *    line and supplemented by GPIOs.  This way you can hook up say a 8MiB flash
0020  *    to a 2MiB memory range and use the GPIOs to select a particular range.
0021  *
0022  *    Copyright © 2000 Nicolas Pitre <nico@cam.org>
0023  *    Copyright © 2005-2009 Analog Devices Inc.
0024  */
0025 
0026 #include <linux/module.h>
0027 #include <linux/types.h>
0028 #include <linux/kernel.h>
0029 #include <linux/init.h>
0030 #include <linux/slab.h>
0031 #include <linux/device.h>
0032 #include <linux/platform_device.h>
0033 #include <linux/mtd/mtd.h>
0034 #include <linux/mtd/map.h>
0035 #include <linux/mtd/partitions.h>
0036 #include <linux/mtd/physmap.h>
0037 #include <linux/mtd/concat.h>
0038 #include <linux/mtd/cfi_endian.h>
0039 #include <linux/io.h>
0040 #include <linux/of_device.h>
0041 #include <linux/pm_runtime.h>
0042 #include <linux/gpio/consumer.h>
0043 
0044 #include "physmap-bt1-rom.h"
0045 #include "physmap-gemini.h"
0046 #include "physmap-ixp4xx.h"
0047 #include "physmap-versatile.h"
0048 
0049 struct physmap_flash_info {
0050     unsigned int        nmaps;
0051     struct mtd_info     **mtds;
0052     struct mtd_info     *cmtd;
0053     struct map_info     *maps;
0054     spinlock_t      vpp_lock;
0055     int         vpp_refcnt;
0056     const char      *probe_type;
0057     const char * const  *part_types;
0058     unsigned int        nparts;
0059     const struct mtd_partition *parts;
0060     struct gpio_descs   *gpios;
0061     unsigned int        gpio_values;
0062     unsigned int        win_order;
0063 };
0064 
0065 static int physmap_flash_remove(struct platform_device *dev)
0066 {
0067     struct physmap_flash_info *info;
0068     struct physmap_flash_data *physmap_data;
0069     int i;
0070 
0071     info = platform_get_drvdata(dev);
0072 
0073     if (info->cmtd) {
0074         WARN_ON(mtd_device_unregister(info->cmtd));
0075 
0076         if (info->cmtd != info->mtds[0])
0077             mtd_concat_destroy(info->cmtd);
0078     }
0079 
0080     for (i = 0; i < info->nmaps; i++) {
0081         if (info->mtds[i])
0082             map_destroy(info->mtds[i]);
0083     }
0084 
0085     physmap_data = dev_get_platdata(&dev->dev);
0086     if (physmap_data && physmap_data->exit)
0087         physmap_data->exit(dev);
0088 
0089     pm_runtime_put(&dev->dev);
0090     pm_runtime_disable(&dev->dev);
0091     return 0;
0092 }
0093 
0094 static void physmap_set_vpp(struct map_info *map, int state)
0095 {
0096     struct platform_device *pdev;
0097     struct physmap_flash_data *physmap_data;
0098     struct physmap_flash_info *info;
0099     unsigned long flags;
0100 
0101     pdev = (struct platform_device *)map->map_priv_1;
0102     physmap_data = dev_get_platdata(&pdev->dev);
0103 
0104     if (!physmap_data->set_vpp)
0105         return;
0106 
0107     info = platform_get_drvdata(pdev);
0108 
0109     spin_lock_irqsave(&info->vpp_lock, flags);
0110     if (state) {
0111         if (++info->vpp_refcnt == 1)    /* first nested 'on' */
0112             physmap_data->set_vpp(pdev, 1);
0113     } else {
0114         if (--info->vpp_refcnt == 0)    /* last nested 'off' */
0115             physmap_data->set_vpp(pdev, 0);
0116     }
0117     spin_unlock_irqrestore(&info->vpp_lock, flags);
0118 }
0119 
0120 #if IS_ENABLED(CONFIG_MTD_PHYSMAP_GPIO_ADDR)
0121 static void physmap_set_addr_gpios(struct physmap_flash_info *info,
0122                    unsigned long ofs)
0123 {
0124     unsigned int i;
0125 
0126     ofs >>= info->win_order;
0127     if (info->gpio_values == ofs)
0128         return;
0129 
0130     for (i = 0; i < info->gpios->ndescs; i++) {
0131         if ((BIT(i) & ofs) == (BIT(i) & info->gpio_values))
0132             continue;
0133 
0134         gpiod_set_value(info->gpios->desc[i], !!(BIT(i) & ofs));
0135     }
0136 
0137     info->gpio_values = ofs;
0138 }
0139 
0140 #define win_mask(order)     (BIT(order) - 1)
0141 
0142 static map_word physmap_addr_gpios_read(struct map_info *map,
0143                     unsigned long ofs)
0144 {
0145     struct platform_device *pdev;
0146     struct physmap_flash_info *info;
0147     map_word mw;
0148     u16 word;
0149 
0150     pdev = (struct platform_device *)map->map_priv_1;
0151     info = platform_get_drvdata(pdev);
0152     physmap_set_addr_gpios(info, ofs);
0153 
0154     word = readw(map->virt + (ofs & win_mask(info->win_order)));
0155     mw.x[0] = word;
0156     return mw;
0157 }
0158 
0159 static void physmap_addr_gpios_copy_from(struct map_info *map, void *buf,
0160                      unsigned long ofs, ssize_t len)
0161 {
0162     struct platform_device *pdev;
0163     struct physmap_flash_info *info;
0164 
0165     pdev = (struct platform_device *)map->map_priv_1;
0166     info = platform_get_drvdata(pdev);
0167 
0168     while (len) {
0169         unsigned int winofs = ofs & win_mask(info->win_order);
0170         unsigned int chunklen = min_t(unsigned int, len,
0171                           BIT(info->win_order) - winofs);
0172 
0173         physmap_set_addr_gpios(info, ofs);
0174         memcpy_fromio(buf, map->virt + winofs, chunklen);
0175         len -= chunklen;
0176         buf += chunklen;
0177         ofs += chunklen;
0178     }
0179 }
0180 
0181 static void physmap_addr_gpios_write(struct map_info *map, map_word mw,
0182                      unsigned long ofs)
0183 {
0184     struct platform_device *pdev;
0185     struct physmap_flash_info *info;
0186     u16 word;
0187 
0188     pdev = (struct platform_device *)map->map_priv_1;
0189     info = platform_get_drvdata(pdev);
0190     physmap_set_addr_gpios(info, ofs);
0191 
0192     word = mw.x[0];
0193     writew(word, map->virt + (ofs & win_mask(info->win_order)));
0194 }
0195 
0196 static void physmap_addr_gpios_copy_to(struct map_info *map, unsigned long ofs,
0197                        const void *buf, ssize_t len)
0198 {
0199     struct platform_device *pdev;
0200     struct physmap_flash_info *info;
0201 
0202     pdev = (struct platform_device *)map->map_priv_1;
0203     info = platform_get_drvdata(pdev);
0204 
0205     while (len) {
0206         unsigned int winofs = ofs & win_mask(info->win_order);
0207         unsigned int chunklen = min_t(unsigned int, len,
0208                           BIT(info->win_order) - winofs);
0209 
0210         physmap_set_addr_gpios(info, ofs);
0211         memcpy_toio(map->virt + winofs, buf, chunklen);
0212         len -= chunklen;
0213         buf += chunklen;
0214         ofs += chunklen;
0215     }
0216 }
0217 
0218 static int physmap_addr_gpios_map_init(struct map_info *map)
0219 {
0220     map->phys = NO_XIP;
0221     map->read = physmap_addr_gpios_read;
0222     map->copy_from = physmap_addr_gpios_copy_from;
0223     map->write = physmap_addr_gpios_write;
0224     map->copy_to = physmap_addr_gpios_copy_to;
0225 
0226     return 0;
0227 }
0228 #else
0229 static int physmap_addr_gpios_map_init(struct map_info *map)
0230 {
0231     return -ENOTSUPP;
0232 }
0233 #endif
0234 
0235 #if IS_ENABLED(CONFIG_MTD_PHYSMAP_OF)
0236 static const struct of_device_id of_flash_match[] = {
0237     {
0238         .compatible = "cfi-flash",
0239         .data = "cfi_probe",
0240     },
0241     {
0242         /*
0243          * FIXME: JEDEC chips can't be safely and reliably
0244          * probed, although the mtd code gets it right in
0245          * practice most of the time.  We should use the
0246          * vendor and device ids specified by the binding to
0247          * bypass the heuristic probe code, but the mtd layer
0248          * provides, at present, no interface for doing so
0249          * :(.
0250          */
0251         .compatible = "jedec-flash",
0252         .data = "jedec_probe",
0253     },
0254     {
0255         .compatible = "mtd-ram",
0256         .data = "map_ram",
0257     },
0258     {
0259         .compatible = "mtd-rom",
0260         .data = "map_rom",
0261     },
0262     {
0263         .type = "rom",
0264         .compatible = "direct-mapped"
0265     },
0266     { /* sentinel */ },
0267 };
0268 MODULE_DEVICE_TABLE(of, of_flash_match);
0269 
0270 static const char * const of_default_part_probes[] = {
0271     "cmdlinepart", "RedBoot", "ofpart", "ofoldpart", NULL
0272 };
0273 
0274 static const char * const *of_get_part_probes(struct platform_device *dev)
0275 {
0276     struct device_node *dp = dev->dev.of_node;
0277     const char **res;
0278     int count;
0279 
0280     count = of_property_count_strings(dp, "linux,part-probe");
0281     if (count < 0)
0282         return of_default_part_probes;
0283 
0284     res = devm_kcalloc(&dev->dev, count + 1, sizeof(*res), GFP_KERNEL);
0285     if (!res)
0286         return NULL;
0287 
0288     count = of_property_read_string_array(dp, "linux,part-probe", res,
0289                           count);
0290     if (count < 0)
0291         return NULL;
0292 
0293     return res;
0294 }
0295 
0296 static const char *of_select_probe_type(struct platform_device *dev)
0297 {
0298     struct device_node *dp = dev->dev.of_node;
0299     const struct of_device_id *match;
0300     const char *probe_type;
0301 
0302     match = of_match_device(of_flash_match, &dev->dev);
0303     probe_type = match->data;
0304     if (probe_type)
0305         return probe_type;
0306 
0307     dev_warn(&dev->dev,
0308          "Device tree uses obsolete \"direct-mapped\" flash binding\n");
0309 
0310     of_property_read_string(dp, "probe-type", &probe_type);
0311     if (!probe_type)
0312         return NULL;
0313 
0314     if (!strcmp(probe_type, "CFI")) {
0315         probe_type = "cfi_probe";
0316     } else if (!strcmp(probe_type, "JEDEC")) {
0317         probe_type = "jedec_probe";
0318     } else if (!strcmp(probe_type, "ROM")) {
0319         probe_type = "map_rom";
0320     } else {
0321         dev_warn(&dev->dev,
0322              "obsolete_probe: don't know probe type '%s', mapping as rom\n",
0323              probe_type);
0324         probe_type = "map_rom";
0325     }
0326 
0327     return probe_type;
0328 }
0329 
0330 static int physmap_flash_of_init(struct platform_device *dev)
0331 {
0332     struct physmap_flash_info *info = platform_get_drvdata(dev);
0333     struct device_node *dp = dev->dev.of_node;
0334     const char *mtd_name = NULL;
0335     int err, swap = 0;
0336     bool map_indirect;
0337     unsigned int i;
0338     u32 bankwidth;
0339 
0340     if (!dp)
0341         return -EINVAL;
0342 
0343     info->probe_type = of_select_probe_type(dev);
0344 
0345     info->part_types = of_get_part_probes(dev);
0346     if (!info->part_types)
0347         return -ENOMEM;
0348 
0349     of_property_read_string(dp, "linux,mtd-name", &mtd_name);
0350 
0351     map_indirect = of_property_read_bool(dp, "no-unaligned-direct-access");
0352 
0353     err = of_property_read_u32(dp, "bank-width", &bankwidth);
0354     if (err) {
0355         dev_err(&dev->dev, "Can't get bank width from device tree\n");
0356         return err;
0357     }
0358 
0359     if (of_property_read_bool(dp, "big-endian"))
0360         swap = CFI_BIG_ENDIAN;
0361     else if (of_property_read_bool(dp, "little-endian"))
0362         swap = CFI_LITTLE_ENDIAN;
0363 
0364     for (i = 0; i < info->nmaps; i++) {
0365         info->maps[i].name = mtd_name;
0366         info->maps[i].swap = swap;
0367         info->maps[i].bankwidth = bankwidth;
0368         info->maps[i].device_node = dp;
0369 
0370         err = of_flash_probe_bt1_rom(dev, dp, &info->maps[i]);
0371         if (err)
0372             return err;
0373 
0374         err = of_flash_probe_gemini(dev, dp, &info->maps[i]);
0375         if (err)
0376             return err;
0377 
0378         err = of_flash_probe_ixp4xx(dev, dp, &info->maps[i]);
0379         if (err)
0380             return err;
0381 
0382         err = of_flash_probe_versatile(dev, dp, &info->maps[i]);
0383         if (err)
0384             return err;
0385 
0386         /*
0387          * On some platforms (e.g. MPC5200) a direct 1:1 mapping
0388          * may cause problems with JFFS2 usage, as the local bus (LPB)
0389          * doesn't support unaligned accesses as implemented in the
0390          * JFFS2 code via memcpy(). By setting NO_XIP, the
0391          * flash will not be exposed directly to the MTD users
0392          * (e.g. JFFS2) any more.
0393          */
0394         if (map_indirect)
0395             info->maps[i].phys = NO_XIP;
0396     }
0397 
0398     return 0;
0399 }
0400 #else /* IS_ENABLED(CONFIG_MTD_PHYSMAP_OF) */
0401 #define of_flash_match NULL
0402 
0403 static int physmap_flash_of_init(struct platform_device *dev)
0404 {
0405     return -ENOTSUPP;
0406 }
0407 #endif /* IS_ENABLED(CONFIG_MTD_PHYSMAP_OF) */
0408 
0409 static const char * const rom_probe_types[] = {
0410     "cfi_probe", "jedec_probe", "qinfo_probe", "map_rom",
0411 };
0412 
0413 static const char * const part_probe_types[] = {
0414     "cmdlinepart", "RedBoot", "afs", NULL
0415 };
0416 
0417 static int physmap_flash_pdata_init(struct platform_device *dev)
0418 {
0419     struct physmap_flash_info *info = platform_get_drvdata(dev);
0420     struct physmap_flash_data *physmap_data;
0421     unsigned int i;
0422     int err;
0423 
0424     physmap_data = dev_get_platdata(&dev->dev);
0425     if (!physmap_data)
0426         return -EINVAL;
0427 
0428     info->probe_type = physmap_data->probe_type;
0429     info->part_types = physmap_data->part_probe_types ? : part_probe_types;
0430     info->parts = physmap_data->parts;
0431     info->nparts = physmap_data->nr_parts;
0432 
0433     if (physmap_data->init) {
0434         err = physmap_data->init(dev);
0435         if (err)
0436             return err;
0437     }
0438 
0439     for (i = 0; i < info->nmaps; i++) {
0440         info->maps[i].bankwidth = physmap_data->width;
0441         info->maps[i].pfow_base = physmap_data->pfow_base;
0442         info->maps[i].set_vpp = physmap_set_vpp;
0443     }
0444 
0445     return 0;
0446 }
0447 
0448 static int physmap_flash_probe(struct platform_device *dev)
0449 {
0450     struct physmap_flash_info *info;
0451     int err = 0;
0452     int i;
0453 
0454     if (!dev->dev.of_node && !dev_get_platdata(&dev->dev))
0455         return -EINVAL;
0456 
0457     info = devm_kzalloc(&dev->dev, sizeof(*info), GFP_KERNEL);
0458     if (!info)
0459         return -ENOMEM;
0460 
0461     while (platform_get_resource(dev, IORESOURCE_MEM, info->nmaps))
0462         info->nmaps++;
0463 
0464     if (!info->nmaps)
0465         return -ENODEV;
0466 
0467     info->maps = devm_kzalloc(&dev->dev,
0468                   sizeof(*info->maps) * info->nmaps,
0469                   GFP_KERNEL);
0470     if (!info->maps)
0471         return -ENOMEM;
0472 
0473     info->mtds = devm_kzalloc(&dev->dev,
0474                   sizeof(*info->mtds) * info->nmaps,
0475                   GFP_KERNEL);
0476     if (!info->mtds)
0477         return -ENOMEM;
0478 
0479     platform_set_drvdata(dev, info);
0480 
0481     info->gpios = devm_gpiod_get_array_optional(&dev->dev, "addr",
0482                             GPIOD_OUT_LOW);
0483     if (IS_ERR(info->gpios))
0484         return PTR_ERR(info->gpios);
0485 
0486     if (info->gpios && info->nmaps > 1) {
0487         dev_err(&dev->dev, "addr-gpios only supported for nmaps == 1\n");
0488         return -EINVAL;
0489     }
0490 
0491     pm_runtime_enable(&dev->dev);
0492     pm_runtime_get_sync(&dev->dev);
0493 
0494     if (dev->dev.of_node)
0495         err = physmap_flash_of_init(dev);
0496     else
0497         err = physmap_flash_pdata_init(dev);
0498 
0499     if (err) {
0500         pm_runtime_put(&dev->dev);
0501         pm_runtime_disable(&dev->dev);
0502         return err;
0503     }
0504 
0505     for (i = 0; i < info->nmaps; i++) {
0506         struct resource *res;
0507 
0508         res = platform_get_resource(dev, IORESOURCE_MEM, i);
0509         info->maps[i].virt = devm_ioremap_resource(&dev->dev, res);
0510         if (IS_ERR(info->maps[i].virt)) {
0511             err = PTR_ERR(info->maps[i].virt);
0512             goto err_out;
0513         }
0514 
0515         dev_notice(&dev->dev, "physmap platform flash device: %pR\n",
0516                res);
0517 
0518         if (!info->maps[i].name)
0519             info->maps[i].name = dev_name(&dev->dev);
0520 
0521         if (!info->maps[i].phys)
0522             info->maps[i].phys = res->start;
0523 
0524         info->win_order = get_bitmask_order(resource_size(res)) - 1;
0525         info->maps[i].size = BIT(info->win_order +
0526                      (info->gpios ?
0527                       info->gpios->ndescs : 0));
0528 
0529         info->maps[i].map_priv_1 = (unsigned long)dev;
0530 
0531         if (info->gpios) {
0532             err = physmap_addr_gpios_map_init(&info->maps[i]);
0533             if (err)
0534                 goto err_out;
0535         }
0536 
0537 #ifdef CONFIG_MTD_COMPLEX_MAPPINGS
0538         /*
0539          * Only use the simple_map implementation if map hooks are not
0540          * implemented. Since map->read() is mandatory checking for its
0541          * presence is enough.
0542          */
0543         if (!info->maps[i].read)
0544             simple_map_init(&info->maps[i]);
0545 #else
0546         simple_map_init(&info->maps[i]);
0547 #endif
0548 
0549         if (info->probe_type) {
0550             info->mtds[i] = do_map_probe(info->probe_type,
0551                              &info->maps[i]);
0552         } else {
0553             int j;
0554 
0555             for (j = 0; j < ARRAY_SIZE(rom_probe_types); j++) {
0556                 info->mtds[i] = do_map_probe(rom_probe_types[j],
0557                                  &info->maps[i]);
0558                 if (info->mtds[i])
0559                     break;
0560             }
0561         }
0562 
0563         if (!info->mtds[i]) {
0564             dev_err(&dev->dev, "map_probe failed\n");
0565             err = -ENXIO;
0566             goto err_out;
0567         }
0568         info->mtds[i]->dev.parent = &dev->dev;
0569     }
0570 
0571     if (info->nmaps == 1) {
0572         info->cmtd = info->mtds[0];
0573     } else {
0574         /*
0575          * We detected multiple devices. Concatenate them together.
0576          */
0577         info->cmtd = mtd_concat_create(info->mtds, info->nmaps,
0578                            dev_name(&dev->dev));
0579         if (!info->cmtd)
0580             err = -ENXIO;
0581     }
0582     if (err)
0583         goto err_out;
0584 
0585     spin_lock_init(&info->vpp_lock);
0586 
0587     mtd_set_of_node(info->cmtd, dev->dev.of_node);
0588     err = mtd_device_parse_register(info->cmtd, info->part_types, NULL,
0589                     info->parts, info->nparts);
0590     if (err)
0591         goto err_out;
0592 
0593     return 0;
0594 
0595 err_out:
0596     physmap_flash_remove(dev);
0597     return err;
0598 }
0599 
0600 #ifdef CONFIG_PM
0601 static void physmap_flash_shutdown(struct platform_device *dev)
0602 {
0603     struct physmap_flash_info *info = platform_get_drvdata(dev);
0604     int i;
0605 
0606     for (i = 0; i < info->nmaps && info->mtds[i]; i++)
0607         if (mtd_suspend(info->mtds[i]) == 0)
0608             mtd_resume(info->mtds[i]);
0609 }
0610 #else
0611 #define physmap_flash_shutdown NULL
0612 #endif
0613 
0614 static struct platform_driver physmap_flash_driver = {
0615     .probe      = physmap_flash_probe,
0616     .remove     = physmap_flash_remove,
0617     .shutdown   = physmap_flash_shutdown,
0618     .driver     = {
0619         .name   = "physmap-flash",
0620         .of_match_table = of_flash_match,
0621     },
0622 };
0623 
0624 #ifdef CONFIG_MTD_PHYSMAP_COMPAT
0625 static struct physmap_flash_data physmap_flash_data = {
0626     .width      = CONFIG_MTD_PHYSMAP_BANKWIDTH,
0627 };
0628 
0629 static struct resource physmap_flash_resource = {
0630     .start      = CONFIG_MTD_PHYSMAP_START,
0631     .end        = CONFIG_MTD_PHYSMAP_START + CONFIG_MTD_PHYSMAP_LEN - 1,
0632     .flags      = IORESOURCE_MEM,
0633 };
0634 
0635 static struct platform_device physmap_flash = {
0636     .name       = "physmap-flash",
0637     .id     = 0,
0638     .dev        = {
0639         .platform_data  = &physmap_flash_data,
0640     },
0641     .num_resources  = 1,
0642     .resource   = &physmap_flash_resource,
0643 };
0644 #endif
0645 
0646 static int __init physmap_init(void)
0647 {
0648     int err;
0649 
0650     err = platform_driver_register(&physmap_flash_driver);
0651 #ifdef CONFIG_MTD_PHYSMAP_COMPAT
0652     if (err == 0) {
0653         err = platform_device_register(&physmap_flash);
0654         if (err)
0655             platform_driver_unregister(&physmap_flash_driver);
0656     }
0657 #endif
0658 
0659     return err;
0660 }
0661 
0662 static void __exit physmap_exit(void)
0663 {
0664 #ifdef CONFIG_MTD_PHYSMAP_COMPAT
0665     platform_device_unregister(&physmap_flash);
0666 #endif
0667     platform_driver_unregister(&physmap_flash_driver);
0668 }
0669 
0670 module_init(physmap_init);
0671 module_exit(physmap_exit);
0672 
0673 MODULE_LICENSE("GPL");
0674 MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>");
0675 MODULE_AUTHOR("Vitaly Wool <vwool@ru.mvista.com>");
0676 MODULE_AUTHOR("Mike Frysinger <vapier@gentoo.org>");
0677 MODULE_DESCRIPTION("Generic configurable MTD map driver");
0678 
0679 /* legacy platform drivers can't hotplug or coldplg */
0680 #ifndef CONFIG_MTD_PHYSMAP_COMPAT
0681 /* work with hotplug and coldplug */
0682 MODULE_ALIAS("platform:physmap-flash");
0683 #endif