1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * rbtx4939-flash (based on physmap.c) 4 * 5 * This is a simplified physmap driver with map_init callback function. 6 * 7 * Copyright (C) 2009 Atsushi Nemoto <anemo@mba.ocn.ne.jp> 8 */ 9 10#include <linux/module.h> 11#include <linux/types.h> 12#include <linux/kernel.h> 13#include <linux/slab.h> 14#include <linux/device.h> 15#include <linux/platform_device.h> 16#include <linux/mtd/mtd.h> 17#include <linux/mtd/map.h> 18#include <linux/mtd/partitions.h> 19#include <asm/txx9/rbtx4939.h> 20 21struct rbtx4939_flash_info { 22 struct mtd_info *mtd; 23 struct map_info map; 24}; 25 26static int rbtx4939_flash_remove(struct platform_device *dev) 27{ 28 struct rbtx4939_flash_info *info; 29 30 info = platform_get_drvdata(dev); 31 if (!info) 32 return 0; 33 34 if (info->mtd) { 35 mtd_device_unregister(info->mtd); 36 map_destroy(info->mtd); 37 } 38 return 0; 39} 40 41static const char * const rom_probe_types[] = { 42 "cfi_probe", "jedec_probe", NULL }; 43 44static int rbtx4939_flash_probe(struct platform_device *dev) 45{ 46 struct rbtx4939_flash_data *pdata; 47 struct rbtx4939_flash_info *info; 48 struct resource *res; 49 const char * const *probe_type; 50 int err = 0; 51 unsigned long size; 52 53 pdata = dev_get_platdata(&dev->dev); 54 if (!pdata) 55 return -ENODEV; 56 57 res = platform_get_resource(dev, IORESOURCE_MEM, 0); 58 if (!res) 59 return -ENODEV; 60 info = devm_kzalloc(&dev->dev, sizeof(struct rbtx4939_flash_info), 61 GFP_KERNEL); 62 if (!info) 63 return -ENOMEM; 64 65 platform_set_drvdata(dev, info); 66 67 size = resource_size(res); 68 pr_notice("rbtx4939 platform flash device: %pR\n", res); 69 70 if (!devm_request_mem_region(&dev->dev, res->start, size, 71 dev_name(&dev->dev))) 72 return -EBUSY; 73 74 info->map.name = dev_name(&dev->dev); 75 info->map.phys = res->start; 76 info->map.size = size; 77 info->map.bankwidth = pdata->width; 78 79 info->map.virt = devm_ioremap(&dev->dev, info->map.phys, size); 80 if (!info->map.virt) 81 return -EBUSY; 82 83 if (pdata->map_init) 84 (*pdata->map_init)(&info->map); 85 else 86 simple_map_init(&info->map); 87 88 probe_type = rom_probe_types; 89 for (; !info->mtd && *probe_type; probe_type++) 90 info->mtd = do_map_probe(*probe_type, &info->map); 91 if (!info->mtd) { 92 dev_err(&dev->dev, "map_probe failed\n"); 93 err = -ENXIO; 94 goto err_out; 95 } 96 info->mtd->dev.parent = &dev->dev; 97 err = mtd_device_register(info->mtd, pdata->parts, pdata->nr_parts); 98 99 if (err) 100 goto err_out; 101 return 0; 102 103err_out: 104 rbtx4939_flash_remove(dev); 105 return err; 106} 107 108#ifdef CONFIG_PM 109static void rbtx4939_flash_shutdown(struct platform_device *dev) 110{ 111 struct rbtx4939_flash_info *info = platform_get_drvdata(dev); 112 113 if (mtd_suspend(info->mtd) == 0) 114 mtd_resume(info->mtd); 115} 116#else 117#define rbtx4939_flash_shutdown NULL 118#endif 119 120static struct platform_driver rbtx4939_flash_driver = { 121 .probe = rbtx4939_flash_probe, 122 .remove = rbtx4939_flash_remove, 123 .shutdown = rbtx4939_flash_shutdown, 124 .driver = { 125 .name = "rbtx4939-flash", 126 }, 127}; 128 129module_platform_driver(rbtx4939_flash_driver); 130 131MODULE_LICENSE("GPL"); 132MODULE_DESCRIPTION("RBTX4939 MTD map driver"); 133MODULE_ALIAS("platform:rbtx4939-flash"); 134