1 /* 2 * Copyright 2010 Benjamin Herrenschmidt, IBM Corp 3 * <benh@kernel.crashing.org> 4 * and David Gibson, IBM Corporation. 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 14 * the GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 */ 20 21 #ifndef _ASM_POWERPC_SCOM_H 22 #define _ASM_POWERPC_SCOM_H 23 24 #ifdef __KERNEL__ 25 #ifndef __ASSEMBLY__ 26 #ifdef CONFIG_PPC_SCOM 27 28 /* 29 * The SCOM bus is a sideband bus used for accessing various internal 30 * registers of the processor or the chipset. The implementation details 31 * differ between processors and platforms, and the access method as 32 * well. 33 * 34 * This API allows to "map" ranges of SCOM register numbers associated 35 * with a given SCOM controller. The later must be represented by a 36 * device node, though some implementations might support NULL if there 37 * is no possible ambiguity 38 * 39 * Then, scom_read/scom_write can be used to accesses registers inside 40 * that range. The argument passed is a register number relative to 41 * the beginning of the range mapped. 42 */ 43 44 typedef void *scom_map_t; 45 46 /* Value for an invalid SCOM map */ 47 #define SCOM_MAP_INVALID (NULL) 48 49 /* The scom_controller data structure is what the platform passes 50 * to the core code in scom_init, it provides the actual implementation 51 * of all the SCOM functions 52 */ 53 struct scom_controller { 54 scom_map_t (*map)(struct device_node *ctrl_dev, u64 reg, u64 count); 55 void (*unmap)(scom_map_t map); 56 57 int (*read)(scom_map_t map, u64 reg, u64 *value); 58 int (*write)(scom_map_t map, u64 reg, u64 value); 59 }; 60 61 extern const struct scom_controller *scom_controller; 62 63 /** 64 * scom_init - Initialize the SCOM backend, called by the platform 65 * @controller: The platform SCOM controller 66 */ scom_init(const struct scom_controller * controller)67 static inline void scom_init(const struct scom_controller *controller) 68 { 69 scom_controller = controller; 70 } 71 72 /** 73 * scom_map_ok - Test is a SCOM mapping is successful 74 * @map: The result of scom_map to test 75 */ scom_map_ok(scom_map_t map)76 static inline int scom_map_ok(scom_map_t map) 77 { 78 return map != SCOM_MAP_INVALID; 79 } 80 81 /** 82 * scom_map - Map a block of SCOM registers 83 * @ctrl_dev: Device node of the SCOM controller 84 * some implementations allow NULL here 85 * @reg: first SCOM register to map 86 * @count: Number of SCOM registers to map 87 */ 88 scom_map(struct device_node * ctrl_dev,u64 reg,u64 count)89 static inline scom_map_t scom_map(struct device_node *ctrl_dev, 90 u64 reg, u64 count) 91 { 92 return scom_controller->map(ctrl_dev, reg, count); 93 } 94 95 /** 96 * scom_find_parent - Find the SCOM controller for a device 97 * @dev: OF node of the device 98 * 99 * This is not meant for general usage, but in combination with 100 * scom_map() allows to map registers not represented by the 101 * device own scom-reg property. Useful for applying HW workarounds 102 * on things not properly represented in the device-tree for example. 103 */ 104 struct device_node *scom_find_parent(struct device_node *dev); 105 106 107 /** 108 * scom_map_device - Map a device's block of SCOM registers 109 * @dev: OF node of the device 110 * @index: Register bank index (index in "scom-reg" property) 111 * 112 * This function will use the device-tree binding for SCOM which 113 * is to follow "scom-parent" properties until it finds a node with 114 * a "scom-controller" property to find the controller. It will then 115 * use the "scom-reg" property which is made of reg/count pairs, 116 * each of them having a size defined by the controller's #scom-cells 117 * property 118 */ 119 extern scom_map_t scom_map_device(struct device_node *dev, int index); 120 121 122 /** 123 * scom_unmap - Unmap a block of SCOM registers 124 * @map: Result of scom_map is to be unmapped 125 */ scom_unmap(scom_map_t map)126 static inline void scom_unmap(scom_map_t map) 127 { 128 if (scom_map_ok(map)) 129 scom_controller->unmap(map); 130 } 131 132 /** 133 * scom_read - Read a SCOM register 134 * @map: Result of scom_map 135 * @reg: Register index within that map 136 * @value: Updated with the value read 137 * 138 * Returns 0 (success) or a negative error code 139 */ scom_read(scom_map_t map,u64 reg,u64 * value)140 static inline int scom_read(scom_map_t map, u64 reg, u64 *value) 141 { 142 int rc; 143 144 rc = scom_controller->read(map, reg, value); 145 if (rc) 146 *value = 0xfffffffffffffffful; 147 return rc; 148 } 149 150 /** 151 * scom_write - Write to a SCOM register 152 * @map: Result of scom_map 153 * @reg: Register index within that map 154 * @value: Value to write 155 * 156 * Returns 0 (success) or a negative error code 157 */ scom_write(scom_map_t map,u64 reg,u64 value)158 static inline int scom_write(scom_map_t map, u64 reg, u64 value) 159 { 160 return scom_controller->write(map, reg, value); 161 } 162 163 164 #endif /* CONFIG_PPC_SCOM */ 165 #endif /* __ASSEMBLY__ */ 166 #endif /* __KERNEL__ */ 167 #endif /* _ASM_POWERPC_SCOM_H */ 168