18c2ecf20Sopenharmony_ci/*
28c2ecf20Sopenharmony_ci * Copyright 2003-2011 NetLogic Microsystems, Inc. (NetLogic). All rights
38c2ecf20Sopenharmony_ci * reserved.
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * This software is available to you under a choice of one of two
68c2ecf20Sopenharmony_ci * licenses.  You may choose to be licensed under the terms of the GNU
78c2ecf20Sopenharmony_ci * General Public License (GPL) Version 2, available from the file
88c2ecf20Sopenharmony_ci * COPYING in the main directory of this source tree, or the NetLogic
98c2ecf20Sopenharmony_ci * license below:
108c2ecf20Sopenharmony_ci *
118c2ecf20Sopenharmony_ci * Redistribution and use in source and binary forms, with or without
128c2ecf20Sopenharmony_ci * modification, are permitted provided that the following conditions
138c2ecf20Sopenharmony_ci * are met:
148c2ecf20Sopenharmony_ci *
158c2ecf20Sopenharmony_ci * 1. Redistributions of source code must retain the above copyright
168c2ecf20Sopenharmony_ci *    notice, this list of conditions and the following disclaimer.
178c2ecf20Sopenharmony_ci * 2. Redistributions in binary form must reproduce the above copyright
188c2ecf20Sopenharmony_ci *    notice, this list of conditions and the following disclaimer in
198c2ecf20Sopenharmony_ci *    the documentation and/or other materials provided with the
208c2ecf20Sopenharmony_ci *    distribution.
218c2ecf20Sopenharmony_ci *
228c2ecf20Sopenharmony_ci * THIS SOFTWARE IS PROVIDED BY NETLOGIC ``AS IS'' AND ANY EXPRESS OR
238c2ecf20Sopenharmony_ci * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
248c2ecf20Sopenharmony_ci * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
258c2ecf20Sopenharmony_ci * ARE DISCLAIMED. IN NO EVENT SHALL NETLOGIC OR CONTRIBUTORS BE LIABLE
268c2ecf20Sopenharmony_ci * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
278c2ecf20Sopenharmony_ci * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
288c2ecf20Sopenharmony_ci * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
298c2ecf20Sopenharmony_ci * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
308c2ecf20Sopenharmony_ci * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
318c2ecf20Sopenharmony_ci * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
328c2ecf20Sopenharmony_ci * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
338c2ecf20Sopenharmony_ci */
348c2ecf20Sopenharmony_ci
358c2ecf20Sopenharmony_ci#ifndef __NLM_HAL_HALDEFS_H__
368c2ecf20Sopenharmony_ci#define __NLM_HAL_HALDEFS_H__
378c2ecf20Sopenharmony_ci
388c2ecf20Sopenharmony_ci#include <linux/irqflags.h>	/* for local_irq_disable */
398c2ecf20Sopenharmony_ci
408c2ecf20Sopenharmony_ci/*
418c2ecf20Sopenharmony_ci * This file contains platform specific memory mapped IO implementation
428c2ecf20Sopenharmony_ci * and will provide a way to read 32/64 bit memory mapped registers in
438c2ecf20Sopenharmony_ci * all ABIs
448c2ecf20Sopenharmony_ci */
458c2ecf20Sopenharmony_cistatic inline uint32_t
468c2ecf20Sopenharmony_cinlm_read_reg(uint64_t base, uint32_t reg)
478c2ecf20Sopenharmony_ci{
488c2ecf20Sopenharmony_ci	volatile uint32_t *addr = (volatile uint32_t *)(long)base + reg;
498c2ecf20Sopenharmony_ci
508c2ecf20Sopenharmony_ci	return *addr;
518c2ecf20Sopenharmony_ci}
528c2ecf20Sopenharmony_ci
538c2ecf20Sopenharmony_cistatic inline void
548c2ecf20Sopenharmony_cinlm_write_reg(uint64_t base, uint32_t reg, uint32_t val)
558c2ecf20Sopenharmony_ci{
568c2ecf20Sopenharmony_ci	volatile uint32_t *addr = (volatile uint32_t *)(long)base + reg;
578c2ecf20Sopenharmony_ci
588c2ecf20Sopenharmony_ci	*addr = val;
598c2ecf20Sopenharmony_ci}
608c2ecf20Sopenharmony_ci
618c2ecf20Sopenharmony_ci/*
628c2ecf20Sopenharmony_ci * For o32 compilation, we have to disable interrupts to access 64 bit
638c2ecf20Sopenharmony_ci * registers
648c2ecf20Sopenharmony_ci *
658c2ecf20Sopenharmony_ci * We need to disable interrupts because we save just the lower 32 bits of
668c2ecf20Sopenharmony_ci * registers in  interrupt handling. So if we get hit by an interrupt while
678c2ecf20Sopenharmony_ci * using the upper 32 bits of a register, we lose.
688c2ecf20Sopenharmony_ci */
698c2ecf20Sopenharmony_ci
708c2ecf20Sopenharmony_cistatic inline uint64_t
718c2ecf20Sopenharmony_cinlm_read_reg64(uint64_t base, uint32_t reg)
728c2ecf20Sopenharmony_ci{
738c2ecf20Sopenharmony_ci	uint64_t addr = base + (reg >> 1) * sizeof(uint64_t);
748c2ecf20Sopenharmony_ci	volatile uint64_t *ptr = (volatile uint64_t *)(long)addr;
758c2ecf20Sopenharmony_ci	uint64_t val;
768c2ecf20Sopenharmony_ci
778c2ecf20Sopenharmony_ci	if (sizeof(unsigned long) == 4) {
788c2ecf20Sopenharmony_ci		unsigned long flags;
798c2ecf20Sopenharmony_ci
808c2ecf20Sopenharmony_ci		local_irq_save(flags);
818c2ecf20Sopenharmony_ci		__asm__ __volatile__(
828c2ecf20Sopenharmony_ci			".set	push"			"\n\t"
838c2ecf20Sopenharmony_ci			".set	mips64"			"\n\t"
848c2ecf20Sopenharmony_ci			"ld	%L0, %1"		"\n\t"
858c2ecf20Sopenharmony_ci			"dsra32	%M0, %L0, 0"		"\n\t"
868c2ecf20Sopenharmony_ci			"sll	%L0, %L0, 0"		"\n\t"
878c2ecf20Sopenharmony_ci			".set	pop"			"\n"
888c2ecf20Sopenharmony_ci			: "=r" (val)
898c2ecf20Sopenharmony_ci			: "m" (*ptr));
908c2ecf20Sopenharmony_ci		local_irq_restore(flags);
918c2ecf20Sopenharmony_ci	} else
928c2ecf20Sopenharmony_ci		val = *ptr;
938c2ecf20Sopenharmony_ci
948c2ecf20Sopenharmony_ci	return val;
958c2ecf20Sopenharmony_ci}
968c2ecf20Sopenharmony_ci
978c2ecf20Sopenharmony_cistatic inline void
988c2ecf20Sopenharmony_cinlm_write_reg64(uint64_t base, uint32_t reg, uint64_t val)
998c2ecf20Sopenharmony_ci{
1008c2ecf20Sopenharmony_ci	uint64_t addr = base + (reg >> 1) * sizeof(uint64_t);
1018c2ecf20Sopenharmony_ci	volatile uint64_t *ptr = (volatile uint64_t *)(long)addr;
1028c2ecf20Sopenharmony_ci
1038c2ecf20Sopenharmony_ci	if (sizeof(unsigned long) == 4) {
1048c2ecf20Sopenharmony_ci		unsigned long flags;
1058c2ecf20Sopenharmony_ci		uint64_t tmp;
1068c2ecf20Sopenharmony_ci
1078c2ecf20Sopenharmony_ci		local_irq_save(flags);
1088c2ecf20Sopenharmony_ci		__asm__ __volatile__(
1098c2ecf20Sopenharmony_ci			".set	push"			"\n\t"
1108c2ecf20Sopenharmony_ci			".set	mips64"			"\n\t"
1118c2ecf20Sopenharmony_ci			"dsll32	%L0, %L0, 0"		"\n\t"
1128c2ecf20Sopenharmony_ci			"dsrl32	%L0, %L0, 0"		"\n\t"
1138c2ecf20Sopenharmony_ci			"dsll32	%M0, %M0, 0"		"\n\t"
1148c2ecf20Sopenharmony_ci			"or	%L0, %L0, %M0"		"\n\t"
1158c2ecf20Sopenharmony_ci			"sd	%L0, %2"		"\n\t"
1168c2ecf20Sopenharmony_ci			".set	pop"			"\n"
1178c2ecf20Sopenharmony_ci			: "=r" (tmp)
1188c2ecf20Sopenharmony_ci			: "0" (val), "m" (*ptr));
1198c2ecf20Sopenharmony_ci		local_irq_restore(flags);
1208c2ecf20Sopenharmony_ci	} else
1218c2ecf20Sopenharmony_ci		*ptr = val;
1228c2ecf20Sopenharmony_ci}
1238c2ecf20Sopenharmony_ci
1248c2ecf20Sopenharmony_ci/*
1258c2ecf20Sopenharmony_ci * Routines to store 32/64 bit values to 64 bit addresses,
1268c2ecf20Sopenharmony_ci * used when going thru XKPHYS to access registers
1278c2ecf20Sopenharmony_ci */
1288c2ecf20Sopenharmony_cistatic inline uint32_t
1298c2ecf20Sopenharmony_cinlm_read_reg_xkphys(uint64_t base, uint32_t reg)
1308c2ecf20Sopenharmony_ci{
1318c2ecf20Sopenharmony_ci	return nlm_read_reg(base, reg);
1328c2ecf20Sopenharmony_ci}
1338c2ecf20Sopenharmony_ci
1348c2ecf20Sopenharmony_cistatic inline void
1358c2ecf20Sopenharmony_cinlm_write_reg_xkphys(uint64_t base, uint32_t reg, uint32_t val)
1368c2ecf20Sopenharmony_ci{
1378c2ecf20Sopenharmony_ci	nlm_write_reg(base, reg, val);
1388c2ecf20Sopenharmony_ci}
1398c2ecf20Sopenharmony_ci
1408c2ecf20Sopenharmony_cistatic inline uint64_t
1418c2ecf20Sopenharmony_cinlm_read_reg64_xkphys(uint64_t base, uint32_t reg)
1428c2ecf20Sopenharmony_ci{
1438c2ecf20Sopenharmony_ci	return nlm_read_reg64(base, reg);
1448c2ecf20Sopenharmony_ci}
1458c2ecf20Sopenharmony_ci
1468c2ecf20Sopenharmony_cistatic inline void
1478c2ecf20Sopenharmony_cinlm_write_reg64_xkphys(uint64_t base, uint32_t reg, uint64_t val)
1488c2ecf20Sopenharmony_ci{
1498c2ecf20Sopenharmony_ci	nlm_write_reg64(base, reg, val);
1508c2ecf20Sopenharmony_ci}
1518c2ecf20Sopenharmony_ci
1528c2ecf20Sopenharmony_ci/* Location where IO base is mapped */
1538c2ecf20Sopenharmony_ciextern uint64_t nlm_io_base;
1548c2ecf20Sopenharmony_ci
1558c2ecf20Sopenharmony_ci#if defined(CONFIG_CPU_XLP)
1568c2ecf20Sopenharmony_cistatic inline uint64_t
1578c2ecf20Sopenharmony_cinlm_pcicfg_base(uint32_t devoffset)
1588c2ecf20Sopenharmony_ci{
1598c2ecf20Sopenharmony_ci	return nlm_io_base + devoffset;
1608c2ecf20Sopenharmony_ci}
1618c2ecf20Sopenharmony_ci
1628c2ecf20Sopenharmony_ci#elif defined(CONFIG_CPU_XLR)
1638c2ecf20Sopenharmony_ci
1648c2ecf20Sopenharmony_cistatic inline uint64_t
1658c2ecf20Sopenharmony_cinlm_mmio_base(uint32_t devoffset)
1668c2ecf20Sopenharmony_ci{
1678c2ecf20Sopenharmony_ci	return nlm_io_base + devoffset;
1688c2ecf20Sopenharmony_ci}
1698c2ecf20Sopenharmony_ci#endif
1708c2ecf20Sopenharmony_ci
1718c2ecf20Sopenharmony_ci#endif
172