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