linux/drivers/mtd/maps/physmap-gemini.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * Cortina Systems Gemini OF physmap add-on
   4 * Copyright (C) 2017 Linus Walleij <linus.walleij@linaro.org>
   5 *
   6 * This SoC has an elaborate flash control register, so we need to
   7 * detect and set it up when booting on this platform.
   8 */
   9#include <linux/export.h>
  10#include <linux/of.h>
  11#include <linux/of_device.h>
  12#include <linux/mtd/map.h>
  13#include <linux/mtd/xip.h>
  14#include <linux/mfd/syscon.h>
  15#include <linux/regmap.h>
  16#include <linux/bitops.h>
  17#include <linux/pinctrl/consumer.h>
  18#include "physmap-gemini.h"
  19
  20/*
  21 * The Flash-relevant parts of the global status register
  22 * These would also be relevant for a NAND driver.
  23 */
  24#define GLOBAL_STATUS                   0x04
  25#define FLASH_TYPE_MASK                 (0x3 << 24)
  26#define FLASH_TYPE_NAND_2K              (0x3 << 24)
  27#define FLASH_TYPE_NAND_512             (0x2 << 24)
  28#define FLASH_TYPE_PARALLEL             (0x1 << 24)
  29#define FLASH_TYPE_SERIAL               (0x0 << 24)
  30/* if parallel */
  31#define FLASH_WIDTH_16BIT               (1 << 23)       /* else 8 bit */
  32/* if serial */
  33#define FLASH_ATMEL                     (1 << 23)       /* else STM */
  34
  35#define FLASH_SIZE_MASK                 (0x3 << 21)
  36#define NAND_256M                       (0x3 << 21)     /* and more */
  37#define NAND_128M                       (0x2 << 21)
  38#define NAND_64M                        (0x1 << 21)
  39#define NAND_32M                        (0x0 << 21)
  40#define ATMEL_16M                       (0x3 << 21)     /* and more */
  41#define ATMEL_8M                        (0x2 << 21)
  42#define ATMEL_4M_2M                     (0x1 << 21)
  43#define ATMEL_1M                        (0x0 << 21)     /* and less */
  44#define STM_32M                         (1 << 22)       /* and more */
  45#define STM_16M                         (0 << 22)       /* and less */
  46
  47#define FLASH_PARALLEL_HIGH_PIN_CNT     (1 << 20)       /* else low pin cnt */
  48
  49struct gemini_flash {
  50        struct device *dev;
  51        struct pinctrl *p;
  52        struct pinctrl_state *enabled_state;
  53        struct pinctrl_state *disabled_state;
  54};
  55
  56/* Static local state */
  57static struct gemini_flash *gf;
  58
  59static void gemini_flash_enable_pins(void)
  60{
  61        int ret;
  62
  63        if (IS_ERR(gf->enabled_state))
  64                return;
  65        ret = pinctrl_select_state(gf->p, gf->enabled_state);
  66        if (ret)
  67                dev_err(gf->dev, "failed to enable pins\n");
  68}
  69
  70static void gemini_flash_disable_pins(void)
  71{
  72        int ret;
  73
  74        if (IS_ERR(gf->disabled_state))
  75                return;
  76        ret = pinctrl_select_state(gf->p, gf->disabled_state);
  77        if (ret)
  78                dev_err(gf->dev, "failed to disable pins\n");
  79}
  80
  81static map_word __xipram gemini_flash_map_read(struct map_info *map,
  82                                               unsigned long ofs)
  83{
  84        map_word ret;
  85
  86        gemini_flash_enable_pins();
  87        ret = inline_map_read(map, ofs);
  88        gemini_flash_disable_pins();
  89
  90        return ret;
  91}
  92
  93static void __xipram gemini_flash_map_write(struct map_info *map,
  94                                            const map_word datum,
  95                                            unsigned long ofs)
  96{
  97        gemini_flash_enable_pins();
  98        inline_map_write(map, datum, ofs);
  99        gemini_flash_disable_pins();
 100}
 101
 102static void __xipram gemini_flash_map_copy_from(struct map_info *map,
 103                                                void *to, unsigned long from,
 104                                                ssize_t len)
 105{
 106        gemini_flash_enable_pins();
 107        inline_map_copy_from(map, to, from, len);
 108        gemini_flash_disable_pins();
 109}
 110
 111static void __xipram gemini_flash_map_copy_to(struct map_info *map,
 112                                              unsigned long to,
 113                                              const void *from, ssize_t len)
 114{
 115        gemini_flash_enable_pins();
 116        inline_map_copy_to(map, to, from, len);
 117        gemini_flash_disable_pins();
 118}
 119
 120int of_flash_probe_gemini(struct platform_device *pdev,
 121                          struct device_node *np,
 122                          struct map_info *map)
 123{
 124        struct regmap *rmap;
 125        struct device *dev = &pdev->dev;
 126        u32 val;
 127        int ret;
 128
 129        /* Multiplatform guard */
 130        if (!of_device_is_compatible(np, "cortina,gemini-flash"))
 131                return 0;
 132
 133        gf = devm_kzalloc(dev, sizeof(*gf), GFP_KERNEL);
 134        if (!gf)
 135                return -ENOMEM;
 136        gf->dev = dev;
 137
 138        rmap = syscon_regmap_lookup_by_phandle(np, "syscon");
 139        if (IS_ERR(rmap)) {
 140                dev_err(dev, "no syscon\n");
 141                return PTR_ERR(rmap);
 142        }
 143
 144        ret = regmap_read(rmap, GLOBAL_STATUS, &val);
 145        if (ret) {
 146                dev_err(dev, "failed to read global status register\n");
 147                return -ENODEV;
 148        }
 149        dev_dbg(dev, "global status reg: %08x\n", val);
 150
 151        /*
 152         * It would be contradictory if a physmap flash was NOT parallel.
 153         */
 154        if ((val & FLASH_TYPE_MASK) != FLASH_TYPE_PARALLEL) {
 155                dev_err(dev, "flash is not parallel\n");
 156                return -ENODEV;
 157        }
 158
 159        /*
 160         * Complain if DT data and hardware definition is different.
 161         */
 162        if (val & FLASH_WIDTH_16BIT) {
 163                if (map->bankwidth != 2)
 164                        dev_warn(dev, "flash hardware say flash is 16 bit wide but DT says it is %d bits wide\n",
 165                                 map->bankwidth * 8);
 166        } else {
 167                if (map->bankwidth != 1)
 168                        dev_warn(dev, "flash hardware say flash is 8 bit wide but DT says it is %d bits wide\n",
 169                                 map->bankwidth * 8);
 170        }
 171
 172        gf->p = devm_pinctrl_get(dev);
 173        if (IS_ERR(gf->p)) {
 174                dev_err(dev, "no pinctrl handle\n");
 175                ret = PTR_ERR(gf->p);
 176                return ret;
 177        }
 178
 179        gf->enabled_state = pinctrl_lookup_state(gf->p, "enabled");
 180        if (IS_ERR(gf->enabled_state))
 181                dev_err(dev, "no enabled pin control state\n");
 182
 183        gf->disabled_state = pinctrl_lookup_state(gf->p, "disabled");
 184        if (IS_ERR(gf->enabled_state)) {
 185                dev_err(dev, "no disabled pin control state\n");
 186        } else {
 187                ret = pinctrl_select_state(gf->p, gf->disabled_state);
 188                if (ret)
 189                        dev_err(gf->dev, "failed to disable pins\n");
 190        }
 191
 192        map->read = gemini_flash_map_read;
 193        map->write = gemini_flash_map_write;
 194        map->copy_from = gemini_flash_map_copy_from;
 195        map->copy_to = gemini_flash_map_copy_to;
 196
 197        dev_info(dev, "initialized Gemini-specific physmap control\n");
 198
 199        return 0;
 200}
 201