18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright 2009-2010, 2012 Freescale Semiconductor, Inc. 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * QorIQ (P1/P2) L2 controller init for Cache-SRAM instantiation 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * Author: Vivek Mahajan <vivek.mahajan@freescale.com> 88c2ecf20Sopenharmony_ci */ 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_ci#include <linux/kernel.h> 118c2ecf20Sopenharmony_ci#include <linux/module.h> 128c2ecf20Sopenharmony_ci#include <linux/of_platform.h> 138c2ecf20Sopenharmony_ci#include <asm/io.h> 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_ci#include "fsl_85xx_cache_ctlr.h" 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_cistatic char *sram_size; 188c2ecf20Sopenharmony_cistatic char *sram_offset; 198c2ecf20Sopenharmony_cistruct mpc85xx_l2ctlr __iomem *l2ctlr; 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_cistatic int get_cache_sram_params(struct sram_parameters *sram_params) 228c2ecf20Sopenharmony_ci{ 238c2ecf20Sopenharmony_ci unsigned long long addr; 248c2ecf20Sopenharmony_ci unsigned int size; 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_ci if (!sram_size || (kstrtouint(sram_size, 0, &size) < 0)) 278c2ecf20Sopenharmony_ci return -EINVAL; 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_ci if (!sram_offset || (kstrtoull(sram_offset, 0, &addr) < 0)) 308c2ecf20Sopenharmony_ci return -EINVAL; 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_ci sram_params->sram_offset = addr; 338c2ecf20Sopenharmony_ci sram_params->sram_size = size; 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_ci return 0; 368c2ecf20Sopenharmony_ci} 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_cistatic int __init get_size_from_cmdline(char *str) 398c2ecf20Sopenharmony_ci{ 408c2ecf20Sopenharmony_ci if (!str) 418c2ecf20Sopenharmony_ci return 0; 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_ci sram_size = str; 448c2ecf20Sopenharmony_ci return 1; 458c2ecf20Sopenharmony_ci} 468c2ecf20Sopenharmony_ci 478c2ecf20Sopenharmony_cistatic int __init get_offset_from_cmdline(char *str) 488c2ecf20Sopenharmony_ci{ 498c2ecf20Sopenharmony_ci if (!str) 508c2ecf20Sopenharmony_ci return 0; 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_ci sram_offset = str; 538c2ecf20Sopenharmony_ci return 1; 548c2ecf20Sopenharmony_ci} 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_ci__setup("cache-sram-size=", get_size_from_cmdline); 578c2ecf20Sopenharmony_ci__setup("cache-sram-offset=", get_offset_from_cmdline); 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_cistatic int mpc85xx_l2ctlr_of_probe(struct platform_device *dev) 608c2ecf20Sopenharmony_ci{ 618c2ecf20Sopenharmony_ci long rval; 628c2ecf20Sopenharmony_ci unsigned int rem; 638c2ecf20Sopenharmony_ci unsigned char ways; 648c2ecf20Sopenharmony_ci const unsigned int *prop; 658c2ecf20Sopenharmony_ci unsigned int l2cache_size; 668c2ecf20Sopenharmony_ci struct sram_parameters sram_params; 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_ci if (!dev->dev.of_node) { 698c2ecf20Sopenharmony_ci dev_err(&dev->dev, "Device's OF-node is NULL\n"); 708c2ecf20Sopenharmony_ci return -EINVAL; 718c2ecf20Sopenharmony_ci } 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_ci prop = of_get_property(dev->dev.of_node, "cache-size", NULL); 748c2ecf20Sopenharmony_ci if (!prop) { 758c2ecf20Sopenharmony_ci dev_err(&dev->dev, "Missing L2 cache-size\n"); 768c2ecf20Sopenharmony_ci return -EINVAL; 778c2ecf20Sopenharmony_ci } 788c2ecf20Sopenharmony_ci l2cache_size = *prop; 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_ci if (get_cache_sram_params(&sram_params)) 818c2ecf20Sopenharmony_ci return 0; /* fall back to L2 cache only */ 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_ci rem = l2cache_size % sram_params.sram_size; 848c2ecf20Sopenharmony_ci ways = LOCK_WAYS_FULL * sram_params.sram_size / l2cache_size; 858c2ecf20Sopenharmony_ci if (rem || (ways & (ways - 1))) { 868c2ecf20Sopenharmony_ci dev_err(&dev->dev, "Illegal cache-sram-size in command line\n"); 878c2ecf20Sopenharmony_ci return -EINVAL; 888c2ecf20Sopenharmony_ci } 898c2ecf20Sopenharmony_ci 908c2ecf20Sopenharmony_ci l2ctlr = of_iomap(dev->dev.of_node, 0); 918c2ecf20Sopenharmony_ci if (!l2ctlr) { 928c2ecf20Sopenharmony_ci dev_err(&dev->dev, "Can't map L2 controller\n"); 938c2ecf20Sopenharmony_ci return -EINVAL; 948c2ecf20Sopenharmony_ci } 958c2ecf20Sopenharmony_ci 968c2ecf20Sopenharmony_ci /* 978c2ecf20Sopenharmony_ci * Write bits[0-17] to srbar0 988c2ecf20Sopenharmony_ci */ 998c2ecf20Sopenharmony_ci out_be32(&l2ctlr->srbar0, 1008c2ecf20Sopenharmony_ci lower_32_bits(sram_params.sram_offset) & L2SRAM_BAR_MSK_LO18); 1018c2ecf20Sopenharmony_ci 1028c2ecf20Sopenharmony_ci /* 1038c2ecf20Sopenharmony_ci * Write bits[18-21] to srbare0 1048c2ecf20Sopenharmony_ci */ 1058c2ecf20Sopenharmony_ci#ifdef CONFIG_PHYS_64BIT 1068c2ecf20Sopenharmony_ci out_be32(&l2ctlr->srbarea0, 1078c2ecf20Sopenharmony_ci upper_32_bits(sram_params.sram_offset) & L2SRAM_BARE_MSK_HI4); 1088c2ecf20Sopenharmony_ci#endif 1098c2ecf20Sopenharmony_ci 1108c2ecf20Sopenharmony_ci clrsetbits_be32(&l2ctlr->ctl, L2CR_L2E, L2CR_L2FI); 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_ci switch (ways) { 1138c2ecf20Sopenharmony_ci case LOCK_WAYS_EIGHTH: 1148c2ecf20Sopenharmony_ci setbits32(&l2ctlr->ctl, 1158c2ecf20Sopenharmony_ci L2CR_L2E | L2CR_L2FI | L2CR_SRAM_EIGHTH); 1168c2ecf20Sopenharmony_ci break; 1178c2ecf20Sopenharmony_ci 1188c2ecf20Sopenharmony_ci case LOCK_WAYS_TWO_EIGHTH: 1198c2ecf20Sopenharmony_ci setbits32(&l2ctlr->ctl, 1208c2ecf20Sopenharmony_ci L2CR_L2E | L2CR_L2FI | L2CR_SRAM_QUART); 1218c2ecf20Sopenharmony_ci break; 1228c2ecf20Sopenharmony_ci 1238c2ecf20Sopenharmony_ci case LOCK_WAYS_HALF: 1248c2ecf20Sopenharmony_ci setbits32(&l2ctlr->ctl, 1258c2ecf20Sopenharmony_ci L2CR_L2E | L2CR_L2FI | L2CR_SRAM_HALF); 1268c2ecf20Sopenharmony_ci break; 1278c2ecf20Sopenharmony_ci 1288c2ecf20Sopenharmony_ci case LOCK_WAYS_FULL: 1298c2ecf20Sopenharmony_ci default: 1308c2ecf20Sopenharmony_ci setbits32(&l2ctlr->ctl, 1318c2ecf20Sopenharmony_ci L2CR_L2E | L2CR_L2FI | L2CR_SRAM_FULL); 1328c2ecf20Sopenharmony_ci break; 1338c2ecf20Sopenharmony_ci } 1348c2ecf20Sopenharmony_ci eieio(); 1358c2ecf20Sopenharmony_ci 1368c2ecf20Sopenharmony_ci rval = instantiate_cache_sram(dev, sram_params); 1378c2ecf20Sopenharmony_ci if (rval < 0) { 1388c2ecf20Sopenharmony_ci dev_err(&dev->dev, "Can't instantiate Cache-SRAM\n"); 1398c2ecf20Sopenharmony_ci iounmap(l2ctlr); 1408c2ecf20Sopenharmony_ci return -EINVAL; 1418c2ecf20Sopenharmony_ci } 1428c2ecf20Sopenharmony_ci 1438c2ecf20Sopenharmony_ci return 0; 1448c2ecf20Sopenharmony_ci} 1458c2ecf20Sopenharmony_ci 1468c2ecf20Sopenharmony_cistatic int mpc85xx_l2ctlr_of_remove(struct platform_device *dev) 1478c2ecf20Sopenharmony_ci{ 1488c2ecf20Sopenharmony_ci BUG_ON(!l2ctlr); 1498c2ecf20Sopenharmony_ci 1508c2ecf20Sopenharmony_ci iounmap(l2ctlr); 1518c2ecf20Sopenharmony_ci remove_cache_sram(dev); 1528c2ecf20Sopenharmony_ci dev_info(&dev->dev, "MPC85xx L2 controller unloaded\n"); 1538c2ecf20Sopenharmony_ci 1548c2ecf20Sopenharmony_ci return 0; 1558c2ecf20Sopenharmony_ci} 1568c2ecf20Sopenharmony_ci 1578c2ecf20Sopenharmony_cistatic const struct of_device_id mpc85xx_l2ctlr_of_match[] = { 1588c2ecf20Sopenharmony_ci { 1598c2ecf20Sopenharmony_ci .compatible = "fsl,p2020-l2-cache-controller", 1608c2ecf20Sopenharmony_ci }, 1618c2ecf20Sopenharmony_ci { 1628c2ecf20Sopenharmony_ci .compatible = "fsl,p2010-l2-cache-controller", 1638c2ecf20Sopenharmony_ci }, 1648c2ecf20Sopenharmony_ci { 1658c2ecf20Sopenharmony_ci .compatible = "fsl,p1020-l2-cache-controller", 1668c2ecf20Sopenharmony_ci }, 1678c2ecf20Sopenharmony_ci { 1688c2ecf20Sopenharmony_ci .compatible = "fsl,p1011-l2-cache-controller", 1698c2ecf20Sopenharmony_ci }, 1708c2ecf20Sopenharmony_ci { 1718c2ecf20Sopenharmony_ci .compatible = "fsl,p1013-l2-cache-controller", 1728c2ecf20Sopenharmony_ci }, 1738c2ecf20Sopenharmony_ci { 1748c2ecf20Sopenharmony_ci .compatible = "fsl,p1022-l2-cache-controller", 1758c2ecf20Sopenharmony_ci }, 1768c2ecf20Sopenharmony_ci { 1778c2ecf20Sopenharmony_ci .compatible = "fsl,mpc8548-l2-cache-controller", 1788c2ecf20Sopenharmony_ci }, 1798c2ecf20Sopenharmony_ci { .compatible = "fsl,mpc8544-l2-cache-controller",}, 1808c2ecf20Sopenharmony_ci { .compatible = "fsl,mpc8572-l2-cache-controller",}, 1818c2ecf20Sopenharmony_ci { .compatible = "fsl,mpc8536-l2-cache-controller",}, 1828c2ecf20Sopenharmony_ci { .compatible = "fsl,p1021-l2-cache-controller",}, 1838c2ecf20Sopenharmony_ci { .compatible = "fsl,p1012-l2-cache-controller",}, 1848c2ecf20Sopenharmony_ci { .compatible = "fsl,p1025-l2-cache-controller",}, 1858c2ecf20Sopenharmony_ci { .compatible = "fsl,p1016-l2-cache-controller",}, 1868c2ecf20Sopenharmony_ci { .compatible = "fsl,p1024-l2-cache-controller",}, 1878c2ecf20Sopenharmony_ci { .compatible = "fsl,p1015-l2-cache-controller",}, 1888c2ecf20Sopenharmony_ci { .compatible = "fsl,p1010-l2-cache-controller",}, 1898c2ecf20Sopenharmony_ci { .compatible = "fsl,bsc9131-l2-cache-controller",}, 1908c2ecf20Sopenharmony_ci {}, 1918c2ecf20Sopenharmony_ci}; 1928c2ecf20Sopenharmony_ci 1938c2ecf20Sopenharmony_cistatic struct platform_driver mpc85xx_l2ctlr_of_platform_driver = { 1948c2ecf20Sopenharmony_ci .driver = { 1958c2ecf20Sopenharmony_ci .name = "fsl-l2ctlr", 1968c2ecf20Sopenharmony_ci .of_match_table = mpc85xx_l2ctlr_of_match, 1978c2ecf20Sopenharmony_ci }, 1988c2ecf20Sopenharmony_ci .probe = mpc85xx_l2ctlr_of_probe, 1998c2ecf20Sopenharmony_ci .remove = mpc85xx_l2ctlr_of_remove, 2008c2ecf20Sopenharmony_ci}; 2018c2ecf20Sopenharmony_ci 2028c2ecf20Sopenharmony_cistatic __init int mpc85xx_l2ctlr_of_init(void) 2038c2ecf20Sopenharmony_ci{ 2048c2ecf20Sopenharmony_ci return platform_driver_register(&mpc85xx_l2ctlr_of_platform_driver); 2058c2ecf20Sopenharmony_ci} 2068c2ecf20Sopenharmony_ci 2078c2ecf20Sopenharmony_cistatic void __exit mpc85xx_l2ctlr_of_exit(void) 2088c2ecf20Sopenharmony_ci{ 2098c2ecf20Sopenharmony_ci platform_driver_unregister(&mpc85xx_l2ctlr_of_platform_driver); 2108c2ecf20Sopenharmony_ci} 2118c2ecf20Sopenharmony_ci 2128c2ecf20Sopenharmony_cisubsys_initcall(mpc85xx_l2ctlr_of_init); 2138c2ecf20Sopenharmony_cimodule_exit(mpc85xx_l2ctlr_of_exit); 2148c2ecf20Sopenharmony_ci 2158c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("Freescale MPC85xx L2 controller init"); 2168c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL v2"); 217