162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright (C) 2000-2003 Deep Blue Solutions Ltd 462306a36Sopenharmony_ci */ 562306a36Sopenharmony_ci#include <linux/types.h> 662306a36Sopenharmony_ci#include <linux/kernel.h> 762306a36Sopenharmony_ci#include <linux/init.h> 862306a36Sopenharmony_ci#include <linux/device.h> 962306a36Sopenharmony_ci#include <linux/export.h> 1062306a36Sopenharmony_ci#include <linux/spinlock.h> 1162306a36Sopenharmony_ci#include <linux/interrupt.h> 1262306a36Sopenharmony_ci#include <linux/irq.h> 1362306a36Sopenharmony_ci#include <linux/memblock.h> 1462306a36Sopenharmony_ci#include <linux/sched.h> 1562306a36Sopenharmony_ci#include <linux/smp.h> 1662306a36Sopenharmony_ci#include <linux/amba/bus.h> 1762306a36Sopenharmony_ci#include <linux/amba/serial.h> 1862306a36Sopenharmony_ci#include <linux/io.h> 1962306a36Sopenharmony_ci#include <linux/stat.h> 2062306a36Sopenharmony_ci#include <linux/of.h> 2162306a36Sopenharmony_ci#include <linux/of_address.h> 2262306a36Sopenharmony_ci#include <linux/pgtable.h> 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_ci#include <asm/mach-types.h> 2562306a36Sopenharmony_ci#include <asm/mach/time.h> 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_ci#include "integrator-hardware.h" 2862306a36Sopenharmony_ci#include "integrator-cm.h" 2962306a36Sopenharmony_ci#include "integrator.h" 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_cistatic DEFINE_RAW_SPINLOCK(cm_lock); 3262306a36Sopenharmony_cistatic void __iomem *cm_base; 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_ci/** 3562306a36Sopenharmony_ci * cm_get - get the value from the CM_CTRL register 3662306a36Sopenharmony_ci */ 3762306a36Sopenharmony_ciu32 cm_get(void) 3862306a36Sopenharmony_ci{ 3962306a36Sopenharmony_ci return readl(cm_base + INTEGRATOR_HDR_CTRL_OFFSET); 4062306a36Sopenharmony_ci} 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_ci/** 4362306a36Sopenharmony_ci * cm_control - update the CM_CTRL register. 4462306a36Sopenharmony_ci * @mask: bits to change 4562306a36Sopenharmony_ci * @set: bits to set 4662306a36Sopenharmony_ci */ 4762306a36Sopenharmony_civoid cm_control(u32 mask, u32 set) 4862306a36Sopenharmony_ci{ 4962306a36Sopenharmony_ci unsigned long flags; 5062306a36Sopenharmony_ci u32 val; 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_ci raw_spin_lock_irqsave(&cm_lock, flags); 5362306a36Sopenharmony_ci val = readl(cm_base + INTEGRATOR_HDR_CTRL_OFFSET) & ~mask; 5462306a36Sopenharmony_ci writel(val | set, cm_base + INTEGRATOR_HDR_CTRL_OFFSET); 5562306a36Sopenharmony_ci raw_spin_unlock_irqrestore(&cm_lock, flags); 5662306a36Sopenharmony_ci} 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_civoid cm_clear_irqs(void) 5962306a36Sopenharmony_ci{ 6062306a36Sopenharmony_ci /* disable core module IRQs */ 6162306a36Sopenharmony_ci writel(0xffffffffU, cm_base + INTEGRATOR_HDR_IC_OFFSET + 6262306a36Sopenharmony_ci IRQ_ENABLE_CLEAR); 6362306a36Sopenharmony_ci} 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_cistatic const struct of_device_id cm_match[] = { 6662306a36Sopenharmony_ci { .compatible = "arm,core-module-integrator"}, 6762306a36Sopenharmony_ci { }, 6862306a36Sopenharmony_ci}; 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_civoid cm_init(void) 7162306a36Sopenharmony_ci{ 7262306a36Sopenharmony_ci struct device_node *cm = of_find_matching_node(NULL, cm_match); 7362306a36Sopenharmony_ci 7462306a36Sopenharmony_ci if (!cm) { 7562306a36Sopenharmony_ci pr_crit("no core module node found in device tree\n"); 7662306a36Sopenharmony_ci return; 7762306a36Sopenharmony_ci } 7862306a36Sopenharmony_ci cm_base = of_iomap(cm, 0); 7962306a36Sopenharmony_ci if (!cm_base) { 8062306a36Sopenharmony_ci pr_crit("could not remap core module\n"); 8162306a36Sopenharmony_ci return; 8262306a36Sopenharmony_ci } 8362306a36Sopenharmony_ci cm_clear_irqs(); 8462306a36Sopenharmony_ci} 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_ci/* 8762306a36Sopenharmony_ci * We need to stop things allocating the low memory; ideally we need a 8862306a36Sopenharmony_ci * better implementation of GFP_DMA which does not assume that DMA-able 8962306a36Sopenharmony_ci * memory starts at zero. 9062306a36Sopenharmony_ci */ 9162306a36Sopenharmony_civoid __init integrator_reserve(void) 9262306a36Sopenharmony_ci{ 9362306a36Sopenharmony_ci memblock_reserve(PHYS_OFFSET, __pa(swapper_pg_dir) - PHYS_OFFSET); 9462306a36Sopenharmony_ci} 95