1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
|
/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright (c) 2018-2019 Intel Corporation */
#ifndef __LINUX_PECI_H
#define __LINUX_PECI_H
#include <linux/device.h>
#include <linux/mutex.h>
#include <linux/peci-ioctl.h>
#define PECI_NAME_SIZE 32
struct peci_board_info {
char type[PECI_NAME_SIZE];
u8 addr; /* CPU client address */
struct device_node *of_node;
};
/**
* struct peci_adapter - represent a PECI adapter
* @owner: owner module of the PECI adpater
* @bus_lock: mutex for exclusion of multiple callers
* @dev: device interface to this driver
* @nr: the bus number to map
* @name: name of the adapter
* @userspace_clients_lock: mutex for exclusion of clients handling
* @userspace_clients: list of registered clients
* @xfer: low-level transfer function pointer of the adapter
* @cmd_mask: mask for supportable PECI commands
* @use_dma: flag for indicating that adapter uses DMA
*
* Each PECI adapter can communicate with one or more PECI client children.
* These make a small bus, sharing a single wired PECI connection.
*/
struct peci_adapter {
struct module *owner;
struct mutex bus_lock; /* mutex for bus locking */
struct device dev;
int nr;
char name[PECI_NAME_SIZE];
struct mutex userspace_clients_lock; /* clients list mutex */
struct list_head userspace_clients;
int (*xfer)(struct peci_adapter *adapter,
struct peci_xfer_msg *msg);
u32 cmd_mask;
bool use_dma;
u8 peci_revision;
};
static inline struct peci_adapter *to_peci_adapter(void *d)
{
return container_of(d, struct peci_adapter, dev);
}
static inline void *peci_get_adapdata(const struct peci_adapter *adapter)
{
return dev_get_drvdata(&adapter->dev);
}
static inline void peci_set_adapdata(struct peci_adapter *adapter, void *data)
{
dev_set_drvdata(&adapter->dev, data);
}
/**
* struct peci_client - represent a PECI client device
* @dev: driver model device node for the client
* @adapter: manages the bus segment hosting this PECI device
* @addr: address used on the PECI bus connected to the parent adapter
* @name: indicates the type of the device
* @detected: detected PECI clients list
*
* A peci_client identifies a single device (i.e. CPU) connected to a peci bus.
* The behaviour exposed to Linux is defined by the driver managing the device.
*/
struct peci_client {
struct device dev;
struct peci_adapter *adapter;
u8 addr;
char name[PECI_NAME_SIZE];
struct list_head detected;
};
static inline struct peci_client *to_peci_client(void *d)
{
return container_of(d, struct peci_client, dev);
}
struct peci_device_id {
char name[PECI_NAME_SIZE];
ulong driver_data; /* Data private to the driver */
};
/**
* struct peci_driver - represent a PECI device driver
* @probe: callback for device binding
* @remove: callback for device unbinding
* @shutdown: callback for device shutdown
* @driver: device driver model driver
* @id_table: list of PECI devices supported by this driver
*
* The driver.owner field should be set to the module owner of this driver.
* The driver.name field should be set to the name of this driver.
*/
struct peci_driver {
int (*probe)(struct peci_client *client);
int (*remove)(struct peci_client *client);
void (*shutdown)(struct peci_client *client);
struct device_driver driver;
const struct peci_device_id *id_table;
};
static inline struct peci_driver *to_peci_driver(void *d)
{
return container_of(d, struct peci_driver, driver);
}
/**
* module_peci_driver - Helper macro for registering a modular PECI driver
* @__peci_driver: peci_driver struct
*
* Helper macro for PECI drivers which do not do anything special in module
* init/exit. This eliminates a lot of boilerplate. Each module may only
* use this macro once, and calling it replaces module_init() and module_exit()
*/
#define module_peci_driver(__peci_driver) \
module_driver(__peci_driver, peci_add_driver, peci_del_driver)
/* use a define to avoid include chaining to get THIS_MODULE */
#define peci_add_driver(driver) peci_register_driver(THIS_MODULE, driver)
extern struct bus_type peci_bus_type;
extern struct device_type peci_adapter_type;
extern struct device_type peci_client_type;
int peci_register_driver(struct module *owner, struct peci_driver *drv);
void peci_del_driver(struct peci_driver *driver);
struct peci_client *peci_verify_client(struct device *dev);
struct peci_adapter *peci_alloc_adapter(struct device *dev, uint size);
struct peci_adapter *peci_get_adapter(int nr);
void peci_put_adapter(struct peci_adapter *adapter);
int peci_add_adapter(struct peci_adapter *adapter);
void peci_del_adapter(struct peci_adapter *adapter);
struct peci_adapter *peci_verify_adapter(struct device *dev);
int peci_for_each_dev(void *data, int (*fn)(struct device *, void *));
struct peci_xfer_msg *peci_get_xfer_msg(u8 tx_len, u8 rx_len);
void peci_put_xfer_msg(struct peci_xfer_msg *msg);
int peci_command(struct peci_adapter *adpater, enum peci_cmd cmd, uint msg_len, void *vmsg);
int peci_get_cpu_id(struct peci_adapter *adapter, u8 addr, u32 *cpu_id);
#endif /* __LINUX_PECI_H */
|