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

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

DEFINITIONS

This source file includes following definitions.
  1. ap_flash_init
  2. ap_flash_set_vpp
  3. cp_flash_set_vpp
  4. versatile_flash_set_vpp
  5. of_flash_probe_versatile

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3  * Versatile OF physmap driver add-on
   4  *
   5  * Copyright (c) 2016, Linaro Limited
   6  * Author: Linus Walleij <linus.walleij@linaro.org>
   7  */
   8 #include <linux/export.h>
   9 #include <linux/io.h>
  10 #include <linux/of.h>
  11 #include <linux/of_address.h>
  12 #include <linux/of_device.h>
  13 #include <linux/mtd/map.h>
  14 #include <linux/mfd/syscon.h>
  15 #include <linux/regmap.h>
  16 #include <linux/bitops.h>
  17 #include "physmap-versatile.h"
  18 
  19 static struct regmap *syscon_regmap;
  20 
  21 enum versatile_flashprot {
  22         INTEGRATOR_AP_FLASHPROT,
  23         INTEGRATOR_CP_FLASHPROT,
  24         VERSATILE_FLASHPROT,
  25         REALVIEW_FLASHPROT,
  26 };
  27 
  28 static const struct of_device_id syscon_match[] = {
  29         {
  30                 .compatible = "arm,integrator-ap-syscon",
  31                 .data = (void *)INTEGRATOR_AP_FLASHPROT,
  32         },
  33         {
  34                 .compatible = "arm,integrator-cp-syscon",
  35                 .data = (void *)INTEGRATOR_CP_FLASHPROT,
  36         },
  37         {
  38                 .compatible = "arm,core-module-versatile",
  39                 .data = (void *)VERSATILE_FLASHPROT,
  40         },
  41         {
  42                 .compatible = "arm,realview-eb-syscon",
  43                 .data = (void *)REALVIEW_FLASHPROT,
  44         },
  45         {
  46                 .compatible = "arm,realview-pb1176-syscon",
  47                 .data = (void *)REALVIEW_FLASHPROT,
  48         },
  49         {
  50                 .compatible = "arm,realview-pb11mp-syscon",
  51                 .data = (void *)REALVIEW_FLASHPROT,
  52         },
  53         {
  54                 .compatible = "arm,realview-pba8-syscon",
  55                 .data = (void *)REALVIEW_FLASHPROT,
  56         },
  57         {
  58                 .compatible = "arm,realview-pbx-syscon",
  59                 .data = (void *)REALVIEW_FLASHPROT,
  60         },
  61         {},
  62 };
  63 
  64 /*
  65  * Flash protection handling for the Integrator/AP
  66  */
  67 #define INTEGRATOR_SC_CTRLS_OFFSET      0x08
  68 #define INTEGRATOR_SC_CTRLC_OFFSET      0x0C
  69 #define INTEGRATOR_SC_CTRL_FLVPPEN      BIT(1)
  70 #define INTEGRATOR_SC_CTRL_FLWP         BIT(2)
  71 
  72 #define INTEGRATOR_EBI_CSR1_OFFSET      0x04
  73 /* The manual says bit 2, the code says bit 3, trust the code */
  74 #define INTEGRATOR_EBI_WRITE_ENABLE     BIT(3)
  75 #define INTEGRATOR_EBI_LOCK_OFFSET      0x20
  76 #define INTEGRATOR_EBI_LOCK_VAL         0xA05F
  77 
  78 static const struct of_device_id ebi_match[] = {
  79         { .compatible = "arm,external-bus-interface"},
  80         { },
  81 };
  82 
  83 static int ap_flash_init(struct platform_device *pdev)
  84 {
  85         struct device_node *ebi;
  86         void __iomem *ebi_base;
  87         u32 val;
  88         int ret;
  89 
  90         /* Look up the EBI */
  91         ebi = of_find_matching_node(NULL, ebi_match);
  92         if (!ebi) {
  93                 return -ENODEV;
  94         }
  95         ebi_base = of_iomap(ebi, 0);
  96         if (!ebi_base)
  97                 return -ENODEV;
  98 
  99         /* Clear VPP and write protection bits */
 100         ret = regmap_write(syscon_regmap,
 101                 INTEGRATOR_SC_CTRLC_OFFSET,
 102                 INTEGRATOR_SC_CTRL_FLVPPEN | INTEGRATOR_SC_CTRL_FLWP);
 103         if (ret)
 104                 dev_err(&pdev->dev, "error clearing Integrator VPP/WP\n");
 105 
 106         /* Unlock the EBI */
 107         writel(INTEGRATOR_EBI_LOCK_VAL, ebi_base + INTEGRATOR_EBI_LOCK_OFFSET);
 108 
 109         /* Enable write cycles on the EBI, CSR1 (flash) */
 110         val = readl(ebi_base + INTEGRATOR_EBI_CSR1_OFFSET);
 111         val |= INTEGRATOR_EBI_WRITE_ENABLE;
 112         writel(val, ebi_base + INTEGRATOR_EBI_CSR1_OFFSET);
 113 
 114         /* Lock the EBI again */
 115         writel(0, ebi_base + INTEGRATOR_EBI_LOCK_OFFSET);
 116         iounmap(ebi_base);
 117 
 118         return 0;
 119 }
 120 
 121 static void ap_flash_set_vpp(struct map_info *map, int on)
 122 {
 123         int ret;
 124 
 125         if (on) {
 126                 ret = regmap_write(syscon_regmap,
 127                         INTEGRATOR_SC_CTRLS_OFFSET,
 128                         INTEGRATOR_SC_CTRL_FLVPPEN | INTEGRATOR_SC_CTRL_FLWP);
 129                 if (ret)
 130                         pr_err("error enabling AP VPP\n");
 131         } else {
 132                 ret = regmap_write(syscon_regmap,
 133                         INTEGRATOR_SC_CTRLC_OFFSET,
 134                         INTEGRATOR_SC_CTRL_FLVPPEN | INTEGRATOR_SC_CTRL_FLWP);
 135                 if (ret)
 136                         pr_err("error disabling AP VPP\n");
 137         }
 138 }
 139 
 140 /*
 141  * Flash protection handling for the Integrator/CP
 142  */
 143 
 144 #define INTCP_FLASHPROG_OFFSET          0x04
 145 #define CINTEGRATOR_FLVPPEN             BIT(0)
 146 #define CINTEGRATOR_FLWREN              BIT(1)
 147 #define CINTEGRATOR_FLMASK              BIT(0)|BIT(1)
 148 
 149 static void cp_flash_set_vpp(struct map_info *map, int on)
 150 {
 151         int ret;
 152 
 153         if (on) {
 154                 ret = regmap_update_bits(syscon_regmap,
 155                                 INTCP_FLASHPROG_OFFSET,
 156                                 CINTEGRATOR_FLMASK,
 157                                 CINTEGRATOR_FLVPPEN | CINTEGRATOR_FLWREN);
 158                 if (ret)
 159                         pr_err("error setting CP VPP\n");
 160         } else {
 161                 ret = regmap_update_bits(syscon_regmap,
 162                                 INTCP_FLASHPROG_OFFSET,
 163                                 CINTEGRATOR_FLMASK,
 164                                 0);
 165                 if (ret)
 166                         pr_err("error setting CP VPP\n");
 167         }
 168 }
 169 
 170 /*
 171  * Flash protection handling for the Versatiles and RealViews
 172  */
 173 
 174 #define VERSATILE_SYS_FLASH_OFFSET            0x4C
 175 
 176 static void versatile_flash_set_vpp(struct map_info *map, int on)
 177 {
 178         int ret;
 179 
 180         ret = regmap_update_bits(syscon_regmap, VERSATILE_SYS_FLASH_OFFSET,
 181                                  0x01, !!on);
 182         if (ret)
 183                 pr_err("error setting Versatile VPP\n");
 184 }
 185 
 186 int of_flash_probe_versatile(struct platform_device *pdev,
 187                              struct device_node *np,
 188                              struct map_info *map)
 189 {
 190         struct device_node *sysnp;
 191         const struct of_device_id *devid;
 192         struct regmap *rmap;
 193         static enum versatile_flashprot versatile_flashprot;
 194         int ret;
 195 
 196         /* Not all flash chips use this protection line */
 197         if (!of_device_is_compatible(np, "arm,versatile-flash"))
 198                 return 0;
 199 
 200         /* For first chip probed, look up the syscon regmap */
 201         if (!syscon_regmap) {
 202                 sysnp = of_find_matching_node_and_match(NULL,
 203                                                         syscon_match,
 204                                                         &devid);
 205                 if (!sysnp)
 206                         return -ENODEV;
 207 
 208                 versatile_flashprot = (enum versatile_flashprot)devid->data;
 209                 rmap = syscon_node_to_regmap(sysnp);
 210                 if (IS_ERR(rmap))
 211                         return PTR_ERR(rmap);
 212 
 213                 syscon_regmap = rmap;
 214         }
 215 
 216         switch (versatile_flashprot) {
 217         case INTEGRATOR_AP_FLASHPROT:
 218                 ret = ap_flash_init(pdev);
 219                 if (ret)
 220                         return ret;
 221                 map->set_vpp = ap_flash_set_vpp;
 222                 dev_info(&pdev->dev, "Integrator/AP flash protection\n");
 223                 break;
 224         case INTEGRATOR_CP_FLASHPROT:
 225                 map->set_vpp = cp_flash_set_vpp;
 226                 dev_info(&pdev->dev, "Integrator/CP flash protection\n");
 227                 break;
 228         case VERSATILE_FLASHPROT:
 229         case REALVIEW_FLASHPROT:
 230                 map->set_vpp = versatile_flash_set_vpp;
 231                 dev_info(&pdev->dev, "versatile/realview flash protection\n");
 232                 break;
 233         default:
 234                 dev_info(&pdev->dev, "device marked as Versatile flash "
 235                          "but no system controller was found\n");
 236                 break;
 237         }
 238 
 239         return 0;
 240 }

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