^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /* sun_uflash.c - Driver for user-programmable flash on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Sun Microsystems SME boardsets.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * This driver does NOT provide access to the OBP-flash for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * safety reasons-- use <linux>/drivers/sbus/char/flash.c instead.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Copyright (c) 2001 Eric Brower (ebrower@usa.net)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/fs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/ioport.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/of.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/of_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <asm/prom.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/uaccess.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <asm/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/mtd/mtd.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/mtd/map.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #define UFLASH_OBPNAME "flashprom"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #define DRIVER_NAME "sun_uflash"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #define PFX DRIVER_NAME ": "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #define UFLASH_WINDOW_SIZE 0x200000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #define UFLASH_BUSWIDTH 1 /* EBus is 8-bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) MODULE_AUTHOR("Eric Brower <ebrower@usa.net>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) MODULE_DESCRIPTION("User-programmable flash device on Sun Microsystems boardsets");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) MODULE_SUPPORTED_DEVICE(DRIVER_NAME);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) MODULE_VERSION("2.1");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) struct uflash_dev {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) const char *name; /* device name */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) struct map_info map; /* mtd map info */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) struct mtd_info *mtd; /* mtd info */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) struct map_info uflash_map_templ = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) .name = "SUNW,???-????",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) .size = UFLASH_WINDOW_SIZE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) .bankwidth = UFLASH_BUSWIDTH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) int uflash_devinit(struct platform_device *op, struct device_node *dp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) struct uflash_dev *up;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) if (op->resource[1].flags) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) /* Non-CFI userflash device-- once I find one we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) * can work on supporting it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) printk(KERN_ERR PFX "Unsupported device at %pOF, 0x%llx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) dp, (unsigned long long)op->resource[0].start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) up = kzalloc(sizeof(struct uflash_dev), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) if (!up) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) printk(KERN_ERR PFX "Cannot allocate struct uflash_dev\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) /* copy defaults and tweak parameters */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) memcpy(&up->map, &uflash_map_templ, sizeof(uflash_map_templ));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) up->map.size = resource_size(&op->resource[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) up->name = of_get_property(dp, "model", NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) if (up->name && 0 < strlen(up->name))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) up->map.name = up->name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) up->map.phys = op->resource[0].start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) up->map.virt = of_ioremap(&op->resource[0], 0, up->map.size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) DRIVER_NAME);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) if (!up->map.virt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) printk(KERN_ERR PFX "Failed to map device.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) kfree(up);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) simple_map_init(&up->map);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) /* MTD registration */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) up->mtd = do_map_probe("cfi_probe", &up->map);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) if (!up->mtd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) of_iounmap(&op->resource[0], up->map.virt, up->map.size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) kfree(up);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) return -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) up->mtd->owner = THIS_MODULE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) mtd_device_register(up->mtd, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) dev_set_drvdata(&op->dev, up);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) static int uflash_probe(struct platform_device *op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) struct device_node *dp = op->dev.of_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) /* Flashprom must have the "user" property in order to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) * be used by this driver.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) if (!of_find_property(dp, "user", NULL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) return uflash_devinit(op, dp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) static int uflash_remove(struct platform_device *op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) struct uflash_dev *up = dev_get_drvdata(&op->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) if (up->mtd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) mtd_device_unregister(up->mtd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) map_destroy(up->mtd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) if (up->map.virt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) of_iounmap(&op->resource[0], up->map.virt, up->map.size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) up->map.virt = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) kfree(up);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) static const struct of_device_id uflash_match[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) .name = UFLASH_OBPNAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) {},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) MODULE_DEVICE_TABLE(of, uflash_match);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) static struct platform_driver uflash_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) .name = DRIVER_NAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) .of_match_table = uflash_match,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) .probe = uflash_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) .remove = uflash_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) module_platform_driver(uflash_driver);