Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

powerpc/85xx: add cache-sram support

It adds cache-sram support in P1/P2 QorIQ platforms as under:

* A small abstraction over powerpc's remote heap allocator
* Exports mpc85xx_cache_sram_alloc()/free() APIs
* Supports only one contiguous SRAM window
* Drivers can do the following in Kconfig to use these APIs
"select FSL_85XX_CACHE_SRAM if MPC85xx"
* Required SRAM size and the offset where SRAM should be mapped must be
provided at kernel command line as :
cache-sram-size=<value>
cache-sram-offset=<offset>

Signed-off-by: Harninder Rai <harninder.rai@freescale.com>
Signed-off-by: Vivek Mahajan <vivek.mahajan@freescale.com>
Signed-off-by: Kumar Gala <galak@kernel.crashing.org>

authored by

Harninder Rai and committed by
Kumar Gala
6db92cc9 6341efe4

+540
+48
arch/powerpc/include/asm/fsl_85xx_cache_sram.h
··· 1 + /* 2 + * Copyright 2009 Freescale Semiconductor, Inc. 3 + * 4 + * Cache SRAM handling for QorIQ platform 5 + * 6 + * Author: Vivek Mahajan <vivek.mahajan@freescale.com> 7 + 8 + * This file is derived from the original work done 9 + * by Sylvain Munaut for the Bestcomm SRAM allocator. 10 + * 11 + * This program is free software; you can redistribute it and/or modify it 12 + * under the terms of the GNU General Public License as published by the 13 + * Free Software Foundation; either version 2 of the License, or (at your 14 + * option) any later version. 15 + * 16 + * This program is distributed in the hope that it will be useful, 17 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 + * GNU General Public License for more details. 20 + * 21 + * You should have received a copy of the GNU General Public License 22 + * along with this program; if not, write to the Free Software 23 + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 24 + */ 25 + 26 + #ifndef __ASM_POWERPC_FSL_85XX_CACHE_SRAM_H__ 27 + #define __ASM_POWERPC_FSL_85XX_CACHE_SRAM_H__ 28 + 29 + #include <asm/rheap.h> 30 + #include <linux/spinlock.h> 31 + 32 + /* 33 + * Cache-SRAM 34 + */ 35 + 36 + struct mpc85xx_cache_sram { 37 + phys_addr_t base_phys; 38 + void *base_virt; 39 + unsigned int size; 40 + rh_info_t *rh; 41 + spinlock_t lock; 42 + }; 43 + 44 + extern void mpc85xx_cache_sram_free(void *ptr); 45 + extern void *mpc85xx_cache_sram_alloc(unsigned int size, 46 + phys_addr_t *phys, unsigned int align); 47 + 48 + #endif /* __AMS_POWERPC_FSL_85XX_CACHE_SRAM_H__ */
+1
arch/powerpc/sysdev/Makefile
··· 18 18 obj-$(CONFIG_FSL_LBC) += fsl_lbc.o 19 19 obj-$(CONFIG_FSL_GTM) += fsl_gtm.o 20 20 obj-$(CONFIG_MPC8xxx_GPIO) += mpc8xxx_gpio.o 21 + obj-$(CONFIG_FSL_85XX_CACHE_SRAM) += fsl_85xx_l2ctlr.o fsl_85xx_cache_sram.o 21 22 obj-$(CONFIG_SIMPLE_GPIO) += simple_gpio.o 22 23 obj-$(CONFIG_RAPIDIO) += fsl_rio.o 23 24 obj-$(CONFIG_TSI108_BRIDGE) += tsi108_pci.o tsi108_dev.o
+101
arch/powerpc/sysdev/fsl_85xx_cache_ctlr.h
··· 1 + /* 2 + * Copyright 2009-2010 Freescale Semiconductor, Inc 3 + * 4 + * QorIQ based Cache Controller Memory Mapped Registers 5 + * 6 + * Author: Vivek Mahajan <vivek.mahajan@freescale.com> 7 + * 8 + * This program is free software; you can redistribute it and/or modify it 9 + * under the terms of the GNU General Public License as published by the 10 + * Free Software Foundation; either version 2 of the License, or (at your 11 + * option) any later version. 12 + * 13 + * This program is distributed in the hope that it will be useful, 14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 + * GNU General Public License for more details. 17 + * 18 + * You should have received a copy of the GNU General Public License 19 + * along with this program; if not, write to the Free Software 20 + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 21 + */ 22 + 23 + #ifndef __FSL_85XX_CACHE_CTLR_H__ 24 + #define __FSL_85XX_CACHE_CTLR_H__ 25 + 26 + #define L2CR_L2FI 0x40000000 /* L2 flash invalidate */ 27 + #define L2CR_L2IO 0x00200000 /* L2 instruction only */ 28 + #define L2CR_SRAM_ZERO 0x00000000 /* L2SRAM zero size */ 29 + #define L2CR_SRAM_FULL 0x00010000 /* L2SRAM full size */ 30 + #define L2CR_SRAM_HALF 0x00020000 /* L2SRAM half size */ 31 + #define L2CR_SRAM_TWO_HALFS 0x00030000 /* L2SRAM two half sizes */ 32 + #define L2CR_SRAM_QUART 0x00040000 /* L2SRAM one quarter size */ 33 + #define L2CR_SRAM_TWO_QUARTS 0x00050000 /* L2SRAM two quarter size */ 34 + #define L2CR_SRAM_EIGHTH 0x00060000 /* L2SRAM one eighth size */ 35 + #define L2CR_SRAM_TWO_EIGHTH 0x00070000 /* L2SRAM two eighth size */ 36 + 37 + #define L2SRAM_OPTIMAL_SZ_SHIFT 0x00000003 /* Optimum size for L2SRAM */ 38 + 39 + #define L2SRAM_BAR_MSK_LO18 0xFFFFC000 /* Lower 18 bits */ 40 + #define L2SRAM_BARE_MSK_HI4 0x0000000F /* Upper 4 bits */ 41 + 42 + enum cache_sram_lock_ways { 43 + LOCK_WAYS_ZERO, 44 + LOCK_WAYS_EIGHTH, 45 + LOCK_WAYS_TWO_EIGHTH, 46 + LOCK_WAYS_HALF = 4, 47 + LOCK_WAYS_FULL = 8, 48 + }; 49 + 50 + struct mpc85xx_l2ctlr { 51 + u32 ctl; /* 0x000 - L2 control */ 52 + u8 res1[0xC]; 53 + u32 ewar0; /* 0x010 - External write address 0 */ 54 + u32 ewarea0; /* 0x014 - External write address extended 0 */ 55 + u32 ewcr0; /* 0x018 - External write ctrl */ 56 + u8 res2[4]; 57 + u32 ewar1; /* 0x020 - External write address 1 */ 58 + u32 ewarea1; /* 0x024 - External write address extended 1 */ 59 + u32 ewcr1; /* 0x028 - External write ctrl 1 */ 60 + u8 res3[4]; 61 + u32 ewar2; /* 0x030 - External write address 2 */ 62 + u32 ewarea2; /* 0x034 - External write address extended 2 */ 63 + u32 ewcr2; /* 0x038 - External write ctrl 2 */ 64 + u8 res4[4]; 65 + u32 ewar3; /* 0x040 - External write address 3 */ 66 + u32 ewarea3; /* 0x044 - External write address extended 3 */ 67 + u32 ewcr3; /* 0x048 - External write ctrl 3 */ 68 + u8 res5[0xB4]; 69 + u32 srbar0; /* 0x100 - SRAM base address 0 */ 70 + u32 srbarea0; /* 0x104 - SRAM base addr reg ext address 0 */ 71 + u32 srbar1; /* 0x108 - SRAM base address 1 */ 72 + u32 srbarea1; /* 0x10C - SRAM base addr reg ext address 1 */ 73 + u8 res6[0xCF0]; 74 + u32 errinjhi; /* 0xE00 - Error injection mask high */ 75 + u32 errinjlo; /* 0xE04 - Error injection mask low */ 76 + u32 errinjctl; /* 0xE08 - Error injection tag/ecc control */ 77 + u8 res7[0x14]; 78 + u32 captdatahi; /* 0xE20 - Error data high capture */ 79 + u32 captdatalo; /* 0xE24 - Error data low capture */ 80 + u32 captecc; /* 0xE28 - Error syndrome */ 81 + u8 res8[0x14]; 82 + u32 errdet; /* 0xE40 - Error detect */ 83 + u32 errdis; /* 0xE44 - Error disable */ 84 + u32 errinten; /* 0xE48 - Error interrupt enable */ 85 + u32 errattr; /* 0xE4c - Error attribute capture */ 86 + u32 erradrrl; /* 0xE50 - Error address capture low */ 87 + u32 erradrrh; /* 0xE54 - Error address capture high */ 88 + u32 errctl; /* 0xE58 - Error control */ 89 + u8 res9[0x1A4]; 90 + }; 91 + 92 + struct sram_parameters { 93 + unsigned int sram_size; 94 + uint64_t sram_offset; 95 + }; 96 + 97 + extern int instantiate_cache_sram(struct platform_device *dev, 98 + struct sram_parameters sram_params); 99 + extern void remove_cache_sram(struct platform_device *dev); 100 + 101 + #endif /* __FSL_85XX_CACHE_CTLR_H__ */
+159
arch/powerpc/sysdev/fsl_85xx_cache_sram.c
··· 1 + /* 2 + * Copyright 2009-2010 Freescale Semiconductor, Inc. 3 + * 4 + * Simple memory allocator abstraction for QorIQ (P1/P2) based Cache-SRAM 5 + * 6 + * Author: Vivek Mahajan <vivek.mahajan@freescale.com> 7 + * 8 + * This file is derived from the original work done 9 + * by Sylvain Munaut for the Bestcomm SRAM allocator. 10 + * 11 + * This program is free software; you can redistribute it and/or modify it 12 + * under the terms of the GNU General Public License as published by the 13 + * Free Software Foundation; either version 2 of the License, or (at your 14 + * option) any later version. 15 + * 16 + * This program is distributed in the hope that it will be useful, 17 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 + * GNU General Public License for more details. 20 + * 21 + * You should have received a copy of the GNU General Public License 22 + * along with this program; if not, write to the Free Software 23 + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 24 + */ 25 + 26 + #include <linux/kernel.h> 27 + #include <linux/slab.h> 28 + #include <linux/err.h> 29 + #include <linux/of_platform.h> 30 + #include <asm/pgtable.h> 31 + #include <asm/fsl_85xx_cache_sram.h> 32 + 33 + #include "fsl_85xx_cache_ctlr.h" 34 + 35 + struct mpc85xx_cache_sram *cache_sram; 36 + 37 + void *mpc85xx_cache_sram_alloc(unsigned int size, 38 + phys_addr_t *phys, unsigned int align) 39 + { 40 + unsigned long offset; 41 + unsigned long flags; 42 + 43 + if (unlikely(cache_sram == NULL)) 44 + return NULL; 45 + 46 + if (!size || (size > cache_sram->size) || (align > cache_sram->size)) { 47 + pr_err("%s(): size(=%x) or align(=%x) zero or too big\n", 48 + __func__, size, align); 49 + return NULL; 50 + } 51 + 52 + if ((align & (align - 1)) || align <= 1) { 53 + pr_err("%s(): align(=%x) must be power of two and >1\n", 54 + __func__, align); 55 + return NULL; 56 + } 57 + 58 + spin_lock_irqsave(&cache_sram->lock, flags); 59 + offset = rh_alloc_align(cache_sram->rh, size, align, NULL); 60 + spin_unlock_irqrestore(&cache_sram->lock, flags); 61 + 62 + if (IS_ERR_VALUE(offset)) 63 + return NULL; 64 + 65 + *phys = cache_sram->base_phys + offset; 66 + 67 + return (unsigned char *)cache_sram->base_virt + offset; 68 + } 69 + EXPORT_SYMBOL(mpc85xx_cache_sram_alloc); 70 + 71 + void mpc85xx_cache_sram_free(void *ptr) 72 + { 73 + unsigned long flags; 74 + BUG_ON(!ptr); 75 + 76 + spin_lock_irqsave(&cache_sram->lock, flags); 77 + rh_free(cache_sram->rh, ptr - cache_sram->base_virt); 78 + spin_unlock_irqrestore(&cache_sram->lock, flags); 79 + } 80 + EXPORT_SYMBOL(mpc85xx_cache_sram_free); 81 + 82 + int __init instantiate_cache_sram(struct platform_device *dev, 83 + struct sram_parameters sram_params) 84 + { 85 + int ret = 0; 86 + 87 + if (cache_sram) { 88 + dev_err(&dev->dev, "Already initialized cache-sram\n"); 89 + return -EBUSY; 90 + } 91 + 92 + cache_sram = kzalloc(sizeof(struct mpc85xx_cache_sram), GFP_KERNEL); 93 + if (!cache_sram) { 94 + dev_err(&dev->dev, "Out of memory for cache_sram structure\n"); 95 + return -ENOMEM; 96 + } 97 + 98 + cache_sram->base_phys = sram_params.sram_offset; 99 + cache_sram->size = sram_params.sram_size; 100 + 101 + if (!request_mem_region(cache_sram->base_phys, cache_sram->size, 102 + "fsl_85xx_cache_sram")) { 103 + dev_err(&dev->dev, "%s: request memory failed\n", 104 + dev->dev.of_node->full_name); 105 + ret = -ENXIO; 106 + goto out_free; 107 + } 108 + 109 + cache_sram->base_virt = ioremap_flags(cache_sram->base_phys, 110 + cache_sram->size, _PAGE_COHERENT | PAGE_KERNEL); 111 + if (!cache_sram->base_virt) { 112 + dev_err(&dev->dev, "%s: ioremap_flags failed\n", 113 + dev->dev.of_node->full_name); 114 + ret = -ENOMEM; 115 + goto out_release; 116 + } 117 + 118 + cache_sram->rh = rh_create(sizeof(unsigned int)); 119 + if (IS_ERR(cache_sram->rh)) { 120 + dev_err(&dev->dev, "%s: Unable to create remote heap\n", 121 + dev->dev.of_node->full_name); 122 + ret = PTR_ERR(cache_sram->rh); 123 + goto out_unmap; 124 + } 125 + 126 + rh_attach_region(cache_sram->rh, 0, cache_sram->size); 127 + spin_lock_init(&cache_sram->lock); 128 + 129 + dev_info(&dev->dev, "[base:0x%llx, size:0x%x] configured and loaded\n", 130 + (unsigned long long)cache_sram->base_phys, cache_sram->size); 131 + 132 + return 0; 133 + 134 + out_unmap: 135 + iounmap(cache_sram->base_virt); 136 + 137 + out_release: 138 + release_mem_region(cache_sram->base_phys, cache_sram->size); 139 + 140 + out_free: 141 + kfree(cache_sram); 142 + return ret; 143 + } 144 + 145 + void remove_cache_sram(struct platform_device *dev) 146 + { 147 + BUG_ON(!cache_sram); 148 + 149 + rh_detach_region(cache_sram->rh, 0, cache_sram->size); 150 + rh_destroy(cache_sram->rh); 151 + 152 + iounmap(cache_sram->base_virt); 153 + release_mem_region(cache_sram->base_phys, cache_sram->size); 154 + 155 + kfree(cache_sram); 156 + cache_sram = NULL; 157 + 158 + dev_info(&dev->dev, "MPC85xx Cache-SRAM driver unloaded\n"); 159 + }
+231
arch/powerpc/sysdev/fsl_85xx_l2ctlr.c
··· 1 + /* 2 + * Copyright 2009-2010 Freescale Semiconductor, Inc. 3 + * 4 + * QorIQ (P1/P2) L2 controller init for Cache-SRAM instantiation 5 + * 6 + * Author: Vivek Mahajan <vivek.mahajan@freescale.com> 7 + * 8 + * This program is free software; you can redistribute it and/or modify it 9 + * under the terms of the GNU General Public License as published by the 10 + * Free Software Foundation; either version 2 of the License, or (at your 11 + * option) any later version. 12 + * 13 + * This program is distributed in the hope that it will be useful, 14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 + * GNU General Public License for more details. 17 + * 18 + * You should have received a copy of the GNU General Public License 19 + * along with this program; if not, write to the Free Software 20 + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 21 + */ 22 + 23 + #include <linux/kernel.h> 24 + #include <linux/of_platform.h> 25 + #include <asm/io.h> 26 + 27 + #include "fsl_85xx_cache_ctlr.h" 28 + 29 + static char *sram_size; 30 + static char *sram_offset; 31 + struct mpc85xx_l2ctlr __iomem *l2ctlr; 32 + 33 + static long get_cache_sram_size(void) 34 + { 35 + unsigned long val; 36 + 37 + if (!sram_size || (strict_strtoul(sram_size, 0, &val) < 0)) 38 + return -EINVAL; 39 + 40 + return val; 41 + } 42 + 43 + static long get_cache_sram_offset(void) 44 + { 45 + unsigned long val; 46 + 47 + if (!sram_offset || (strict_strtoul(sram_offset, 0, &val) < 0)) 48 + return -EINVAL; 49 + 50 + return val; 51 + } 52 + 53 + static int __init get_size_from_cmdline(char *str) 54 + { 55 + if (!str) 56 + return 0; 57 + 58 + sram_size = str; 59 + return 1; 60 + } 61 + 62 + static int __init get_offset_from_cmdline(char *str) 63 + { 64 + if (!str) 65 + return 0; 66 + 67 + sram_offset = str; 68 + return 1; 69 + } 70 + 71 + __setup("cache-sram-size=", get_size_from_cmdline); 72 + __setup("cache-sram-offset=", get_offset_from_cmdline); 73 + 74 + static int __devinit mpc85xx_l2ctlr_of_probe(struct platform_device *dev, 75 + const struct of_device_id *match) 76 + { 77 + long rval; 78 + unsigned int rem; 79 + unsigned char ways; 80 + const unsigned int *prop; 81 + unsigned int l2cache_size; 82 + struct sram_parameters sram_params; 83 + 84 + if (!dev->dev.of_node) { 85 + dev_err(&dev->dev, "Device's OF-node is NULL\n"); 86 + return -EINVAL; 87 + } 88 + 89 + prop = of_get_property(dev->dev.of_node, "cache-size", NULL); 90 + if (!prop) { 91 + dev_err(&dev->dev, "Missing L2 cache-size\n"); 92 + return -EINVAL; 93 + } 94 + l2cache_size = *prop; 95 + 96 + sram_params.sram_size = get_cache_sram_size(); 97 + if (sram_params.sram_size <= 0) { 98 + dev_err(&dev->dev, 99 + "Entire L2 as cache, Aborting Cache-SRAM stuff\n"); 100 + return -EINVAL; 101 + } 102 + 103 + sram_params.sram_offset = get_cache_sram_offset(); 104 + if (sram_params.sram_offset <= 0) { 105 + dev_err(&dev->dev, 106 + "Entire L2 as cache, provide a valid sram offset\n"); 107 + return -EINVAL; 108 + } 109 + 110 + 111 + rem = l2cache_size % sram_params.sram_size; 112 + ways = LOCK_WAYS_FULL * sram_params.sram_size / l2cache_size; 113 + if (rem || (ways & (ways - 1))) { 114 + dev_err(&dev->dev, "Illegal cache-sram-size in command line\n"); 115 + return -EINVAL; 116 + } 117 + 118 + l2ctlr = of_iomap(dev->dev.of_node, 0); 119 + if (!l2ctlr) { 120 + dev_err(&dev->dev, "Can't map L2 controller\n"); 121 + return -EINVAL; 122 + } 123 + 124 + /* 125 + * Write bits[0-17] to srbar0 126 + */ 127 + out_be32(&l2ctlr->srbar0, 128 + sram_params.sram_offset & L2SRAM_BAR_MSK_LO18); 129 + 130 + /* 131 + * Write bits[18-21] to srbare0 132 + */ 133 + #ifdef CONFIG_PHYS_64BIT 134 + out_be32(&l2ctlr->srbarea0, 135 + (sram_params.sram_offset >> 32) & L2SRAM_BARE_MSK_HI4); 136 + #endif 137 + 138 + clrsetbits_be32(&l2ctlr->ctl, L2CR_L2E, L2CR_L2FI); 139 + 140 + switch (ways) { 141 + case LOCK_WAYS_EIGHTH: 142 + setbits32(&l2ctlr->ctl, 143 + L2CR_L2E | L2CR_L2FI | L2CR_SRAM_EIGHTH); 144 + break; 145 + 146 + case LOCK_WAYS_TWO_EIGHTH: 147 + setbits32(&l2ctlr->ctl, 148 + L2CR_L2E | L2CR_L2FI | L2CR_SRAM_QUART); 149 + break; 150 + 151 + case LOCK_WAYS_HALF: 152 + setbits32(&l2ctlr->ctl, 153 + L2CR_L2E | L2CR_L2FI | L2CR_SRAM_HALF); 154 + break; 155 + 156 + case LOCK_WAYS_FULL: 157 + default: 158 + setbits32(&l2ctlr->ctl, 159 + L2CR_L2E | L2CR_L2FI | L2CR_SRAM_FULL); 160 + break; 161 + } 162 + eieio(); 163 + 164 + rval = instantiate_cache_sram(dev, sram_params); 165 + if (rval < 0) { 166 + dev_err(&dev->dev, "Can't instantiate Cache-SRAM\n"); 167 + iounmap(l2ctlr); 168 + return -EINVAL; 169 + } 170 + 171 + return 0; 172 + } 173 + 174 + static int __devexit mpc85xx_l2ctlr_of_remove(struct platform_device *dev) 175 + { 176 + BUG_ON(!l2ctlr); 177 + 178 + iounmap(l2ctlr); 179 + remove_cache_sram(dev); 180 + dev_info(&dev->dev, "MPC85xx L2 controller unloaded\n"); 181 + 182 + return 0; 183 + } 184 + 185 + static struct of_device_id mpc85xx_l2ctlr_of_match[] = { 186 + { 187 + .compatible = "fsl,p2020-l2-cache-controller", 188 + }, 189 + { 190 + .compatible = "fsl,p2010-l2-cache-controller", 191 + }, 192 + { 193 + .compatible = "fsl,p1020-l2-cache-controller", 194 + }, 195 + { 196 + .compatible = "fsl,p1011-l2-cache-controller", 197 + }, 198 + { 199 + .compatible = "fsl,p1013-l2-cache-controller", 200 + }, 201 + { 202 + .compatible = "fsl,p1022-l2-cache-controller", 203 + }, 204 + {}, 205 + }; 206 + 207 + static struct of_platform_driver mpc85xx_l2ctlr_of_platform_driver = { 208 + .driver = { 209 + .name = "fsl-l2ctlr", 210 + .owner = THIS_MODULE, 211 + .of_match_table = mpc85xx_l2ctlr_of_match, 212 + }, 213 + .probe = mpc85xx_l2ctlr_of_probe, 214 + .remove = __devexit_p(mpc85xx_l2ctlr_of_remove), 215 + }; 216 + 217 + static __init int mpc85xx_l2ctlr_of_init(void) 218 + { 219 + return of_register_platform_driver(&mpc85xx_l2ctlr_of_platform_driver); 220 + } 221 + 222 + static void __exit mpc85xx_l2ctlr_of_exit(void) 223 + { 224 + of_unregister_platform_driver(&mpc85xx_l2ctlr_of_platform_driver); 225 + } 226 + 227 + subsys_initcall(mpc85xx_l2ctlr_of_init); 228 + module_exit(mpc85xx_l2ctlr_of_exit); 229 + 230 + MODULE_DESCRIPTION("Freescale MPC85xx L2 controller init"); 231 + MODULE_LICENSE("GPL v2");