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