root/drivers/mtd/hyperbus/hyperbus-core.c

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

DEFINITIONS

This source file includes following definitions.
  1. map_to_hbdev
  2. hyperbus_read16
  3. hyperbus_write16
  4. hyperbus_copy_from
  5. hyperbus_copy_to
  6. hyperbus_register_device
  7. hyperbus_unregister_device

   1 // SPDX-License-Identifier: GPL-2.0
   2 //
   3 // Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com/
   4 // Author: Vignesh Raghavendra <vigneshr@ti.com>
   5 
   6 #include <linux/err.h>
   7 #include <linux/kernel.h>
   8 #include <linux/module.h>
   9 #include <linux/mtd/hyperbus.h>
  10 #include <linux/mtd/map.h>
  11 #include <linux/mtd/mtd.h>
  12 #include <linux/of.h>
  13 #include <linux/of_address.h>
  14 #include <linux/types.h>
  15 
  16 static struct hyperbus_device *map_to_hbdev(struct map_info *map)
  17 {
  18         return container_of(map, struct hyperbus_device, map);
  19 }
  20 
  21 static map_word hyperbus_read16(struct map_info *map, unsigned long addr)
  22 {
  23         struct hyperbus_device *hbdev = map_to_hbdev(map);
  24         struct hyperbus_ctlr *ctlr = hbdev->ctlr;
  25         map_word read_data;
  26 
  27         read_data.x[0] = ctlr->ops->read16(hbdev, addr);
  28 
  29         return read_data;
  30 }
  31 
  32 static void hyperbus_write16(struct map_info *map, map_word d,
  33                              unsigned long addr)
  34 {
  35         struct hyperbus_device *hbdev = map_to_hbdev(map);
  36         struct hyperbus_ctlr *ctlr = hbdev->ctlr;
  37 
  38         ctlr->ops->write16(hbdev, addr, d.x[0]);
  39 }
  40 
  41 static void hyperbus_copy_from(struct map_info *map, void *to,
  42                                unsigned long from, ssize_t len)
  43 {
  44         struct hyperbus_device *hbdev = map_to_hbdev(map);
  45         struct hyperbus_ctlr *ctlr = hbdev->ctlr;
  46 
  47         ctlr->ops->copy_from(hbdev, to, from, len);
  48 }
  49 
  50 static void hyperbus_copy_to(struct map_info *map, unsigned long to,
  51                              const void *from, ssize_t len)
  52 {
  53         struct hyperbus_device *hbdev = map_to_hbdev(map);
  54         struct hyperbus_ctlr *ctlr = hbdev->ctlr;
  55 
  56         ctlr->ops->copy_to(hbdev, to, from, len);
  57 }
  58 
  59 int hyperbus_register_device(struct hyperbus_device *hbdev)
  60 {
  61         const struct hyperbus_ops *ops;
  62         struct hyperbus_ctlr *ctlr;
  63         struct device_node *np;
  64         struct map_info *map;
  65         struct resource res;
  66         struct device *dev;
  67         int ret;
  68 
  69         if (!hbdev || !hbdev->np || !hbdev->ctlr || !hbdev->ctlr->dev) {
  70                 pr_err("hyperbus: please fill all the necessary fields!\n");
  71                 return -EINVAL;
  72         }
  73 
  74         np = hbdev->np;
  75         ctlr = hbdev->ctlr;
  76         if (!of_device_is_compatible(np, "cypress,hyperflash"))
  77                 return -ENODEV;
  78 
  79         hbdev->memtype = HYPERFLASH;
  80 
  81         ret = of_address_to_resource(np, 0, &res);
  82         if (ret)
  83                 return ret;
  84 
  85         dev = ctlr->dev;
  86         map = &hbdev->map;
  87         map->size = resource_size(&res);
  88         map->virt = devm_ioremap_resource(dev, &res);
  89         if (IS_ERR(map->virt))
  90                 return PTR_ERR(map->virt);
  91 
  92         map->name = dev_name(dev);
  93         map->bankwidth = 2;
  94         map->device_node = np;
  95 
  96         simple_map_init(map);
  97         ops = ctlr->ops;
  98         if (ops) {
  99                 if (ops->read16)
 100                         map->read = hyperbus_read16;
 101                 if (ops->write16)
 102                         map->write = hyperbus_write16;
 103                 if (ops->copy_to)
 104                         map->copy_to = hyperbus_copy_to;
 105                 if (ops->copy_from)
 106                         map->copy_from = hyperbus_copy_from;
 107 
 108                 if (ops->calibrate && !ctlr->calibrated) {
 109                         ret = ops->calibrate(hbdev);
 110                         if (!ret) {
 111                                 dev_err(dev, "Calibration failed\n");
 112                                 return -ENODEV;
 113                         }
 114                         ctlr->calibrated = true;
 115                 }
 116         }
 117 
 118         hbdev->mtd = do_map_probe("cfi_probe", map);
 119         if (!hbdev->mtd) {
 120                 dev_err(dev, "probing of hyperbus device failed\n");
 121                 return -ENODEV;
 122         }
 123 
 124         hbdev->mtd->dev.parent = dev;
 125         mtd_set_of_node(hbdev->mtd, np);
 126 
 127         ret = mtd_device_register(hbdev->mtd, NULL, 0);
 128         if (ret) {
 129                 dev_err(dev, "failed to register mtd device\n");
 130                 map_destroy(hbdev->mtd);
 131                 return ret;
 132         }
 133 
 134         return 0;
 135 }
 136 EXPORT_SYMBOL_GPL(hyperbus_register_device);
 137 
 138 int hyperbus_unregister_device(struct hyperbus_device *hbdev)
 139 {
 140         int ret = 0;
 141 
 142         if (hbdev && hbdev->mtd) {
 143                 ret = mtd_device_unregister(hbdev->mtd);
 144                 map_destroy(hbdev->mtd);
 145         }
 146 
 147         return ret;
 148 }
 149 EXPORT_SYMBOL_GPL(hyperbus_unregister_device);
 150 
 151 MODULE_DESCRIPTION("HyperBus Framework");
 152 MODULE_LICENSE("GPL v2");
 153 MODULE_AUTHOR("Vignesh Raghavendra <vigneshr@ti.com>");

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