| /* Copyright (c) 2015 Google Inc | 
 |  * Davide Libenzi <dlibenzi@google.com> | 
 |  * See LICENSE for details. | 
 |  */ | 
 |  | 
 | #pragma once | 
 |  | 
 | #include <sys/types.h> | 
 | #include <ros/errno.h> | 
 | #include <stdio.h> | 
 | #include <string.h> | 
 | #include <core_set.h> | 
 |  | 
 | /* The msr_address and msr_value structures allow to specify either a single | 
 |  * address/value for all cores, or dedicated ones for every core. | 
 |  * This allow a single logical call to msr_cores_read()/msr_cores_write() APIs, | 
 |  * to read/write MSRs at different addresses and using different values. | 
 |  */ | 
 | struct msr_address { | 
 | 	uint32_t addr; | 
 | 	const uint32_t *addresses; | 
 | 	size_t num_addresses; | 
 | }; | 
 |  | 
 | struct msr_value { | 
 | 	uint64_t value; | 
 | 	uint64_t *values; | 
 | 	size_t num_values; | 
 | }; | 
 |  | 
 | int msr_cores_read(const struct core_set *cset, const struct msr_address *msra, | 
 | 		   struct msr_value *msrv); | 
 | int msr_core_read(unsigned int core, uint32_t addr, uint64_t *value); | 
 | int msr_cores_write(const struct core_set *cset, const struct msr_address *msra, | 
 | 		    const struct msr_value *msrv); | 
 | int msr_core_write(unsigned int core, uint32_t addr, uint64_t value); | 
 |  | 
 | static inline void msr_set_address(struct msr_address *msra, uint32_t addr) | 
 | { | 
 | 	ZERO_DATA(*msra); | 
 | 	msra->addr = addr; | 
 | } | 
 |  | 
 | static inline void msr_set_addresses(struct msr_address *msra, | 
 | 				     const uint32_t *addresses, | 
 | 				     size_t num_addresses) | 
 | { | 
 | 	ZERO_DATA(*msra); | 
 | 	msra->addresses = addresses; | 
 | 	msra->num_addresses = num_addresses; | 
 | } | 
 |  | 
 | static inline int msr_get_core_address(unsigned int coreno, | 
 | 				       const struct msr_address *msra, | 
 | 				       uint32_t *paddr) | 
 | { | 
 | 	if (msra->addresses != NULL) { | 
 | 		if (coreno >= (unsigned int) msra->num_addresses) | 
 | 			return -ERANGE; | 
 |  | 
 | 		*paddr = msra->addresses[coreno]; | 
 | 	} else { | 
 | 		*paddr = msra->addr; | 
 | 	} | 
 |  | 
 | 	return 0; | 
 | } | 
 |  | 
 | static inline void msr_set_value(struct msr_value *msrv, uint64_t value) | 
 | { | 
 | 	ZERO_DATA(*msrv); | 
 | 	msrv->value = value; | 
 | } | 
 |  | 
 | static inline void msr_set_values(struct msr_value *msrv, | 
 | 				  const uint64_t *values, size_t num_values) | 
 | { | 
 | 	ZERO_DATA(*msrv); | 
 |  | 
 | 	/* Avoid supporting two APIs, one for setting const values, and one for | 
 | 	 * setting the non const ones. | 
 | 	 */ | 
 | 	msrv->values = (uint64_t *) values; | 
 | 	msrv->num_values = num_values; | 
 | } | 
 |  | 
 | static inline int msr_set_core_value(unsigned int coreno, uint64_t value, | 
 | 				     struct msr_value *msrv) | 
 | { | 
 | 	if (msrv->values != NULL) { | 
 | 		if (coreno >= (unsigned int) msrv->num_values) | 
 | 			return -ERANGE; | 
 |  | 
 | 		msrv->values[coreno] = value; | 
 | 	} else { | 
 | 		msrv->value = value; | 
 | 	} | 
 |  | 
 | 	return 0; | 
 | } | 
 |  | 
 | static inline int msr_get_core_value(unsigned int coreno, | 
 | 				     const struct msr_value *msrv, | 
 | 				     uint64_t *pvalue) | 
 | { | 
 | 	if (msrv->values != NULL) { | 
 | 		if (coreno >= (unsigned int) msrv->num_values) | 
 | 			return -ERANGE; | 
 |  | 
 | 		*pvalue = msrv->values[coreno]; | 
 | 	} else { | 
 | 		*pvalue = msrv->value; | 
 | 	} | 
 |  | 
 | 	return 0; | 
 | } |