root/drivers/mtd/maps/physmap-core.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. physmap_flash_remove
  2. physmap_set_vpp
  3. physmap_set_addr_gpios
  4. physmap_addr_gpios_read
  5. physmap_addr_gpios_copy_from
  6. physmap_addr_gpios_write
  7. physmap_addr_gpios_copy_to
  8. physmap_addr_gpios_map_init
  9. physmap_addr_gpios_map_init
  10. of_get_part_probes
  11. of_select_probe_type
  12. physmap_flash_of_init
  13. physmap_flash_of_init
  14. physmap_flash_pdata_init
  15. physmap_flash_probe
  16. physmap_flash_shutdown
  17. physmap_init
  18. physmap_exit

   1 // SPDX-License-Identifier: GPL-2.0+
   2 /*
   3  * Normal mappings of chips in physical memory
   4  *
   5  * Copyright (C) 2003 MontaVista Software Inc.
   6  * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
   7  *
   8  * 031022 - [jsun] add run-time configure and partition setup
   9  *
  10  * Device tree support:
  11  *    Copyright (C) 2006 MontaVista Software Inc.
  12  *    Author: Vitaly Wool <vwool@ru.mvista.com>
  13  *
  14  *    Revised to handle newer style flash binding by:
  15  *    Copyright (C) 2007 David Gibson, IBM Corporation.
  16  *
  17  * GPIO address extension:
  18  *    Handle the case where a flash device is mostly addressed using physical
  19  *    line and supplemented by GPIOs.  This way you can hook up say a 8MiB flash
  20  *    to a 2MiB memory range and use the GPIOs to select a particular range.
  21  *
  22  *    Copyright © 2000 Nicolas Pitre <nico@cam.org>
  23  *    Copyright © 2005-2009 Analog Devices Inc.
  24  */
  25 
  26 #include <linux/module.h>
  27 #include <linux/types.h>
  28 #include <linux/kernel.h>
  29 #include <linux/init.h>
  30 #include <linux/slab.h>
  31 #include <linux/device.h>
  32 #include <linux/platform_device.h>
  33 #include <linux/mtd/mtd.h>
  34 #include <linux/mtd/map.h>
  35 #include <linux/mtd/partitions.h>
  36 #include <linux/mtd/physmap.h>
  37 #include <linux/mtd/concat.h>
  38 #include <linux/mtd/cfi_endian.h>
  39 #include <linux/io.h>
  40 #include <linux/of_device.h>
  41 #include <linux/gpio/consumer.h>
  42 
  43 #include "physmap-gemini.h"
  44 #include "physmap-versatile.h"
  45 
  46 struct physmap_flash_info {
  47         unsigned int            nmaps;
  48         struct mtd_info         **mtds;
  49         struct mtd_info         *cmtd;
  50         struct map_info         *maps;
  51         spinlock_t              vpp_lock;
  52         int                     vpp_refcnt;
  53         const char              *probe_type;
  54         const char * const      *part_types;
  55         unsigned int            nparts;
  56         const struct mtd_partition *parts;
  57         struct gpio_descs       *gpios;
  58         unsigned int            gpio_values;
  59         unsigned int            win_order;
  60 };
  61 
  62 static int physmap_flash_remove(struct platform_device *dev)
  63 {
  64         struct physmap_flash_info *info;
  65         struct physmap_flash_data *physmap_data;
  66         int i, err;
  67 
  68         info = platform_get_drvdata(dev);
  69         if (!info)
  70                 return 0;
  71 
  72         if (info->cmtd) {
  73                 err = mtd_device_unregister(info->cmtd);
  74                 if (err)
  75                         return err;
  76 
  77                 if (info->cmtd != info->mtds[0])
  78                         mtd_concat_destroy(info->cmtd);
  79         }
  80 
  81         for (i = 0; i < info->nmaps; i++) {
  82                 if (info->mtds[i])
  83                         map_destroy(info->mtds[i]);
  84         }
  85 
  86         physmap_data = dev_get_platdata(&dev->dev);
  87         if (physmap_data && physmap_data->exit)
  88                 physmap_data->exit(dev);
  89 
  90         return 0;
  91 }
  92 
  93 static void physmap_set_vpp(struct map_info *map, int state)
  94 {
  95         struct platform_device *pdev;
  96         struct physmap_flash_data *physmap_data;
  97         struct physmap_flash_info *info;
  98         unsigned long flags;
  99 
 100         pdev = (struct platform_device *)map->map_priv_1;
 101         physmap_data = dev_get_platdata(&pdev->dev);
 102 
 103         if (!physmap_data->set_vpp)
 104                 return;
 105 
 106         info = platform_get_drvdata(pdev);
 107 
 108         spin_lock_irqsave(&info->vpp_lock, flags);
 109         if (state) {
 110                 if (++info->vpp_refcnt == 1)    /* first nested 'on' */
 111                         physmap_data->set_vpp(pdev, 1);
 112         } else {
 113                 if (--info->vpp_refcnt == 0)    /* last nested 'off' */
 114                         physmap_data->set_vpp(pdev, 0);
 115         }
 116         spin_unlock_irqrestore(&info->vpp_lock, flags);
 117 }
 118 
 119 #if IS_ENABLED(CONFIG_MTD_PHYSMAP_GPIO_ADDR)
 120 static void physmap_set_addr_gpios(struct physmap_flash_info *info,
 121                                    unsigned long ofs)
 122 {
 123         unsigned int i;
 124 
 125         ofs >>= info->win_order;
 126         if (info->gpio_values == ofs)
 127                 return;
 128 
 129         for (i = 0; i < info->gpios->ndescs; i++) {
 130                 if ((BIT(i) & ofs) == (BIT(i) & info->gpio_values))
 131                         continue;
 132 
 133                 gpiod_set_value(info->gpios->desc[i], !!(BIT(i) & ofs));
 134         }
 135 
 136         info->gpio_values = ofs;
 137 }
 138 
 139 #define win_mask(order)         (BIT(order) - 1)
 140 
 141 static map_word physmap_addr_gpios_read(struct map_info *map,
 142                                         unsigned long ofs)
 143 {
 144         struct platform_device *pdev;
 145         struct physmap_flash_info *info;
 146         map_word mw;
 147         u16 word;
 148 
 149         pdev = (struct platform_device *)map->map_priv_1;
 150         info = platform_get_drvdata(pdev);
 151         physmap_set_addr_gpios(info, ofs);
 152 
 153         word = readw(map->virt + (ofs & win_mask(info->win_order)));
 154         mw.x[0] = word;
 155         return mw;
 156 }
 157 
 158 static void physmap_addr_gpios_copy_from(struct map_info *map, void *buf,
 159                                          unsigned long ofs, ssize_t len)
 160 {
 161         struct platform_device *pdev;
 162         struct physmap_flash_info *info;
 163 
 164         pdev = (struct platform_device *)map->map_priv_1;
 165         info = platform_get_drvdata(pdev);
 166 
 167         while (len) {
 168                 unsigned int winofs = ofs & win_mask(info->win_order);
 169                 unsigned int chunklen = min_t(unsigned int, len,
 170                                               BIT(info->win_order) - winofs);
 171 
 172                 physmap_set_addr_gpios(info, ofs);
 173                 memcpy_fromio(buf, map->virt + winofs, chunklen);
 174                 len -= chunklen;
 175                 buf += chunklen;
 176                 ofs += chunklen;
 177         }
 178 }
 179 
 180 static void physmap_addr_gpios_write(struct map_info *map, map_word mw,
 181                                      unsigned long ofs)
 182 {
 183         struct platform_device *pdev;
 184         struct physmap_flash_info *info;
 185         u16 word;
 186 
 187         pdev = (struct platform_device *)map->map_priv_1;
 188         info = platform_get_drvdata(pdev);
 189         physmap_set_addr_gpios(info, ofs);
 190 
 191         word = mw.x[0];
 192         writew(word, map->virt + (ofs & win_mask(info->win_order)));
 193 }
 194 
 195 static void physmap_addr_gpios_copy_to(struct map_info *map, unsigned long ofs,
 196                                        const void *buf, ssize_t len)
 197 {
 198         struct platform_device *pdev;
 199         struct physmap_flash_info *info;
 200 
 201         pdev = (struct platform_device *)map->map_priv_1;
 202         info = platform_get_drvdata(pdev);
 203 
 204         while (len) {
 205                 unsigned int winofs = ofs & win_mask(info->win_order);
 206                 unsigned int chunklen = min_t(unsigned int, len,
 207                                               BIT(info->win_order) - winofs);
 208 
 209                 physmap_set_addr_gpios(info, ofs);
 210                 memcpy_toio(map->virt + winofs, buf, chunklen);
 211                 len -= chunklen;
 212                 buf += chunklen;
 213                 ofs += chunklen;
 214         }
 215 }
 216 
 217 static int physmap_addr_gpios_map_init(struct map_info *map)
 218 {
 219         map->phys = NO_XIP;
 220         map->read = physmap_addr_gpios_read;
 221         map->copy_from = physmap_addr_gpios_copy_from;
 222         map->write = physmap_addr_gpios_write;
 223         map->copy_to = physmap_addr_gpios_copy_to;
 224 
 225         return 0;
 226 }
 227 #else
 228 static int physmap_addr_gpios_map_init(struct map_info *map)
 229 {
 230         return -ENOTSUPP;
 231 }
 232 #endif
 233 
 234 #if IS_ENABLED(CONFIG_MTD_PHYSMAP_OF)
 235 static const struct of_device_id of_flash_match[] = {
 236         {
 237                 .compatible = "cfi-flash",
 238                 .data = "cfi_probe",
 239         },
 240         {
 241                 /*
 242                  * FIXME: JEDEC chips can't be safely and reliably
 243                  * probed, although the mtd code gets it right in
 244                  * practice most of the time.  We should use the
 245                  * vendor and device ids specified by the binding to
 246                  * bypass the heuristic probe code, but the mtd layer
 247                  * provides, at present, no interface for doing so
 248                  * :(.
 249                  */
 250                 .compatible = "jedec-flash",
 251                 .data = "jedec_probe",
 252         },
 253         {
 254                 .compatible = "mtd-ram",
 255                 .data = "map_ram",
 256         },
 257         {
 258                 .compatible = "mtd-rom",
 259                 .data = "map_rom",
 260         },
 261         {
 262                 .type = "rom",
 263                 .compatible = "direct-mapped"
 264         },
 265         { /* sentinel */ },
 266 };
 267 MODULE_DEVICE_TABLE(of, of_flash_match);
 268 
 269 static const char * const of_default_part_probes[] = {
 270         "cmdlinepart", "RedBoot", "ofpart", "ofoldpart", NULL
 271 };
 272 
 273 static const char * const *of_get_part_probes(struct platform_device *dev)
 274 {
 275         struct device_node *dp = dev->dev.of_node;
 276         const char **res;
 277         int count;
 278 
 279         count = of_property_count_strings(dp, "linux,part-probe");
 280         if (count < 0)
 281                 return of_default_part_probes;
 282 
 283         res = devm_kcalloc(&dev->dev, count + 1, sizeof(*res), GFP_KERNEL);
 284         if (!res)
 285                 return NULL;
 286 
 287         count = of_property_read_string_array(dp, "linux,part-probe", res,
 288                                               count);
 289         if (count < 0)
 290                 return NULL;
 291 
 292         return res;
 293 }
 294 
 295 static const char *of_select_probe_type(struct platform_device *dev)
 296 {
 297         struct device_node *dp = dev->dev.of_node;
 298         const struct of_device_id *match;
 299         const char *probe_type;
 300 
 301         match = of_match_device(of_flash_match, &dev->dev);
 302         probe_type = match->data;
 303         if (probe_type)
 304                 return probe_type;
 305 
 306         dev_warn(&dev->dev,
 307                  "Device tree uses obsolete \"direct-mapped\" flash binding\n");
 308 
 309         of_property_read_string(dp, "probe-type", &probe_type);
 310         if (!probe_type)
 311                 return NULL;
 312 
 313         if (!strcmp(probe_type, "CFI")) {
 314                 probe_type = "cfi_probe";
 315         } else if (!strcmp(probe_type, "JEDEC")) {
 316                 probe_type = "jedec_probe";
 317         } else if (!strcmp(probe_type, "ROM")) {
 318                 probe_type = "map_rom";
 319         } else {
 320                 dev_warn(&dev->dev,
 321                          "obsolete_probe: don't know probe type '%s', mapping as rom\n",
 322                          probe_type);
 323                 probe_type = "map_rom";
 324         }
 325 
 326         return probe_type;
 327 }
 328 
 329 static int physmap_flash_of_init(struct platform_device *dev)
 330 {
 331         struct physmap_flash_info *info = platform_get_drvdata(dev);
 332         struct device_node *dp = dev->dev.of_node;
 333         const char *mtd_name = NULL;
 334         int err, swap = 0;
 335         bool map_indirect;
 336         unsigned int i;
 337         u32 bankwidth;
 338 
 339         if (!dp)
 340                 return -EINVAL;
 341 
 342         info->probe_type = of_select_probe_type(dev);
 343 
 344         info->part_types = of_get_part_probes(dev);
 345         if (!info->part_types)
 346                 return -ENOMEM;
 347 
 348         of_property_read_string(dp, "linux,mtd-name", &mtd_name);
 349 
 350         map_indirect = of_property_read_bool(dp, "no-unaligned-direct-access");
 351 
 352         err = of_property_read_u32(dp, "bank-width", &bankwidth);
 353         if (err) {
 354                 dev_err(&dev->dev, "Can't get bank width from device tree\n");
 355                 return err;
 356         }
 357 
 358         if (of_property_read_bool(dp, "big-endian"))
 359                 swap = CFI_BIG_ENDIAN;
 360         else if (of_property_read_bool(dp, "little-endian"))
 361                 swap = CFI_LITTLE_ENDIAN;
 362 
 363         for (i = 0; i < info->nmaps; i++) {
 364                 info->maps[i].name = mtd_name;
 365                 info->maps[i].swap = swap;
 366                 info->maps[i].bankwidth = bankwidth;
 367                 info->maps[i].device_node = dp;
 368 
 369                 err = of_flash_probe_gemini(dev, dp, &info->maps[i]);
 370                 if (err)
 371                         return err;
 372 
 373                 err = of_flash_probe_versatile(dev, dp, &info->maps[i]);
 374                 if (err)
 375                         return err;
 376 
 377                 /*
 378                  * On some platforms (e.g. MPC5200) a direct 1:1 mapping
 379                  * may cause problems with JFFS2 usage, as the local bus (LPB)
 380                  * doesn't support unaligned accesses as implemented in the
 381                  * JFFS2 code via memcpy(). By setting NO_XIP, the
 382                  * flash will not be exposed directly to the MTD users
 383                  * (e.g. JFFS2) any more.
 384                  */
 385                 if (map_indirect)
 386                         info->maps[i].phys = NO_XIP;
 387         }
 388 
 389         return 0;
 390 }
 391 #else /* IS_ENABLED(CONFIG_MTD_PHYSMAP_OF) */
 392 #define of_flash_match NULL
 393 
 394 static int physmap_flash_of_init(struct platform_device *dev)
 395 {
 396         return -ENOTSUPP;
 397 }
 398 #endif /* IS_ENABLED(CONFIG_MTD_PHYSMAP_OF) */
 399 
 400 static const char * const rom_probe_types[] = {
 401         "cfi_probe", "jedec_probe", "qinfo_probe", "map_rom",
 402 };
 403 
 404 static const char * const part_probe_types[] = {
 405         "cmdlinepart", "RedBoot", "afs", NULL
 406 };
 407 
 408 static int physmap_flash_pdata_init(struct platform_device *dev)
 409 {
 410         struct physmap_flash_info *info = platform_get_drvdata(dev);
 411         struct physmap_flash_data *physmap_data;
 412         unsigned int i;
 413         int err;
 414 
 415         physmap_data = dev_get_platdata(&dev->dev);
 416         if (!physmap_data)
 417                 return -EINVAL;
 418 
 419         info->probe_type = physmap_data->probe_type;
 420         info->part_types = physmap_data->part_probe_types ? : part_probe_types;
 421         info->parts = physmap_data->parts;
 422         info->nparts = physmap_data->nr_parts;
 423 
 424         if (physmap_data->init) {
 425                 err = physmap_data->init(dev);
 426                 if (err)
 427                         return err;
 428         }
 429 
 430         for (i = 0; i < info->nmaps; i++) {
 431                 info->maps[i].bankwidth = physmap_data->width;
 432                 info->maps[i].pfow_base = physmap_data->pfow_base;
 433                 info->maps[i].set_vpp = physmap_set_vpp;
 434         }
 435 
 436         return 0;
 437 }
 438 
 439 static int physmap_flash_probe(struct platform_device *dev)
 440 {
 441         struct physmap_flash_info *info;
 442         int err = 0;
 443         int i;
 444 
 445         if (!dev->dev.of_node && !dev_get_platdata(&dev->dev))
 446                 return -EINVAL;
 447 
 448         info = devm_kzalloc(&dev->dev, sizeof(*info), GFP_KERNEL);
 449         if (!info)
 450                 return -ENOMEM;
 451 
 452         while (platform_get_resource(dev, IORESOURCE_MEM, info->nmaps))
 453                 info->nmaps++;
 454 
 455         if (!info->nmaps)
 456                 return -ENODEV;
 457 
 458         info->maps = devm_kzalloc(&dev->dev,
 459                                   sizeof(*info->maps) * info->nmaps,
 460                                   GFP_KERNEL);
 461         if (!info->maps)
 462                 return -ENOMEM;
 463 
 464         info->mtds = devm_kzalloc(&dev->dev,
 465                                   sizeof(*info->mtds) * info->nmaps,
 466                                   GFP_KERNEL);
 467         if (!info->mtds)
 468                 return -ENOMEM;
 469 
 470         platform_set_drvdata(dev, info);
 471 
 472         info->gpios = devm_gpiod_get_array_optional(&dev->dev, "addr",
 473                                                     GPIOD_OUT_LOW);
 474         if (IS_ERR(info->gpios))
 475                 return PTR_ERR(info->gpios);
 476 
 477         if (info->gpios && info->nmaps > 1) {
 478                 dev_err(&dev->dev, "addr-gpios only supported for nmaps == 1\n");
 479                 return -EINVAL;
 480         }
 481 
 482         if (dev->dev.of_node)
 483                 err = physmap_flash_of_init(dev);
 484         else
 485                 err = physmap_flash_pdata_init(dev);
 486 
 487         if (err)
 488                 return err;
 489 
 490         for (i = 0; i < info->nmaps; i++) {
 491                 struct resource *res;
 492 
 493                 res = platform_get_resource(dev, IORESOURCE_MEM, i);
 494                 info->maps[i].virt = devm_ioremap_resource(&dev->dev, res);
 495                 if (IS_ERR(info->maps[i].virt)) {
 496                         err = PTR_ERR(info->maps[i].virt);
 497                         goto err_out;
 498                 }
 499 
 500                 dev_notice(&dev->dev, "physmap platform flash device: %pR\n",
 501                            res);
 502 
 503                 info->maps[i].name = dev_name(&dev->dev);
 504 
 505                 if (!info->maps[i].phys)
 506                         info->maps[i].phys = res->start;
 507 
 508                 info->win_order = get_bitmask_order(resource_size(res)) - 1;
 509                 info->maps[i].size = BIT(info->win_order +
 510                                          (info->gpios ?
 511                                           info->gpios->ndescs : 0));
 512 
 513                 info->maps[i].map_priv_1 = (unsigned long)dev;
 514 
 515                 if (info->gpios) {
 516                         err = physmap_addr_gpios_map_init(&info->maps[i]);
 517                         if (err)
 518                                 goto err_out;
 519                 }
 520 
 521 #ifdef CONFIG_MTD_COMPLEX_MAPPINGS
 522                 /*
 523                  * Only use the simple_map implementation if map hooks are not
 524                  * implemented. Since map->read() is mandatory checking for its
 525                  * presence is enough.
 526                  */
 527                 if (!info->maps[i].read)
 528                         simple_map_init(&info->maps[i]);
 529 #else
 530                 simple_map_init(&info->maps[i]);
 531 #endif
 532 
 533                 if (info->probe_type) {
 534                         info->mtds[i] = do_map_probe(info->probe_type,
 535                                                      &info->maps[i]);
 536                 } else {
 537                         int j;
 538 
 539                         for (j = 0; j < ARRAY_SIZE(rom_probe_types); j++) {
 540                                 info->mtds[i] = do_map_probe(rom_probe_types[j],
 541                                                              &info->maps[i]);
 542                                 if (info->mtds[i])
 543                                         break;
 544                         }
 545                 }
 546 
 547                 if (!info->mtds[i]) {
 548                         dev_err(&dev->dev, "map_probe failed\n");
 549                         err = -ENXIO;
 550                         goto err_out;
 551                 }
 552                 info->mtds[i]->dev.parent = &dev->dev;
 553         }
 554 
 555         if (info->nmaps == 1) {
 556                 info->cmtd = info->mtds[0];
 557         } else {
 558                 /*
 559                  * We detected multiple devices. Concatenate them together.
 560                  */
 561                 info->cmtd = mtd_concat_create(info->mtds, info->nmaps,
 562                                                dev_name(&dev->dev));
 563                 if (!info->cmtd)
 564                         err = -ENXIO;
 565         }
 566         if (err)
 567                 goto err_out;
 568 
 569         spin_lock_init(&info->vpp_lock);
 570 
 571         mtd_set_of_node(info->cmtd, dev->dev.of_node);
 572         err = mtd_device_parse_register(info->cmtd, info->part_types, NULL,
 573                                         info->parts, info->nparts);
 574         if (err)
 575                 goto err_out;
 576 
 577         return 0;
 578 
 579 err_out:
 580         physmap_flash_remove(dev);
 581         return err;
 582 }
 583 
 584 #ifdef CONFIG_PM
 585 static void physmap_flash_shutdown(struct platform_device *dev)
 586 {
 587         struct physmap_flash_info *info = platform_get_drvdata(dev);
 588         int i;
 589 
 590         for (i = 0; i < info->nmaps && info->mtds[i]; i++)
 591                 if (mtd_suspend(info->mtds[i]) == 0)
 592                         mtd_resume(info->mtds[i]);
 593 }
 594 #else
 595 #define physmap_flash_shutdown NULL
 596 #endif
 597 
 598 static struct platform_driver physmap_flash_driver = {
 599         .probe          = physmap_flash_probe,
 600         .remove         = physmap_flash_remove,
 601         .shutdown       = physmap_flash_shutdown,
 602         .driver         = {
 603                 .name   = "physmap-flash",
 604                 .of_match_table = of_flash_match,
 605         },
 606 };
 607 
 608 #ifdef CONFIG_MTD_PHYSMAP_COMPAT
 609 static struct physmap_flash_data physmap_flash_data = {
 610         .width          = CONFIG_MTD_PHYSMAP_BANKWIDTH,
 611 };
 612 
 613 static struct resource physmap_flash_resource = {
 614         .start          = CONFIG_MTD_PHYSMAP_START,
 615         .end            = CONFIG_MTD_PHYSMAP_START + CONFIG_MTD_PHYSMAP_LEN - 1,
 616         .flags          = IORESOURCE_MEM,
 617 };
 618 
 619 static struct platform_device physmap_flash = {
 620         .name           = "physmap-flash",
 621         .id             = 0,
 622         .dev            = {
 623                 .platform_data  = &physmap_flash_data,
 624         },
 625         .num_resources  = 1,
 626         .resource       = &physmap_flash_resource,
 627 };
 628 #endif
 629 
 630 static int __init physmap_init(void)
 631 {
 632         int err;
 633 
 634         err = platform_driver_register(&physmap_flash_driver);
 635 #ifdef CONFIG_MTD_PHYSMAP_COMPAT
 636         if (err == 0) {
 637                 err = platform_device_register(&physmap_flash);
 638                 if (err)
 639                         platform_driver_unregister(&physmap_flash_driver);
 640         }
 641 #endif
 642 
 643         return err;
 644 }
 645 
 646 static void __exit physmap_exit(void)
 647 {
 648 #ifdef CONFIG_MTD_PHYSMAP_COMPAT
 649         platform_device_unregister(&physmap_flash);
 650 #endif
 651         platform_driver_unregister(&physmap_flash_driver);
 652 }
 653 
 654 module_init(physmap_init);
 655 module_exit(physmap_exit);
 656 
 657 MODULE_LICENSE("GPL");
 658 MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>");
 659 MODULE_AUTHOR("Vitaly Wool <vwool@ru.mvista.com>");
 660 MODULE_AUTHOR("Mike Frysinger <vapier@gentoo.org>");
 661 MODULE_DESCRIPTION("Generic configurable MTD map driver");
 662 
 663 /* legacy platform drivers can't hotplug or coldplg */
 664 #ifndef CONFIG_MTD_PHYSMAP_COMPAT
 665 /* work with hotplug and coldplug */
 666 MODULE_ALIAS("platform:physmap-flash");
 667 #endif

/* [<][>][^][v][top][bottom][index][help] */