162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Atheros AR71XX/AR724X/AR913X common routines 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 2010-2011 Jaiganesh Narayanan <jnarayanan@atheros.com> 662306a36Sopenharmony_ci * Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org> 762306a36Sopenharmony_ci * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> 862306a36Sopenharmony_ci * 962306a36Sopenharmony_ci * Parts of this file are based on Atheros' 2.6.15/2.6.31 BSP 1062306a36Sopenharmony_ci */ 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ci#include <linux/kernel.h> 1362306a36Sopenharmony_ci#include <linux/export.h> 1462306a36Sopenharmony_ci#include <linux/types.h> 1562306a36Sopenharmony_ci#include <linux/spinlock.h> 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_ci#include <asm/mach-ath79/ath79.h> 1862306a36Sopenharmony_ci#include <asm/mach-ath79/ar71xx_regs.h> 1962306a36Sopenharmony_ci#include "common.h" 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_cistatic DEFINE_SPINLOCK(ath79_device_reset_lock); 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_ciu32 ath79_cpu_freq; 2462306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(ath79_cpu_freq); 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_ciu32 ath79_ahb_freq; 2762306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(ath79_ahb_freq); 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_ciu32 ath79_ddr_freq; 3062306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(ath79_ddr_freq); 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_cienum ath79_soc_type ath79_soc; 3362306a36Sopenharmony_ciunsigned int ath79_soc_rev; 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_civoid __iomem *ath79_pll_base; 3662306a36Sopenharmony_civoid __iomem *ath79_reset_base; 3762306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(ath79_reset_base); 3862306a36Sopenharmony_cistatic void __iomem *ath79_ddr_base; 3962306a36Sopenharmony_cistatic void __iomem *ath79_ddr_wb_flush_base; 4062306a36Sopenharmony_cistatic void __iomem *ath79_ddr_pci_win_base; 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_civoid ath79_ddr_ctrl_init(void) 4362306a36Sopenharmony_ci{ 4462306a36Sopenharmony_ci ath79_ddr_base = ioremap(AR71XX_DDR_CTRL_BASE, 4562306a36Sopenharmony_ci AR71XX_DDR_CTRL_SIZE); 4662306a36Sopenharmony_ci if (soc_is_ar913x() || soc_is_ar724x() || soc_is_ar933x()) { 4762306a36Sopenharmony_ci ath79_ddr_wb_flush_base = ath79_ddr_base + 0x7c; 4862306a36Sopenharmony_ci ath79_ddr_pci_win_base = 0; 4962306a36Sopenharmony_ci } else { 5062306a36Sopenharmony_ci ath79_ddr_wb_flush_base = ath79_ddr_base + 0x9c; 5162306a36Sopenharmony_ci ath79_ddr_pci_win_base = ath79_ddr_base + 0x7c; 5262306a36Sopenharmony_ci } 5362306a36Sopenharmony_ci} 5462306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(ath79_ddr_ctrl_init); 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_civoid ath79_ddr_wb_flush(u32 reg) 5762306a36Sopenharmony_ci{ 5862306a36Sopenharmony_ci void __iomem *flush_reg = ath79_ddr_wb_flush_base + (reg * 4); 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_ci /* Flush the DDR write buffer. */ 6162306a36Sopenharmony_ci __raw_writel(0x1, flush_reg); 6262306a36Sopenharmony_ci while (__raw_readl(flush_reg) & 0x1) 6362306a36Sopenharmony_ci ; 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_ci /* It must be run twice. */ 6662306a36Sopenharmony_ci __raw_writel(0x1, flush_reg); 6762306a36Sopenharmony_ci while (__raw_readl(flush_reg) & 0x1) 6862306a36Sopenharmony_ci ; 6962306a36Sopenharmony_ci} 7062306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(ath79_ddr_wb_flush); 7162306a36Sopenharmony_ci 7262306a36Sopenharmony_civoid ath79_ddr_set_pci_windows(void) 7362306a36Sopenharmony_ci{ 7462306a36Sopenharmony_ci BUG_ON(!ath79_ddr_pci_win_base); 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_ci __raw_writel(AR71XX_PCI_WIN0_OFFS, ath79_ddr_pci_win_base + 0x0); 7762306a36Sopenharmony_ci __raw_writel(AR71XX_PCI_WIN1_OFFS, ath79_ddr_pci_win_base + 0x4); 7862306a36Sopenharmony_ci __raw_writel(AR71XX_PCI_WIN2_OFFS, ath79_ddr_pci_win_base + 0x8); 7962306a36Sopenharmony_ci __raw_writel(AR71XX_PCI_WIN3_OFFS, ath79_ddr_pci_win_base + 0xc); 8062306a36Sopenharmony_ci __raw_writel(AR71XX_PCI_WIN4_OFFS, ath79_ddr_pci_win_base + 0x10); 8162306a36Sopenharmony_ci __raw_writel(AR71XX_PCI_WIN5_OFFS, ath79_ddr_pci_win_base + 0x14); 8262306a36Sopenharmony_ci __raw_writel(AR71XX_PCI_WIN6_OFFS, ath79_ddr_pci_win_base + 0x18); 8362306a36Sopenharmony_ci __raw_writel(AR71XX_PCI_WIN7_OFFS, ath79_ddr_pci_win_base + 0x1c); 8462306a36Sopenharmony_ci} 8562306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(ath79_ddr_set_pci_windows); 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_civoid ath79_device_reset_set(u32 mask) 8862306a36Sopenharmony_ci{ 8962306a36Sopenharmony_ci unsigned long flags; 9062306a36Sopenharmony_ci u32 reg; 9162306a36Sopenharmony_ci u32 t; 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_ci if (soc_is_ar71xx()) 9462306a36Sopenharmony_ci reg = AR71XX_RESET_REG_RESET_MODULE; 9562306a36Sopenharmony_ci else if (soc_is_ar724x()) 9662306a36Sopenharmony_ci reg = AR724X_RESET_REG_RESET_MODULE; 9762306a36Sopenharmony_ci else if (soc_is_ar913x()) 9862306a36Sopenharmony_ci reg = AR913X_RESET_REG_RESET_MODULE; 9962306a36Sopenharmony_ci else if (soc_is_ar933x()) 10062306a36Sopenharmony_ci reg = AR933X_RESET_REG_RESET_MODULE; 10162306a36Sopenharmony_ci else if (soc_is_ar934x()) 10262306a36Sopenharmony_ci reg = AR934X_RESET_REG_RESET_MODULE; 10362306a36Sopenharmony_ci else if (soc_is_qca953x()) 10462306a36Sopenharmony_ci reg = QCA953X_RESET_REG_RESET_MODULE; 10562306a36Sopenharmony_ci else if (soc_is_qca955x()) 10662306a36Sopenharmony_ci reg = QCA955X_RESET_REG_RESET_MODULE; 10762306a36Sopenharmony_ci else if (soc_is_qca956x() || soc_is_tp9343()) 10862306a36Sopenharmony_ci reg = QCA956X_RESET_REG_RESET_MODULE; 10962306a36Sopenharmony_ci else 11062306a36Sopenharmony_ci BUG(); 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_ci spin_lock_irqsave(&ath79_device_reset_lock, flags); 11362306a36Sopenharmony_ci t = ath79_reset_rr(reg); 11462306a36Sopenharmony_ci ath79_reset_wr(reg, t | mask); 11562306a36Sopenharmony_ci spin_unlock_irqrestore(&ath79_device_reset_lock, flags); 11662306a36Sopenharmony_ci} 11762306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(ath79_device_reset_set); 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_civoid ath79_device_reset_clear(u32 mask) 12062306a36Sopenharmony_ci{ 12162306a36Sopenharmony_ci unsigned long flags; 12262306a36Sopenharmony_ci u32 reg; 12362306a36Sopenharmony_ci u32 t; 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_ci if (soc_is_ar71xx()) 12662306a36Sopenharmony_ci reg = AR71XX_RESET_REG_RESET_MODULE; 12762306a36Sopenharmony_ci else if (soc_is_ar724x()) 12862306a36Sopenharmony_ci reg = AR724X_RESET_REG_RESET_MODULE; 12962306a36Sopenharmony_ci else if (soc_is_ar913x()) 13062306a36Sopenharmony_ci reg = AR913X_RESET_REG_RESET_MODULE; 13162306a36Sopenharmony_ci else if (soc_is_ar933x()) 13262306a36Sopenharmony_ci reg = AR933X_RESET_REG_RESET_MODULE; 13362306a36Sopenharmony_ci else if (soc_is_ar934x()) 13462306a36Sopenharmony_ci reg = AR934X_RESET_REG_RESET_MODULE; 13562306a36Sopenharmony_ci else if (soc_is_qca953x()) 13662306a36Sopenharmony_ci reg = QCA953X_RESET_REG_RESET_MODULE; 13762306a36Sopenharmony_ci else if (soc_is_qca955x()) 13862306a36Sopenharmony_ci reg = QCA955X_RESET_REG_RESET_MODULE; 13962306a36Sopenharmony_ci else if (soc_is_qca956x() || soc_is_tp9343()) 14062306a36Sopenharmony_ci reg = QCA956X_RESET_REG_RESET_MODULE; 14162306a36Sopenharmony_ci else 14262306a36Sopenharmony_ci BUG(); 14362306a36Sopenharmony_ci 14462306a36Sopenharmony_ci spin_lock_irqsave(&ath79_device_reset_lock, flags); 14562306a36Sopenharmony_ci t = ath79_reset_rr(reg); 14662306a36Sopenharmony_ci ath79_reset_wr(reg, t & ~mask); 14762306a36Sopenharmony_ci spin_unlock_irqrestore(&ath79_device_reset_lock, flags); 14862306a36Sopenharmony_ci} 14962306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(ath79_device_reset_clear); 150