LCOV - code coverage report
Current view: top level - arch/arm/mm - cache-l2x0.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 320 0.0 %
Date: 2014-04-16 Functions: 0 30 0.0 %
Branches: 0 169 0.0 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * arch/arm/mm/cache-l2x0.c - L210/L220 cache controller support
       3                 :            :  *
       4                 :            :  * Copyright (C) 2007 ARM Limited
       5                 :            :  *
       6                 :            :  * This program is free software; you can redistribute it and/or modify
       7                 :            :  * it under the terms of the GNU General Public License version 2 as
       8                 :            :  * published by the Free Software Foundation.
       9                 :            :  *
      10                 :            :  * This program is distributed in the hope that it will be useful,
      11                 :            :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      12                 :            :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      13                 :            :  * GNU General Public License for more details.
      14                 :            :  *
      15                 :            :  * You should have received a copy of the GNU General Public License
      16                 :            :  * along with this program; if not, write to the Free Software
      17                 :            :  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
      18                 :            :  */
      19                 :            : #include <linux/err.h>
      20                 :            : #include <linux/init.h>
      21                 :            : #include <linux/spinlock.h>
      22                 :            : #include <linux/io.h>
      23                 :            : #include <linux/of.h>
      24                 :            : #include <linux/of_address.h>
      25                 :            : 
      26                 :            : #include <asm/cacheflush.h>
      27                 :            : #include <asm/hardware/cache-l2x0.h>
      28                 :            : #include "cache-tauros3.h"
      29                 :            : #include "cache-aurora-l2.h"
      30                 :            : 
      31                 :            : #define CACHE_LINE_SIZE         32
      32                 :            : 
      33                 :            : static void __iomem *l2x0_base;
      34                 :            : static DEFINE_RAW_SPINLOCK(l2x0_lock);
      35                 :            : static u32 l2x0_way_mask;       /* Bitmask of active ways */
      36                 :            : static u32 l2x0_size;
      37                 :            : static u32 l2x0_cache_id;
      38                 :            : static unsigned int l2x0_sets;
      39                 :            : static unsigned int l2x0_ways;
      40                 :            : static unsigned long sync_reg_offset = L2X0_CACHE_SYNC;
      41                 :            : 
      42                 :            : /* Aurora don't have the cache ID register available, so we have to
      43                 :            :  * pass it though the device tree */
      44                 :            : static u32  cache_id_part_number_from_dt;
      45                 :            : 
      46                 :            : struct l2x0_regs l2x0_saved_regs;
      47                 :            : 
      48                 :            : struct l2x0_of_data {
      49                 :            :         void (*setup)(const struct device_node *, u32 *, u32 *);
      50                 :            :         void (*save)(void);
      51                 :            :         struct outer_cache_fns outer_cache;
      52                 :            : };
      53                 :            : 
      54                 :            : static bool of_init = false;
      55                 :            : 
      56                 :            : static inline bool is_pl310_rev(int rev)
      57                 :            : {
      58                 :            :         return (l2x0_cache_id &
      59                 :            :                 (L2X0_CACHE_ID_PART_MASK | L2X0_CACHE_ID_REV_MASK)) ==
      60                 :            :                         (L2X0_CACHE_ID_PART_L310 | rev);
      61                 :            : }
      62                 :            : 
      63                 :            : static inline void cache_wait_way(void __iomem *reg, unsigned long mask)
      64                 :            : {
      65                 :            :         /* wait for cache operation by line or way to complete */
      66   [ #  #  #  #  :          0 :         while (readl_relaxed(reg) & mask)
                   #  # ]
      67                 :          0 :                 cpu_relax();
      68                 :            : }
      69                 :            : 
      70                 :            : #ifdef CONFIG_CACHE_PL310
      71                 :            : static inline void cache_wait(void __iomem *reg, unsigned long mask)
      72                 :            : {
      73                 :            :         /* cache operations by line are atomic on PL310 */
      74                 :            : }
      75                 :            : #else
      76                 :            : #define cache_wait      cache_wait_way
      77                 :            : #endif
      78                 :            : 
      79                 :            : static inline void cache_sync(void)
      80                 :            : {
      81                 :          0 :         void __iomem *base = l2x0_base;
      82                 :            : 
      83                 :          0 :         writel_relaxed(0, base + sync_reg_offset);
      84                 :            :         cache_wait(base + L2X0_CACHE_SYNC, 1);
      85                 :            : }
      86                 :            : 
      87                 :            : static inline void l2x0_clean_line(unsigned long addr)
      88                 :            : {
      89                 :          0 :         void __iomem *base = l2x0_base;
      90                 :            :         cache_wait(base + L2X0_CLEAN_LINE_PA, 1);
      91                 :          0 :         writel_relaxed(addr, base + L2X0_CLEAN_LINE_PA);
      92                 :            : }
      93                 :            : 
      94                 :            : static inline void l2x0_inv_line(unsigned long addr)
      95                 :            : {
      96                 :          0 :         void __iomem *base = l2x0_base;
      97                 :            :         cache_wait(base + L2X0_INV_LINE_PA, 1);
      98                 :          0 :         writel_relaxed(addr, base + L2X0_INV_LINE_PA);
      99                 :            : }
     100                 :            : 
     101                 :            : #if defined(CONFIG_PL310_ERRATA_588369) || defined(CONFIG_PL310_ERRATA_727915)
     102                 :            : static inline void debug_writel(unsigned long val)
     103                 :            : {
     104                 :            :         if (outer_cache.set_debug)
     105                 :            :                 outer_cache.set_debug(val);
     106                 :            : }
     107                 :            : 
     108                 :            : static void pl310_set_debug(unsigned long val)
     109                 :            : {
     110                 :            :         writel_relaxed(val, l2x0_base + L2X0_DEBUG_CTRL);
     111                 :            : }
     112                 :            : #else
     113                 :            : /* Optimised out for non-errata case */
     114                 :            : static inline void debug_writel(unsigned long val)
     115                 :            : {
     116                 :            : }
     117                 :            : 
     118                 :            : #define pl310_set_debug NULL
     119                 :            : #endif
     120                 :            : 
     121                 :            : #ifdef CONFIG_PL310_ERRATA_588369
     122                 :            : static inline void l2x0_flush_line(unsigned long addr)
     123                 :            : {
     124                 :            :         void __iomem *base = l2x0_base;
     125                 :            : 
     126                 :            :         /* Clean by PA followed by Invalidate by PA */
     127                 :            :         cache_wait(base + L2X0_CLEAN_LINE_PA, 1);
     128                 :            :         writel_relaxed(addr, base + L2X0_CLEAN_LINE_PA);
     129                 :            :         cache_wait(base + L2X0_INV_LINE_PA, 1);
     130                 :            :         writel_relaxed(addr, base + L2X0_INV_LINE_PA);
     131                 :            : }
     132                 :            : #else
     133                 :            : 
     134                 :            : static inline void l2x0_flush_line(unsigned long addr)
     135                 :            : {
     136                 :          0 :         void __iomem *base = l2x0_base;
     137                 :            :         cache_wait(base + L2X0_CLEAN_INV_LINE_PA, 1);
     138                 :          0 :         writel_relaxed(addr, base + L2X0_CLEAN_INV_LINE_PA);
     139                 :            : }
     140                 :            : #endif
     141                 :            : 
     142                 :          0 : static void l2x0_cache_sync(void)
     143                 :            : {
     144                 :            :         unsigned long flags;
     145                 :            : 
     146                 :          0 :         raw_spin_lock_irqsave(&l2x0_lock, flags);
     147                 :            :         cache_sync();
     148                 :          0 :         raw_spin_unlock_irqrestore(&l2x0_lock, flags);
     149                 :          0 : }
     150                 :            : 
     151                 :            : #ifdef CONFIG_PL310_ERRATA_727915
     152                 :            : static void l2x0_for_each_set_way(void __iomem *reg)
     153                 :            : {
     154                 :            :         int set;
     155                 :            :         int way;
     156                 :            :         unsigned long flags;
     157                 :            : 
     158                 :            :         for (way = 0; way < l2x0_ways; way++) {
     159                 :            :                 raw_spin_lock_irqsave(&l2x0_lock, flags);
     160                 :            :                 for (set = 0; set < l2x0_sets; set++)
     161                 :            :                         writel_relaxed((way << 28) | (set << 5), reg);
     162                 :            :                 cache_sync();
     163                 :            :                 raw_spin_unlock_irqrestore(&l2x0_lock, flags);
     164                 :            :         }
     165                 :            : }
     166                 :            : #endif
     167                 :            : 
     168                 :          0 : static void __l2x0_flush_all(void)
     169                 :            : {
     170                 :            :         debug_writel(0x03);
     171                 :          0 :         writel_relaxed(l2x0_way_mask, l2x0_base + L2X0_CLEAN_INV_WAY);
     172                 :          0 :         cache_wait_way(l2x0_base + L2X0_CLEAN_INV_WAY, l2x0_way_mask);
     173                 :            :         cache_sync();
     174                 :            :         debug_writel(0x00);
     175                 :          0 : }
     176                 :            : 
     177                 :          0 : static void l2x0_flush_all(void)
     178                 :            : {
     179                 :            :         unsigned long flags;
     180                 :            : 
     181                 :            : #ifdef CONFIG_PL310_ERRATA_727915
     182                 :            :         if (is_pl310_rev(REV_PL310_R2P0)) {
     183                 :            :                 l2x0_for_each_set_way(l2x0_base + L2X0_CLEAN_INV_LINE_IDX);
     184                 :            :                 return;
     185                 :            :         }
     186                 :            : #endif
     187                 :            : 
     188                 :            :         /* clean all ways */
     189                 :          0 :         raw_spin_lock_irqsave(&l2x0_lock, flags);
     190                 :          0 :         __l2x0_flush_all();
     191                 :          0 :         raw_spin_unlock_irqrestore(&l2x0_lock, flags);
     192                 :          0 : }
     193                 :            : 
     194                 :          0 : static void l2x0_clean_all(void)
     195                 :            : {
     196                 :            :         unsigned long flags;
     197                 :            : 
     198                 :            : #ifdef CONFIG_PL310_ERRATA_727915
     199                 :            :         if (is_pl310_rev(REV_PL310_R2P0)) {
     200                 :            :                 l2x0_for_each_set_way(l2x0_base + L2X0_CLEAN_LINE_IDX);
     201                 :            :                 return;
     202                 :            :         }
     203                 :            : #endif
     204                 :            : 
     205                 :            :         /* clean all ways */
     206                 :          0 :         raw_spin_lock_irqsave(&l2x0_lock, flags);
     207                 :            :         debug_writel(0x03);
     208                 :          0 :         writel_relaxed(l2x0_way_mask, l2x0_base + L2X0_CLEAN_WAY);
     209                 :          0 :         cache_wait_way(l2x0_base + L2X0_CLEAN_WAY, l2x0_way_mask);
     210                 :            :         cache_sync();
     211                 :            :         debug_writel(0x00);
     212                 :          0 :         raw_spin_unlock_irqrestore(&l2x0_lock, flags);
     213                 :          0 : }
     214                 :            : 
     215                 :          0 : static void l2x0_inv_all(void)
     216                 :            : {
     217                 :            :         unsigned long flags;
     218                 :            : 
     219                 :            :         /* invalidate all ways */
     220                 :          0 :         raw_spin_lock_irqsave(&l2x0_lock, flags);
     221                 :            :         /* Invalidating when L2 is enabled is a nono */
     222         [ #  # ]:          0 :         BUG_ON(readl(l2x0_base + L2X0_CTRL) & L2X0_CTRL_EN);
     223                 :          0 :         writel_relaxed(l2x0_way_mask, l2x0_base + L2X0_INV_WAY);
     224                 :          0 :         cache_wait_way(l2x0_base + L2X0_INV_WAY, l2x0_way_mask);
     225                 :            :         cache_sync();
     226                 :          0 :         raw_spin_unlock_irqrestore(&l2x0_lock, flags);
     227                 :          0 : }
     228                 :            : 
     229                 :          0 : static void l2x0_inv_range(unsigned long start, unsigned long end)
     230                 :            : {
     231                 :            :         void __iomem *base = l2x0_base;
     232                 :            :         unsigned long flags;
     233                 :            : 
     234                 :          0 :         raw_spin_lock_irqsave(&l2x0_lock, flags);
     235         [ #  # ]:          0 :         if (start & (CACHE_LINE_SIZE - 1)) {
     236                 :          0 :                 start &= ~(CACHE_LINE_SIZE - 1);
     237                 :            :                 debug_writel(0x03);
     238                 :            :                 l2x0_flush_line(start);
     239                 :            :                 debug_writel(0x00);
     240                 :          0 :                 start += CACHE_LINE_SIZE;
     241                 :            :         }
     242                 :            : 
     243         [ #  # ]:          0 :         if (end & (CACHE_LINE_SIZE - 1)) {
     244                 :          0 :                 end &= ~(CACHE_LINE_SIZE - 1);
     245                 :            :                 debug_writel(0x03);
     246                 :            :                 l2x0_flush_line(end);
     247                 :            :                 debug_writel(0x00);
     248                 :            :         }
     249                 :            : 
     250         [ #  # ]:          0 :         while (start < end) {
     251                 :          0 :                 unsigned long blk_end = start + min(end - start, 4096UL);
     252                 :            : 
     253         [ #  # ]:          0 :                 while (start < blk_end) {
     254                 :            :                         l2x0_inv_line(start);
     255                 :          0 :                         start += CACHE_LINE_SIZE;
     256                 :            :                 }
     257                 :            : 
     258         [ #  # ]:          0 :                 if (blk_end < end) {
     259                 :          0 :                         raw_spin_unlock_irqrestore(&l2x0_lock, flags);
     260                 :          0 :                         raw_spin_lock_irqsave(&l2x0_lock, flags);
     261                 :            :                 }
     262                 :            :         }
     263                 :            :         cache_wait(base + L2X0_INV_LINE_PA, 1);
     264                 :            :         cache_sync();
     265                 :          0 :         raw_spin_unlock_irqrestore(&l2x0_lock, flags);
     266                 :          0 : }
     267                 :            : 
     268                 :          0 : static void l2x0_clean_range(unsigned long start, unsigned long end)
     269                 :            : {
     270                 :            :         void __iomem *base = l2x0_base;
     271                 :            :         unsigned long flags;
     272                 :            : 
     273         [ #  # ]:          0 :         if ((end - start) >= l2x0_size) {
     274                 :          0 :                 l2x0_clean_all();
     275                 :          0 :                 return;
     276                 :            :         }
     277                 :            : 
     278                 :          0 :         raw_spin_lock_irqsave(&l2x0_lock, flags);
     279                 :          0 :         start &= ~(CACHE_LINE_SIZE - 1);
     280         [ #  # ]:          0 :         while (start < end) {
     281                 :          0 :                 unsigned long blk_end = start + min(end - start, 4096UL);
     282                 :            : 
     283         [ #  # ]:          0 :                 while (start < blk_end) {
     284                 :            :                         l2x0_clean_line(start);
     285                 :          0 :                         start += CACHE_LINE_SIZE;
     286                 :            :                 }
     287                 :            : 
     288         [ #  # ]:          0 :                 if (blk_end < end) {
     289                 :          0 :                         raw_spin_unlock_irqrestore(&l2x0_lock, flags);
     290                 :          0 :                         raw_spin_lock_irqsave(&l2x0_lock, flags);
     291                 :            :                 }
     292                 :            :         }
     293                 :            :         cache_wait(base + L2X0_CLEAN_LINE_PA, 1);
     294                 :            :         cache_sync();
     295                 :          0 :         raw_spin_unlock_irqrestore(&l2x0_lock, flags);
     296                 :            : }
     297                 :            : 
     298                 :          0 : static void l2x0_flush_range(unsigned long start, unsigned long end)
     299                 :            : {
     300                 :            :         void __iomem *base = l2x0_base;
     301                 :            :         unsigned long flags;
     302                 :            : 
     303         [ #  # ]:          0 :         if ((end - start) >= l2x0_size) {
     304                 :          0 :                 l2x0_flush_all();
     305                 :          0 :                 return;
     306                 :            :         }
     307                 :            : 
     308                 :          0 :         raw_spin_lock_irqsave(&l2x0_lock, flags);
     309                 :          0 :         start &= ~(CACHE_LINE_SIZE - 1);
     310         [ #  # ]:          0 :         while (start < end) {
     311                 :          0 :                 unsigned long blk_end = start + min(end - start, 4096UL);
     312                 :            : 
     313                 :            :                 debug_writel(0x03);
     314         [ #  # ]:          0 :                 while (start < blk_end) {
     315                 :            :                         l2x0_flush_line(start);
     316                 :          0 :                         start += CACHE_LINE_SIZE;
     317                 :            :                 }
     318                 :            :                 debug_writel(0x00);
     319                 :            : 
     320         [ #  # ]:          0 :                 if (blk_end < end) {
     321                 :          0 :                         raw_spin_unlock_irqrestore(&l2x0_lock, flags);
     322                 :          0 :                         raw_spin_lock_irqsave(&l2x0_lock, flags);
     323                 :            :                 }
     324                 :            :         }
     325                 :            :         cache_wait(base + L2X0_CLEAN_INV_LINE_PA, 1);
     326                 :            :         cache_sync();
     327                 :          0 :         raw_spin_unlock_irqrestore(&l2x0_lock, flags);
     328                 :            : }
     329                 :            : 
     330                 :          0 : static void l2x0_disable(void)
     331                 :            : {
     332                 :            :         unsigned long flags;
     333                 :            : 
     334                 :          0 :         raw_spin_lock_irqsave(&l2x0_lock, flags);
     335                 :          0 :         __l2x0_flush_all();
     336                 :          0 :         writel_relaxed(0, l2x0_base + L2X0_CTRL);
     337                 :          0 :         dsb(st);
     338                 :          0 :         raw_spin_unlock_irqrestore(&l2x0_lock, flags);
     339                 :          0 : }
     340                 :            : 
     341                 :          0 : static void l2x0_unlock(u32 cache_id)
     342                 :            : {
     343                 :            :         int lockregs;
     344                 :            :         int i;
     345                 :            : 
     346      [ #  #  # ]:          0 :         switch (cache_id & L2X0_CACHE_ID_PART_MASK) {
     347                 :            :         case L2X0_CACHE_ID_PART_L310:
     348                 :            :                 lockregs = 8;
     349                 :            :                 break;
     350                 :            :         case AURORA_CACHE_ID:
     351                 :            :                 lockregs = 4;
     352                 :          0 :                 break;
     353                 :            :         default:
     354                 :            :                 /* L210 and unknown types */
     355                 :            :                 lockregs = 1;
     356                 :          0 :                 break;
     357                 :            :         }
     358                 :            : 
     359         [ #  # ]:          0 :         for (i = 0; i < lockregs; i++) {
     360                 :          0 :                 writel_relaxed(0x0, l2x0_base + L2X0_LOCKDOWN_WAY_D_BASE +
     361                 :            :                                i * L2X0_LOCKDOWN_STRIDE);
     362                 :          0 :                 writel_relaxed(0x0, l2x0_base + L2X0_LOCKDOWN_WAY_I_BASE +
     363                 :            :                                i * L2X0_LOCKDOWN_STRIDE);
     364                 :            :         }
     365                 :          0 : }
     366                 :            : 
     367                 :          0 : void __init l2x0_init(void __iomem *base, u32 aux_val, u32 aux_mask)
     368                 :            : {
     369                 :            :         u32 aux;
     370                 :            :         u32 way_size = 0;
     371                 :            :         int way_size_shift = L2X0_WAY_SIZE_SHIFT;
     372                 :            :         const char *type;
     373                 :            : 
     374                 :          0 :         l2x0_base = base;
     375         [ #  # ]:          0 :         if (cache_id_part_number_from_dt)
     376                 :          0 :                 l2x0_cache_id = cache_id_part_number_from_dt;
     377                 :            :         else
     378                 :          0 :                 l2x0_cache_id = readl_relaxed(l2x0_base + L2X0_CACHE_ID);
     379                 :          0 :         aux = readl_relaxed(l2x0_base + L2X0_AUX_CTRL);
     380                 :            : 
     381                 :          0 :         aux &= aux_mask;
     382                 :          0 :         aux |= aux_val;
     383                 :            : 
     384                 :            :         /* Determine the number of ways */
     385   [ #  #  #  # ]:          0 :         switch (l2x0_cache_id & L2X0_CACHE_ID_PART_MASK) {
     386                 :            :         case L2X0_CACHE_ID_PART_L310:
     387         [ #  # ]:          0 :                 if (aux & (1 << 16))
     388                 :          0 :                         l2x0_ways = 16;
     389                 :            :                 else
     390                 :          0 :                         l2x0_ways = 8;
     391                 :            :                 type = "L310";
     392                 :            : #ifdef CONFIG_PL310_ERRATA_753970
     393                 :            :                 /* Unmapped register. */
     394                 :          0 :                 sync_reg_offset = L2X0_DUMMY_REG;
     395                 :            : #endif
     396         [ #  # ]:          0 :                 if ((l2x0_cache_id & L2X0_CACHE_ID_RTL_MASK) <= L2X0_CACHE_ID_RTL_R3P0)
     397                 :          0 :                         outer_cache.set_debug = pl310_set_debug;
     398                 :            :                 break;
     399                 :            :         case L2X0_CACHE_ID_PART_L210:
     400                 :          0 :                 l2x0_ways = (aux >> 13) & 0xf;
     401                 :            :                 type = "L210";
     402                 :          0 :                 break;
     403                 :            : 
     404                 :            :         case AURORA_CACHE_ID:
     405                 :          0 :                 sync_reg_offset = AURORA_SYNC_REG;
     406                 :          0 :                 l2x0_ways = (aux >> 13) & 0xf;
     407                 :          0 :                 l2x0_ways = 2 << ((l2x0_ways + 1) >> 2);
     408                 :            :                 way_size_shift = AURORA_WAY_SIZE_SHIFT;
     409                 :            :                 type = "Aurora";
     410                 :          0 :                 break;
     411                 :            :         default:
     412                 :            :                 /* Assume unknown chips have 8 ways */
     413                 :          0 :                 l2x0_ways = 8;
     414                 :            :                 type = "L2x0 series";
     415                 :          0 :                 break;
     416                 :            :         }
     417                 :            : 
     418                 :          0 :         l2x0_way_mask = (1 << l2x0_ways) - 1;
     419                 :            : 
     420                 :            :         /*
     421                 :            :          * L2 cache Size =  Way size * Number of ways
     422                 :            :          */
     423                 :          0 :         way_size = (aux & L2X0_AUX_CTRL_WAY_SIZE_MASK) >> 17;
     424                 :          0 :         way_size = SZ_1K << (way_size + way_size_shift);
     425                 :            : 
     426                 :          0 :         l2x0_size = l2x0_ways * way_size;
     427                 :          0 :         l2x0_sets = way_size / CACHE_LINE_SIZE;
     428                 :            : 
     429                 :            :         /*
     430                 :            :          * Check if l2x0 controller is already enabled.
     431                 :            :          * If you are booting from non-secure mode
     432                 :            :          * accessing the below registers will fault.
     433                 :            :          */
     434         [ #  # ]:          0 :         if (!(readl_relaxed(l2x0_base + L2X0_CTRL) & L2X0_CTRL_EN)) {
     435                 :            :                 /* Make sure that I&D is not locked down when starting */
     436                 :          0 :                 l2x0_unlock(l2x0_cache_id);
     437                 :            : 
     438                 :            :                 /* l2x0 controller is disabled */
     439                 :          0 :                 writel_relaxed(aux, l2x0_base + L2X0_AUX_CTRL);
     440                 :            : 
     441                 :          0 :                 l2x0_inv_all();
     442                 :            : 
     443                 :            :                 /* enable L2X0 */
     444                 :          0 :                 writel_relaxed(L2X0_CTRL_EN, l2x0_base + L2X0_CTRL);
     445                 :            :         }
     446                 :            : 
     447                 :            :         /* Re-read it in case some bits are reserved. */
     448                 :          0 :         aux = readl_relaxed(l2x0_base + L2X0_AUX_CTRL);
     449                 :            : 
     450                 :            :         /* Save the value for resuming. */
     451                 :          0 :         l2x0_saved_regs.aux_ctrl = aux;
     452                 :            : 
     453         [ #  # ]:          0 :         if (!of_init) {
     454                 :          0 :                 outer_cache.inv_range = l2x0_inv_range;
     455                 :          0 :                 outer_cache.clean_range = l2x0_clean_range;
     456                 :          0 :                 outer_cache.flush_range = l2x0_flush_range;
     457                 :          0 :                 outer_cache.sync = l2x0_cache_sync;
     458                 :          0 :                 outer_cache.flush_all = l2x0_flush_all;
     459                 :          0 :                 outer_cache.inv_all = l2x0_inv_all;
     460                 :          0 :                 outer_cache.disable = l2x0_disable;
     461                 :            :         }
     462                 :            : 
     463                 :          0 :         pr_info("%s cache controller enabled\n", type);
     464                 :          0 :         pr_info("l2x0: %d ways, CACHE_ID 0x%08x, AUX_CTRL 0x%08x, Cache size: %d kB\n",
     465                 :            :                 l2x0_ways, l2x0_cache_id, aux, l2x0_size >> 10);
     466                 :          0 : }
     467                 :            : 
     468                 :            : #ifdef CONFIG_OF
     469                 :            : static int l2_wt_override;
     470                 :            : 
     471                 :            : /*
     472                 :            :  * Note that the end addresses passed to Linux primitives are
     473                 :            :  * noninclusive, while the hardware cache range operations use
     474                 :            :  * inclusive start and end addresses.
     475                 :            :  */
     476                 :            : static unsigned long calc_range_end(unsigned long start, unsigned long end)
     477                 :            : {
     478                 :            :         /*
     479                 :            :          * Limit the number of cache lines processed at once,
     480                 :            :          * since cache range operations stall the CPU pipeline
     481                 :            :          * until completion.
     482                 :            :          */
     483 [ #  # ][ #  # ]:          0 :         if (end > start + MAX_RANGE_SIZE)
                 [ #  # ]
     484                 :            :                 end = start + MAX_RANGE_SIZE;
     485                 :            : 
     486                 :            :         /*
     487                 :            :          * Cache range operations can't straddle a page boundary.
     488                 :            :          */
     489 [ #  # ][ #  # ]:          0 :         if (end > PAGE_ALIGN(start+1))
                 [ #  # ]
     490                 :            :                 end = PAGE_ALIGN(start+1);
     491                 :            : 
     492                 :            :         return end;
     493                 :            : }
     494                 :            : 
     495                 :            : /*
     496                 :            :  * Make sure 'start' and 'end' reference the same page, as L2 is PIPT
     497                 :            :  * and range operations only do a TLB lookup on the start address.
     498                 :            :  */
     499                 :          0 : static void aurora_pa_range(unsigned long start, unsigned long end,
     500                 :            :                         unsigned long offset)
     501                 :            : {
     502                 :            :         unsigned long flags;
     503                 :            : 
     504                 :          0 :         raw_spin_lock_irqsave(&l2x0_lock, flags);
     505                 :          0 :         writel_relaxed(start, l2x0_base + AURORA_RANGE_BASE_ADDR_REG);
     506                 :          0 :         writel_relaxed(end, l2x0_base + offset);
     507                 :          0 :         raw_spin_unlock_irqrestore(&l2x0_lock, flags);
     508                 :            : 
     509                 :            :         cache_sync();
     510                 :          0 : }
     511                 :            : 
     512                 :          0 : static void aurora_inv_range(unsigned long start, unsigned long end)
     513                 :            : {
     514                 :            :         /*
     515                 :            :          * round start and end adresses up to cache line size
     516                 :            :          */
     517                 :          0 :         start &= ~(CACHE_LINE_SIZE - 1);
     518                 :          0 :         end = ALIGN(end, CACHE_LINE_SIZE);
     519                 :            : 
     520                 :            :         /*
     521                 :            :          * Invalidate all full cache lines between 'start' and 'end'.
     522                 :            :          */
     523         [ #  # ]:          0 :         while (start < end) {
     524                 :            :                 unsigned long range_end = calc_range_end(start, end);
     525                 :          0 :                 aurora_pa_range(start, range_end - CACHE_LINE_SIZE,
     526                 :            :                                 AURORA_INVAL_RANGE_REG);
     527                 :            :                 start = range_end;
     528                 :            :         }
     529                 :          0 : }
     530                 :            : 
     531                 :          0 : static void aurora_clean_range(unsigned long start, unsigned long end)
     532                 :            : {
     533                 :            :         /*
     534                 :            :          * If L2 is forced to WT, the L2 will always be clean and we
     535                 :            :          * don't need to do anything here.
     536                 :            :          */
     537         [ #  # ]:          0 :         if (!l2_wt_override) {
     538                 :          0 :                 start &= ~(CACHE_LINE_SIZE - 1);
     539                 :          0 :                 end = ALIGN(end, CACHE_LINE_SIZE);
     540         [ #  # ]:          0 :                 while (start != end) {
     541                 :            :                         unsigned long range_end = calc_range_end(start, end);
     542                 :          0 :                         aurora_pa_range(start, range_end - CACHE_LINE_SIZE,
     543                 :            :                                         AURORA_CLEAN_RANGE_REG);
     544                 :            :                         start = range_end;
     545                 :            :                 }
     546                 :            :         }
     547                 :          0 : }
     548                 :            : 
     549                 :          0 : static void aurora_flush_range(unsigned long start, unsigned long end)
     550                 :            : {
     551                 :          0 :         start &= ~(CACHE_LINE_SIZE - 1);
     552                 :          0 :         end = ALIGN(end, CACHE_LINE_SIZE);
     553         [ #  # ]:          0 :         while (start != end) {
     554                 :            :                 unsigned long range_end = calc_range_end(start, end);
     555                 :            :                 /*
     556                 :            :                  * If L2 is forced to WT, the L2 will always be clean and we
     557                 :            :                  * just need to invalidate.
     558                 :            :                  */
     559         [ #  # ]:          0 :                 if (l2_wt_override)
     560                 :          0 :                         aurora_pa_range(start, range_end - CACHE_LINE_SIZE,
     561                 :            :                                                         AURORA_INVAL_RANGE_REG);
     562                 :            :                 else
     563                 :          0 :                         aurora_pa_range(start, range_end - CACHE_LINE_SIZE,
     564                 :            :                                                         AURORA_FLUSH_RANGE_REG);
     565                 :            :                 start = range_end;
     566                 :            :         }
     567                 :          0 : }
     568                 :            : 
     569                 :            : /*
     570                 :            :  * For certain Broadcom SoCs, depending on the address range, different offsets
     571                 :            :  * need to be added to the address before passing it to L2 for
     572                 :            :  * invalidation/clean/flush
     573                 :            :  *
     574                 :            :  * Section Address Range              Offset        EMI
     575                 :            :  *   1     0x00000000 - 0x3FFFFFFF    0x80000000    VC
     576                 :            :  *   2     0x40000000 - 0xBFFFFFFF    0x40000000    SYS
     577                 :            :  *   3     0xC0000000 - 0xFFFFFFFF    0x80000000    VC
     578                 :            :  *
     579                 :            :  * When the start and end addresses have crossed two different sections, we
     580                 :            :  * need to break the L2 operation into two, each within its own section.
     581                 :            :  * For example, if we need to invalidate addresses starts at 0xBFFF0000 and
     582                 :            :  * ends at 0xC0001000, we need do invalidate 1) 0xBFFF0000 - 0xBFFFFFFF and 2)
     583                 :            :  * 0xC0000000 - 0xC0001000
     584                 :            :  *
     585                 :            :  * Note 1:
     586                 :            :  * By breaking a single L2 operation into two, we may potentially suffer some
     587                 :            :  * performance hit, but keep in mind the cross section case is very rare
     588                 :            :  *
     589                 :            :  * Note 2:
     590                 :            :  * We do not need to handle the case when the start address is in
     591                 :            :  * Section 1 and the end address is in Section 3, since it is not a valid use
     592                 :            :  * case
     593                 :            :  *
     594                 :            :  * Note 3:
     595                 :            :  * Section 1 in practical terms can no longer be used on rev A2. Because of
     596                 :            :  * that the code does not need to handle section 1 at all.
     597                 :            :  *
     598                 :            :  */
     599                 :            : #define BCM_SYS_EMI_START_ADDR        0x40000000UL
     600                 :            : #define BCM_VC_EMI_SEC3_START_ADDR    0xC0000000UL
     601                 :            : 
     602                 :            : #define BCM_SYS_EMI_OFFSET            0x40000000UL
     603                 :            : #define BCM_VC_EMI_OFFSET             0x80000000UL
     604                 :            : 
     605                 :            : static inline int bcm_addr_is_sys_emi(unsigned long addr)
     606                 :            : {
     607                 :          0 :         return (addr >= BCM_SYS_EMI_START_ADDR) &&
     608                 :            :                 (addr < BCM_VC_EMI_SEC3_START_ADDR);
     609                 :            : }
     610                 :            : 
     611                 :            : static inline unsigned long bcm_l2_phys_addr(unsigned long addr)
     612                 :            : {
     613 [ #  # ][ #  # ]:          0 :         if (bcm_addr_is_sys_emi(addr))
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     614                 :          0 :                 return addr + BCM_SYS_EMI_OFFSET;
     615                 :            :         else
     616                 :          0 :                 return addr + BCM_VC_EMI_OFFSET;
     617                 :            : }
     618                 :            : 
     619                 :          0 : static void bcm_inv_range(unsigned long start, unsigned long end)
     620                 :            : {
     621                 :            :         unsigned long new_start, new_end;
     622                 :            : 
     623         [ #  # ]:          0 :         BUG_ON(start < BCM_SYS_EMI_START_ADDR);
     624                 :            : 
     625         [ #  # ]:          0 :         if (unlikely(end <= start))
     626                 :            :                 return;
     627                 :            : 
     628                 :            :         new_start = bcm_l2_phys_addr(start);
     629                 :            :         new_end = bcm_l2_phys_addr(end);
     630                 :            : 
     631                 :            :         /* normal case, no cross section between start and end */
     632 [ #  # ][ #  # ]:          0 :         if (likely(bcm_addr_is_sys_emi(end) || !bcm_addr_is_sys_emi(start))) {
     633                 :          0 :                 l2x0_inv_range(new_start, new_end);
     634                 :          0 :                 return;
     635                 :            :         }
     636                 :            : 
     637                 :            :         /* They cross sections, so it can only be a cross from section
     638                 :            :          * 2 to section 3
     639                 :            :          */
     640                 :          0 :         l2x0_inv_range(new_start,
     641                 :            :                 bcm_l2_phys_addr(BCM_VC_EMI_SEC3_START_ADDR-1));
     642                 :          0 :         l2x0_inv_range(bcm_l2_phys_addr(BCM_VC_EMI_SEC3_START_ADDR),
     643                 :            :                 new_end);
     644                 :            : }
     645                 :            : 
     646                 :          0 : static void bcm_clean_range(unsigned long start, unsigned long end)
     647                 :            : {
     648                 :            :         unsigned long new_start, new_end;
     649                 :            : 
     650         [ #  # ]:          0 :         BUG_ON(start < BCM_SYS_EMI_START_ADDR);
     651                 :            : 
     652         [ #  # ]:          0 :         if (unlikely(end <= start))
     653                 :            :                 return;
     654                 :            : 
     655         [ #  # ]:          0 :         if ((end - start) >= l2x0_size) {
     656                 :          0 :                 l2x0_clean_all();
     657                 :          0 :                 return;
     658                 :            :         }
     659                 :            : 
     660                 :            :         new_start = bcm_l2_phys_addr(start);
     661                 :            :         new_end = bcm_l2_phys_addr(end);
     662                 :            : 
     663                 :            :         /* normal case, no cross section between start and end */
     664 [ #  # ][ #  # ]:          0 :         if (likely(bcm_addr_is_sys_emi(end) || !bcm_addr_is_sys_emi(start))) {
     665                 :          0 :                 l2x0_clean_range(new_start, new_end);
     666                 :          0 :                 return;
     667                 :            :         }
     668                 :            : 
     669                 :            :         /* They cross sections, so it can only be a cross from section
     670                 :            :          * 2 to section 3
     671                 :            :          */
     672                 :          0 :         l2x0_clean_range(new_start,
     673                 :            :                 bcm_l2_phys_addr(BCM_VC_EMI_SEC3_START_ADDR-1));
     674                 :          0 :         l2x0_clean_range(bcm_l2_phys_addr(BCM_VC_EMI_SEC3_START_ADDR),
     675                 :            :                 new_end);
     676                 :            : }
     677                 :            : 
     678                 :          0 : static void bcm_flush_range(unsigned long start, unsigned long end)
     679                 :            : {
     680                 :            :         unsigned long new_start, new_end;
     681                 :            : 
     682         [ #  # ]:          0 :         BUG_ON(start < BCM_SYS_EMI_START_ADDR);
     683                 :            : 
     684         [ #  # ]:          0 :         if (unlikely(end <= start))
     685                 :            :                 return;
     686                 :            : 
     687         [ #  # ]:          0 :         if ((end - start) >= l2x0_size) {
     688                 :          0 :                 l2x0_flush_all();
     689                 :          0 :                 return;
     690                 :            :         }
     691                 :            : 
     692                 :            :         new_start = bcm_l2_phys_addr(start);
     693                 :            :         new_end = bcm_l2_phys_addr(end);
     694                 :            : 
     695                 :            :         /* normal case, no cross section between start and end */
     696 [ #  # ][ #  # ]:          0 :         if (likely(bcm_addr_is_sys_emi(end) || !bcm_addr_is_sys_emi(start))) {
     697                 :          0 :                 l2x0_flush_range(new_start, new_end);
     698                 :          0 :                 return;
     699                 :            :         }
     700                 :            : 
     701                 :            :         /* They cross sections, so it can only be a cross from section
     702                 :            :          * 2 to section 3
     703                 :            :          */
     704                 :          0 :         l2x0_flush_range(new_start,
     705                 :            :                 bcm_l2_phys_addr(BCM_VC_EMI_SEC3_START_ADDR-1));
     706                 :          0 :         l2x0_flush_range(bcm_l2_phys_addr(BCM_VC_EMI_SEC3_START_ADDR),
     707                 :            :                 new_end);
     708                 :            : }
     709                 :            : 
     710                 :          0 : static void __init l2x0_of_setup(const struct device_node *np,
     711                 :            :                                  u32 *aux_val, u32 *aux_mask)
     712                 :            : {
     713                 :          0 :         u32 data[2] = { 0, 0 };
     714                 :          0 :         u32 tag = 0;
     715                 :          0 :         u32 dirty = 0;
     716                 :            :         u32 val = 0, mask = 0;
     717                 :            : 
     718                 :            :         of_property_read_u32(np, "arm,tag-latency", &tag);
     719         [ #  # ]:          0 :         if (tag) {
     720                 :            :                 mask |= L2X0_AUX_CTRL_TAG_LATENCY_MASK;
     721                 :          0 :                 val |= (tag - 1) << L2X0_AUX_CTRL_TAG_LATENCY_SHIFT;
     722                 :            :         }
     723                 :            : 
     724                 :          0 :         of_property_read_u32_array(np, "arm,data-latency",
     725                 :            :                                    data, ARRAY_SIZE(data));
     726 [ #  # ][ #  # ]:          0 :         if (data[0] && data[1]) {
     727                 :          0 :                 mask |= L2X0_AUX_CTRL_DATA_RD_LATENCY_MASK |
     728                 :            :                         L2X0_AUX_CTRL_DATA_WR_LATENCY_MASK;
     729                 :          0 :                 val |= ((data[0] - 1) << L2X0_AUX_CTRL_DATA_RD_LATENCY_SHIFT) |
     730                 :          0 :                        ((data[1] - 1) << L2X0_AUX_CTRL_DATA_WR_LATENCY_SHIFT);
     731                 :            :         }
     732                 :            : 
     733                 :            :         of_property_read_u32(np, "arm,dirty-latency", &dirty);
     734         [ #  # ]:          0 :         if (dirty) {
     735                 :          0 :                 mask |= L2X0_AUX_CTRL_DIRTY_LATENCY_MASK;
     736                 :          0 :                 val |= (dirty - 1) << L2X0_AUX_CTRL_DIRTY_LATENCY_SHIFT;
     737                 :            :         }
     738                 :            : 
     739                 :          0 :         *aux_val &= ~mask;
     740                 :          0 :         *aux_val |= val;
     741                 :          0 :         *aux_mask &= ~mask;
     742                 :          0 : }
     743                 :            : 
     744                 :          0 : static void __init pl310_of_setup(const struct device_node *np,
     745                 :            :                                   u32 *aux_val, u32 *aux_mask)
     746                 :            : {
     747                 :          0 :         u32 data[3] = { 0, 0, 0 };
     748                 :          0 :         u32 tag[3] = { 0, 0, 0 };
     749                 :          0 :         u32 filter[2] = { 0, 0 };
     750                 :            : 
     751                 :          0 :         of_property_read_u32_array(np, "arm,tag-latency", tag, ARRAY_SIZE(tag));
     752 [ #  # ][ #  # ]:          0 :         if (tag[0] && tag[1] && tag[2])
                 [ #  # ]
     753                 :          0 :                 writel_relaxed(
     754                 :            :                         ((tag[0] - 1) << L2X0_LATENCY_CTRL_RD_SHIFT) |
     755                 :            :                         ((tag[1] - 1) << L2X0_LATENCY_CTRL_WR_SHIFT) |
     756                 :            :                         ((tag[2] - 1) << L2X0_LATENCY_CTRL_SETUP_SHIFT),
     757                 :            :                         l2x0_base + L2X0_TAG_LATENCY_CTRL);
     758                 :            : 
     759                 :          0 :         of_property_read_u32_array(np, "arm,data-latency",
     760                 :            :                                    data, ARRAY_SIZE(data));
     761 [ #  # ][ #  # ]:          0 :         if (data[0] && data[1] && data[2])
                 [ #  # ]
     762                 :          0 :                 writel_relaxed(
     763                 :            :                         ((data[0] - 1) << L2X0_LATENCY_CTRL_RD_SHIFT) |
     764                 :            :                         ((data[1] - 1) << L2X0_LATENCY_CTRL_WR_SHIFT) |
     765                 :            :                         ((data[2] - 1) << L2X0_LATENCY_CTRL_SETUP_SHIFT),
     766                 :            :                         l2x0_base + L2X0_DATA_LATENCY_CTRL);
     767                 :            : 
     768                 :          0 :         of_property_read_u32_array(np, "arm,filter-ranges",
     769                 :            :                                    filter, ARRAY_SIZE(filter));
     770         [ #  # ]:          0 :         if (filter[1]) {
     771                 :          0 :                 writel_relaxed(ALIGN(filter[0] + filter[1], SZ_1M),
     772                 :            :                                l2x0_base + L2X0_ADDR_FILTER_END);
     773                 :          0 :                 writel_relaxed((filter[0] & ~(SZ_1M - 1)) | L2X0_ADDR_FILTER_EN,
     774                 :            :                                l2x0_base + L2X0_ADDR_FILTER_START);
     775                 :            :         }
     776                 :          0 : }
     777                 :            : 
     778                 :          0 : static void __init pl310_save(void)
     779                 :            : {
     780                 :          0 :         u32 l2x0_revision = readl_relaxed(l2x0_base + L2X0_CACHE_ID) &
     781                 :            :                 L2X0_CACHE_ID_RTL_MASK;
     782                 :            : 
     783                 :          0 :         l2x0_saved_regs.tag_latency = readl_relaxed(l2x0_base +
     784                 :            :                 L2X0_TAG_LATENCY_CTRL);
     785                 :          0 :         l2x0_saved_regs.data_latency = readl_relaxed(l2x0_base +
     786                 :            :                 L2X0_DATA_LATENCY_CTRL);
     787                 :          0 :         l2x0_saved_regs.filter_end = readl_relaxed(l2x0_base +
     788                 :            :                 L2X0_ADDR_FILTER_END);
     789                 :          0 :         l2x0_saved_regs.filter_start = readl_relaxed(l2x0_base +
     790                 :            :                 L2X0_ADDR_FILTER_START);
     791                 :            : 
     792         [ #  # ]:          0 :         if (l2x0_revision >= L2X0_CACHE_ID_RTL_R2P0) {
     793                 :            :                 /*
     794                 :            :                  * From r2p0, there is Prefetch offset/control register
     795                 :            :                  */
     796                 :          0 :                 l2x0_saved_regs.prefetch_ctrl = readl_relaxed(l2x0_base +
     797                 :            :                         L2X0_PREFETCH_CTRL);
     798                 :            :                 /*
     799                 :            :                  * From r3p0, there is Power control register
     800                 :            :                  */
     801         [ #  # ]:          0 :                 if (l2x0_revision >= L2X0_CACHE_ID_RTL_R3P0)
     802                 :          0 :                         l2x0_saved_regs.pwr_ctrl = readl_relaxed(l2x0_base +
     803                 :            :                                 L2X0_POWER_CTRL);
     804                 :            :         }
     805                 :          0 : }
     806                 :            : 
     807                 :          0 : static void aurora_save(void)
     808                 :            : {
     809                 :          0 :         l2x0_saved_regs.ctrl = readl_relaxed(l2x0_base + L2X0_CTRL);
     810                 :          0 :         l2x0_saved_regs.aux_ctrl = readl_relaxed(l2x0_base + L2X0_AUX_CTRL);
     811                 :          0 : }
     812                 :            : 
     813                 :          0 : static void __init tauros3_save(void)
     814                 :            : {
     815                 :          0 :         l2x0_saved_regs.aux2_ctrl =
     816                 :          0 :                 readl_relaxed(l2x0_base + TAUROS3_AUX2_CTRL);
     817                 :          0 :         l2x0_saved_regs.prefetch_ctrl =
     818                 :          0 :                 readl_relaxed(l2x0_base + L2X0_PREFETCH_CTRL);
     819                 :          0 : }
     820                 :            : 
     821                 :          0 : static void l2x0_resume(void)
     822                 :            : {
     823         [ #  # ]:          0 :         if (!(readl_relaxed(l2x0_base + L2X0_CTRL) & L2X0_CTRL_EN)) {
     824                 :            :                 /* restore aux ctrl and enable l2 */
     825                 :          0 :                 l2x0_unlock(readl_relaxed(l2x0_base + L2X0_CACHE_ID));
     826                 :            : 
     827                 :          0 :                 writel_relaxed(l2x0_saved_regs.aux_ctrl, l2x0_base +
     828                 :            :                         L2X0_AUX_CTRL);
     829                 :            : 
     830                 :          0 :                 l2x0_inv_all();
     831                 :            : 
     832                 :          0 :                 writel_relaxed(L2X0_CTRL_EN, l2x0_base + L2X0_CTRL);
     833                 :            :         }
     834                 :          0 : }
     835                 :            : 
     836                 :          0 : static void pl310_resume(void)
     837                 :            : {
     838                 :            :         u32 l2x0_revision;
     839                 :            : 
     840         [ #  # ]:          0 :         if (!(readl_relaxed(l2x0_base + L2X0_CTRL) & L2X0_CTRL_EN)) {
     841                 :            :                 /* restore pl310 setup */
     842                 :          0 :                 writel_relaxed(l2x0_saved_regs.tag_latency,
     843                 :            :                         l2x0_base + L2X0_TAG_LATENCY_CTRL);
     844                 :          0 :                 writel_relaxed(l2x0_saved_regs.data_latency,
     845                 :            :                         l2x0_base + L2X0_DATA_LATENCY_CTRL);
     846                 :          0 :                 writel_relaxed(l2x0_saved_regs.filter_end,
     847                 :            :                         l2x0_base + L2X0_ADDR_FILTER_END);
     848                 :          0 :                 writel_relaxed(l2x0_saved_regs.filter_start,
     849                 :            :                         l2x0_base + L2X0_ADDR_FILTER_START);
     850                 :            : 
     851                 :          0 :                 l2x0_revision = readl_relaxed(l2x0_base + L2X0_CACHE_ID) &
     852                 :            :                         L2X0_CACHE_ID_RTL_MASK;
     853                 :            : 
     854         [ #  # ]:          0 :                 if (l2x0_revision >= L2X0_CACHE_ID_RTL_R2P0) {
     855                 :          0 :                         writel_relaxed(l2x0_saved_regs.prefetch_ctrl,
     856                 :            :                                 l2x0_base + L2X0_PREFETCH_CTRL);
     857         [ #  # ]:          0 :                         if (l2x0_revision >= L2X0_CACHE_ID_RTL_R3P0)
     858                 :          0 :                                 writel_relaxed(l2x0_saved_regs.pwr_ctrl,
     859                 :            :                                         l2x0_base + L2X0_POWER_CTRL);
     860                 :            :                 }
     861                 :            :         }
     862                 :            : 
     863                 :          0 :         l2x0_resume();
     864                 :          0 : }
     865                 :            : 
     866                 :          0 : static void aurora_resume(void)
     867                 :            : {
     868         [ #  # ]:          0 :         if (!(readl(l2x0_base + L2X0_CTRL) & L2X0_CTRL_EN)) {
     869                 :          0 :                 writel_relaxed(l2x0_saved_regs.aux_ctrl,
     870                 :            :                                 l2x0_base + L2X0_AUX_CTRL);
     871                 :          0 :                 writel_relaxed(l2x0_saved_regs.ctrl, l2x0_base + L2X0_CTRL);
     872                 :            :         }
     873                 :          0 : }
     874                 :            : 
     875                 :          0 : static void tauros3_resume(void)
     876                 :            : {
     877         [ #  # ]:          0 :         if (!(readl_relaxed(l2x0_base + L2X0_CTRL) & L2X0_CTRL_EN)) {
     878                 :          0 :                 writel_relaxed(l2x0_saved_regs.aux2_ctrl,
     879                 :            :                                l2x0_base + TAUROS3_AUX2_CTRL);
     880                 :          0 :                 writel_relaxed(l2x0_saved_regs.prefetch_ctrl,
     881                 :            :                                l2x0_base + L2X0_PREFETCH_CTRL);
     882                 :            :         }
     883                 :            : 
     884                 :          0 :         l2x0_resume();
     885                 :          0 : }
     886                 :            : 
     887                 :          0 : static void __init aurora_broadcast_l2_commands(void)
     888                 :            : {
     889                 :            :         __u32 u;
     890                 :            :         /* Enable Broadcasting of cache commands to L2*/
     891                 :          0 :         __asm__ __volatile__("mrc p15, 1, %0, c15, c2, 0" : "=r"(u));
     892                 :          0 :         u |= AURORA_CTRL_FW;            /* Set the FW bit */
     893                 :          0 :         __asm__ __volatile__("mcr p15, 1, %0, c15, c2, 0\n" : : "r"(u));
     894                 :          0 :         isb();
     895                 :          0 : }
     896                 :            : 
     897                 :          0 : static void __init aurora_of_setup(const struct device_node *np,
     898                 :            :                                 u32 *aux_val, u32 *aux_mask)
     899                 :            : {
     900                 :            :         u32 val = AURORA_ACR_REPLACEMENT_TYPE_SEMIPLRU;
     901                 :            :         u32 mask =  AURORA_ACR_REPLACEMENT_MASK;
     902                 :            : 
     903                 :            :         of_property_read_u32(np, "cache-id-part",
     904                 :            :                         &cache_id_part_number_from_dt);
     905                 :            : 
     906                 :            :         /* Determine and save the write policy */
     907                 :          0 :         l2_wt_override = of_property_read_bool(np, "wt-override");
     908                 :            : 
     909         [ #  # ]:          0 :         if (l2_wt_override) {
     910                 :            :                 val |= AURORA_ACR_FORCE_WRITE_THRO_POLICY;
     911                 :            :                 mask |= AURORA_ACR_FORCE_WRITE_POLICY_MASK;
     912                 :            :         }
     913                 :            : 
     914                 :          0 :         *aux_val &= ~mask;
     915                 :          0 :         *aux_val |= val;
     916                 :          0 :         *aux_mask &= ~mask;
     917                 :          0 : }
     918                 :            : 
     919                 :            : static const struct l2x0_of_data pl310_data = {
     920                 :            :         .setup = pl310_of_setup,
     921                 :            :         .save  = pl310_save,
     922                 :            :         .outer_cache = {
     923                 :            :                 .resume      = pl310_resume,
     924                 :            :                 .inv_range   = l2x0_inv_range,
     925                 :            :                 .clean_range = l2x0_clean_range,
     926                 :            :                 .flush_range = l2x0_flush_range,
     927                 :            :                 .sync        = l2x0_cache_sync,
     928                 :            :                 .flush_all   = l2x0_flush_all,
     929                 :            :                 .inv_all     = l2x0_inv_all,
     930                 :            :                 .disable     = l2x0_disable,
     931                 :            :         },
     932                 :            : };
     933                 :            : 
     934                 :            : static const struct l2x0_of_data l2x0_data = {
     935                 :            :         .setup = l2x0_of_setup,
     936                 :            :         .save  = NULL,
     937                 :            :         .outer_cache = {
     938                 :            :                 .resume      = l2x0_resume,
     939                 :            :                 .inv_range   = l2x0_inv_range,
     940                 :            :                 .clean_range = l2x0_clean_range,
     941                 :            :                 .flush_range = l2x0_flush_range,
     942                 :            :                 .sync        = l2x0_cache_sync,
     943                 :            :                 .flush_all   = l2x0_flush_all,
     944                 :            :                 .inv_all     = l2x0_inv_all,
     945                 :            :                 .disable     = l2x0_disable,
     946                 :            :         },
     947                 :            : };
     948                 :            : 
     949                 :            : static const struct l2x0_of_data aurora_with_outer_data = {
     950                 :            :         .setup = aurora_of_setup,
     951                 :            :         .save  = aurora_save,
     952                 :            :         .outer_cache = {
     953                 :            :                 .resume      = aurora_resume,
     954                 :            :                 .inv_range   = aurora_inv_range,
     955                 :            :                 .clean_range = aurora_clean_range,
     956                 :            :                 .flush_range = aurora_flush_range,
     957                 :            :                 .sync        = l2x0_cache_sync,
     958                 :            :                 .flush_all   = l2x0_flush_all,
     959                 :            :                 .inv_all     = l2x0_inv_all,
     960                 :            :                 .disable     = l2x0_disable,
     961                 :            :         },
     962                 :            : };
     963                 :            : 
     964                 :            : static const struct l2x0_of_data aurora_no_outer_data = {
     965                 :            :         .setup = aurora_of_setup,
     966                 :            :         .save  = aurora_save,
     967                 :            :         .outer_cache = {
     968                 :            :                 .resume      = aurora_resume,
     969                 :            :         },
     970                 :            : };
     971                 :            : 
     972                 :            : static const struct l2x0_of_data tauros3_data = {
     973                 :            :         .setup = NULL,
     974                 :            :         .save  = tauros3_save,
     975                 :            :         /* Tauros3 broadcasts L1 cache operations to L2 */
     976                 :            :         .outer_cache = {
     977                 :            :                 .resume      = tauros3_resume,
     978                 :            :         },
     979                 :            : };
     980                 :            : 
     981                 :            : static const struct l2x0_of_data bcm_l2x0_data = {
     982                 :            :         .setup = pl310_of_setup,
     983                 :            :         .save  = pl310_save,
     984                 :            :         .outer_cache = {
     985                 :            :                 .resume      = pl310_resume,
     986                 :            :                 .inv_range   = bcm_inv_range,
     987                 :            :                 .clean_range = bcm_clean_range,
     988                 :            :                 .flush_range = bcm_flush_range,
     989                 :            :                 .sync        = l2x0_cache_sync,
     990                 :            :                 .flush_all   = l2x0_flush_all,
     991                 :            :                 .inv_all     = l2x0_inv_all,
     992                 :            :                 .disable     = l2x0_disable,
     993                 :            :         },
     994                 :            : };
     995                 :            : 
     996                 :            : static const struct of_device_id l2x0_ids[] __initconst = {
     997                 :            :         { .compatible = "arm,l210-cache", .data = (void *)&l2x0_data },
     998                 :            :         { .compatible = "arm,l220-cache", .data = (void *)&l2x0_data },
     999                 :            :         { .compatible = "arm,pl310-cache", .data = (void *)&pl310_data },
    1000                 :            :         { .compatible = "bcm,bcm11351-a2-pl310-cache", /* deprecated name */
    1001                 :            :           .data = (void *)&bcm_l2x0_data},
    1002                 :            :         { .compatible = "brcm,bcm11351-a2-pl310-cache",
    1003                 :            :           .data = (void *)&bcm_l2x0_data},
    1004                 :            :         { .compatible = "marvell,aurora-outer-cache",
    1005                 :            :           .data = (void *)&aurora_with_outer_data},
    1006                 :            :         { .compatible = "marvell,aurora-system-cache",
    1007                 :            :           .data = (void *)&aurora_no_outer_data},
    1008                 :            :         { .compatible = "marvell,tauros3-cache",
    1009                 :            :           .data = (void *)&tauros3_data },
    1010                 :            :         {}
    1011                 :            : };
    1012                 :            : 
    1013                 :          0 : int __init l2x0_of_init(u32 aux_val, u32 aux_mask)
    1014                 :            : {
    1015                 :            :         struct device_node *np;
    1016                 :            :         const struct l2x0_of_data *data;
    1017                 :            :         struct resource res;
    1018                 :            : 
    1019                 :            :         np = of_find_matching_node(NULL, l2x0_ids);
    1020         [ #  # ]:          0 :         if (!np)
    1021                 :            :                 return -ENODEV;
    1022                 :            : 
    1023         [ #  # ]:          0 :         if (of_address_to_resource(np, 0, &res))
    1024                 :            :                 return -ENODEV;
    1025                 :            : 
    1026                 :          0 :         l2x0_base = ioremap(res.start, resource_size(&res));
    1027         [ #  # ]:          0 :         if (!l2x0_base)
    1028                 :            :                 return -ENOMEM;
    1029                 :            : 
    1030                 :          0 :         l2x0_saved_regs.phy_base = res.start;
    1031                 :            : 
    1032                 :          0 :         data = of_match_node(l2x0_ids, np)->data;
    1033                 :            : 
    1034                 :            :         /* L2 configuration can only be changed if the cache is disabled */
    1035         [ #  # ]:          0 :         if (!(readl_relaxed(l2x0_base + L2X0_CTRL) & L2X0_CTRL_EN)) {
    1036         [ #  # ]:          0 :                 if (data->setup)
    1037                 :          0 :                         data->setup(np, &aux_val, &aux_mask);
    1038                 :            : 
    1039                 :            :                 /* For aurora cache in no outer mode select the
    1040                 :            :                  * correct mode using the coprocessor*/
    1041         [ #  # ]:          0 :                 if (data == &aurora_no_outer_data)
    1042                 :          0 :                         aurora_broadcast_l2_commands();
    1043                 :            :         }
    1044                 :            : 
    1045         [ #  # ]:          0 :         if (data->save)
    1046                 :          0 :                 data->save();
    1047                 :            : 
    1048                 :          0 :         of_init = true;
    1049                 :          0 :         memcpy(&outer_cache, &data->outer_cache, sizeof(outer_cache));
    1050                 :          0 :         l2x0_init(l2x0_base, aux_val, aux_mask);
    1051                 :            : 
    1052                 :          0 :         return 0;
    1053                 :            : }
    1054                 :            : #endif

Generated by: LCOV version 1.9