18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Atheros AR71XX/AR724X/AR913X common routines 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (C) 2010-2011 Jaiganesh Narayanan <jnarayanan@atheros.com> 68c2ecf20Sopenharmony_ci * Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org> 78c2ecf20Sopenharmony_ci * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> 88c2ecf20Sopenharmony_ci * 98c2ecf20Sopenharmony_ci * Parts of this file are based on Atheros' 2.6.15/2.6.31 BSP 108c2ecf20Sopenharmony_ci */ 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_ci#include <linux/kernel.h> 138c2ecf20Sopenharmony_ci#include <linux/export.h> 148c2ecf20Sopenharmony_ci#include <linux/types.h> 158c2ecf20Sopenharmony_ci#include <linux/spinlock.h> 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_ci#include <asm/mach-ath79/ath79.h> 188c2ecf20Sopenharmony_ci#include <asm/mach-ath79/ar71xx_regs.h> 198c2ecf20Sopenharmony_ci#include "common.h" 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_cistatic DEFINE_SPINLOCK(ath79_device_reset_lock); 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_ciu32 ath79_cpu_freq; 248c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(ath79_cpu_freq); 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_ciu32 ath79_ahb_freq; 278c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(ath79_ahb_freq); 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_ciu32 ath79_ddr_freq; 308c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(ath79_ddr_freq); 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_cienum ath79_soc_type ath79_soc; 338c2ecf20Sopenharmony_ciunsigned int ath79_soc_rev; 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_civoid __iomem *ath79_pll_base; 368c2ecf20Sopenharmony_civoid __iomem *ath79_reset_base; 378c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(ath79_reset_base); 388c2ecf20Sopenharmony_cistatic void __iomem *ath79_ddr_base; 398c2ecf20Sopenharmony_cistatic void __iomem *ath79_ddr_wb_flush_base; 408c2ecf20Sopenharmony_cistatic void __iomem *ath79_ddr_pci_win_base; 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_civoid ath79_ddr_ctrl_init(void) 438c2ecf20Sopenharmony_ci{ 448c2ecf20Sopenharmony_ci ath79_ddr_base = ioremap(AR71XX_DDR_CTRL_BASE, 458c2ecf20Sopenharmony_ci AR71XX_DDR_CTRL_SIZE); 468c2ecf20Sopenharmony_ci if (soc_is_ar913x() || soc_is_ar724x() || soc_is_ar933x()) { 478c2ecf20Sopenharmony_ci ath79_ddr_wb_flush_base = ath79_ddr_base + 0x7c; 488c2ecf20Sopenharmony_ci ath79_ddr_pci_win_base = 0; 498c2ecf20Sopenharmony_ci } else { 508c2ecf20Sopenharmony_ci ath79_ddr_wb_flush_base = ath79_ddr_base + 0x9c; 518c2ecf20Sopenharmony_ci ath79_ddr_pci_win_base = ath79_ddr_base + 0x7c; 528c2ecf20Sopenharmony_ci } 538c2ecf20Sopenharmony_ci} 548c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(ath79_ddr_ctrl_init); 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_civoid ath79_ddr_wb_flush(u32 reg) 578c2ecf20Sopenharmony_ci{ 588c2ecf20Sopenharmony_ci void __iomem *flush_reg = ath79_ddr_wb_flush_base + (reg * 4); 598c2ecf20Sopenharmony_ci 608c2ecf20Sopenharmony_ci /* Flush the DDR write buffer. */ 618c2ecf20Sopenharmony_ci __raw_writel(0x1, flush_reg); 628c2ecf20Sopenharmony_ci while (__raw_readl(flush_reg) & 0x1) 638c2ecf20Sopenharmony_ci ; 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_ci /* It must be run twice. */ 668c2ecf20Sopenharmony_ci __raw_writel(0x1, flush_reg); 678c2ecf20Sopenharmony_ci while (__raw_readl(flush_reg) & 0x1) 688c2ecf20Sopenharmony_ci ; 698c2ecf20Sopenharmony_ci} 708c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(ath79_ddr_wb_flush); 718c2ecf20Sopenharmony_ci 728c2ecf20Sopenharmony_civoid ath79_ddr_set_pci_windows(void) 738c2ecf20Sopenharmony_ci{ 748c2ecf20Sopenharmony_ci BUG_ON(!ath79_ddr_pci_win_base); 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_ci __raw_writel(AR71XX_PCI_WIN0_OFFS, ath79_ddr_pci_win_base + 0x0); 778c2ecf20Sopenharmony_ci __raw_writel(AR71XX_PCI_WIN1_OFFS, ath79_ddr_pci_win_base + 0x4); 788c2ecf20Sopenharmony_ci __raw_writel(AR71XX_PCI_WIN2_OFFS, ath79_ddr_pci_win_base + 0x8); 798c2ecf20Sopenharmony_ci __raw_writel(AR71XX_PCI_WIN3_OFFS, ath79_ddr_pci_win_base + 0xc); 808c2ecf20Sopenharmony_ci __raw_writel(AR71XX_PCI_WIN4_OFFS, ath79_ddr_pci_win_base + 0x10); 818c2ecf20Sopenharmony_ci __raw_writel(AR71XX_PCI_WIN5_OFFS, ath79_ddr_pci_win_base + 0x14); 828c2ecf20Sopenharmony_ci __raw_writel(AR71XX_PCI_WIN6_OFFS, ath79_ddr_pci_win_base + 0x18); 838c2ecf20Sopenharmony_ci __raw_writel(AR71XX_PCI_WIN7_OFFS, ath79_ddr_pci_win_base + 0x1c); 848c2ecf20Sopenharmony_ci} 858c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(ath79_ddr_set_pci_windows); 868c2ecf20Sopenharmony_ci 878c2ecf20Sopenharmony_civoid ath79_device_reset_set(u32 mask) 888c2ecf20Sopenharmony_ci{ 898c2ecf20Sopenharmony_ci unsigned long flags; 908c2ecf20Sopenharmony_ci u32 reg; 918c2ecf20Sopenharmony_ci u32 t; 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_ci if (soc_is_ar71xx()) 948c2ecf20Sopenharmony_ci reg = AR71XX_RESET_REG_RESET_MODULE; 958c2ecf20Sopenharmony_ci else if (soc_is_ar724x()) 968c2ecf20Sopenharmony_ci reg = AR724X_RESET_REG_RESET_MODULE; 978c2ecf20Sopenharmony_ci else if (soc_is_ar913x()) 988c2ecf20Sopenharmony_ci reg = AR913X_RESET_REG_RESET_MODULE; 998c2ecf20Sopenharmony_ci else if (soc_is_ar933x()) 1008c2ecf20Sopenharmony_ci reg = AR933X_RESET_REG_RESET_MODULE; 1018c2ecf20Sopenharmony_ci else if (soc_is_ar934x()) 1028c2ecf20Sopenharmony_ci reg = AR934X_RESET_REG_RESET_MODULE; 1038c2ecf20Sopenharmony_ci else if (soc_is_qca953x()) 1048c2ecf20Sopenharmony_ci reg = QCA953X_RESET_REG_RESET_MODULE; 1058c2ecf20Sopenharmony_ci else if (soc_is_qca955x()) 1068c2ecf20Sopenharmony_ci reg = QCA955X_RESET_REG_RESET_MODULE; 1078c2ecf20Sopenharmony_ci else if (soc_is_qca956x() || soc_is_tp9343()) 1088c2ecf20Sopenharmony_ci reg = QCA956X_RESET_REG_RESET_MODULE; 1098c2ecf20Sopenharmony_ci else 1108c2ecf20Sopenharmony_ci BUG(); 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_ci spin_lock_irqsave(&ath79_device_reset_lock, flags); 1138c2ecf20Sopenharmony_ci t = ath79_reset_rr(reg); 1148c2ecf20Sopenharmony_ci ath79_reset_wr(reg, t | mask); 1158c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&ath79_device_reset_lock, flags); 1168c2ecf20Sopenharmony_ci} 1178c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(ath79_device_reset_set); 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_civoid ath79_device_reset_clear(u32 mask) 1208c2ecf20Sopenharmony_ci{ 1218c2ecf20Sopenharmony_ci unsigned long flags; 1228c2ecf20Sopenharmony_ci u32 reg; 1238c2ecf20Sopenharmony_ci u32 t; 1248c2ecf20Sopenharmony_ci 1258c2ecf20Sopenharmony_ci if (soc_is_ar71xx()) 1268c2ecf20Sopenharmony_ci reg = AR71XX_RESET_REG_RESET_MODULE; 1278c2ecf20Sopenharmony_ci else if (soc_is_ar724x()) 1288c2ecf20Sopenharmony_ci reg = AR724X_RESET_REG_RESET_MODULE; 1298c2ecf20Sopenharmony_ci else if (soc_is_ar913x()) 1308c2ecf20Sopenharmony_ci reg = AR913X_RESET_REG_RESET_MODULE; 1318c2ecf20Sopenharmony_ci else if (soc_is_ar933x()) 1328c2ecf20Sopenharmony_ci reg = AR933X_RESET_REG_RESET_MODULE; 1338c2ecf20Sopenharmony_ci else if (soc_is_ar934x()) 1348c2ecf20Sopenharmony_ci reg = AR934X_RESET_REG_RESET_MODULE; 1358c2ecf20Sopenharmony_ci else if (soc_is_qca953x()) 1368c2ecf20Sopenharmony_ci reg = QCA953X_RESET_REG_RESET_MODULE; 1378c2ecf20Sopenharmony_ci else if (soc_is_qca955x()) 1388c2ecf20Sopenharmony_ci reg = QCA955X_RESET_REG_RESET_MODULE; 1398c2ecf20Sopenharmony_ci else if (soc_is_qca956x() || soc_is_tp9343()) 1408c2ecf20Sopenharmony_ci reg = QCA956X_RESET_REG_RESET_MODULE; 1418c2ecf20Sopenharmony_ci else 1428c2ecf20Sopenharmony_ci BUG(); 1438c2ecf20Sopenharmony_ci 1448c2ecf20Sopenharmony_ci spin_lock_irqsave(&ath79_device_reset_lock, flags); 1458c2ecf20Sopenharmony_ci t = ath79_reset_rr(reg); 1468c2ecf20Sopenharmony_ci ath79_reset_wr(reg, t & ~mask); 1478c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&ath79_device_reset_lock, flags); 1488c2ecf20Sopenharmony_ci} 1498c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(ath79_device_reset_clear); 150