1 // SPDX-License-Identifier: GPL-2.0+
2 // Copyright IBM Corp 2019
4 #include <linux/device.h>
5 #include <linux/errno.h>
6 #include <linux/fsi-occ.h>
8 #include <linux/jiffies.h>
9 #include <linux/module.h>
10 #include <linux/sched.h>
11 #include <linux/unaligned.h>
15 #define OCC_TIMEOUT_MS 1000
16 #define OCC_CMD_IN_PRG_WAIT_MS 50
18 /* OCB (on-chip control bridge - interface to OCC) registers */
19 #define OCB_DATA1 0x6B035
20 #define OCB_ADDR 0x6B070
21 #define OCB_DATA3 0x6B075
23 /* OCC SRAM address space */
24 #define OCC_SRAM_ADDR_CMD 0xFFFF6000
25 #define OCC_SRAM_ADDR_RESP 0xFFFF7000
27 #define OCC_DATA_ATTN 0x20010000
31 struct i2c_client
*client
;
34 #define to_p8_i2c_occ(x) container_of((x), struct p8_i2c_occ, occ)
36 static int p8_i2c_occ_getscom(struct i2c_client
*client
, u32 address
, u8
*data
)
40 struct i2c_msg msgs
[2];
42 /* p8 i2c slave requires shift */
45 msgs
[0].addr
= client
->addr
;
46 msgs
[0].flags
= client
->flags
& I2C_M_TEN
;
47 msgs
[0].len
= sizeof(u32
);
48 /* address is a scom address; bus-endian */
49 msgs
[0].buf
= (char *)&address
;
51 /* data from OCC is big-endian */
52 msgs
[1].addr
= client
->addr
;
53 msgs
[1].flags
= (client
->flags
& I2C_M_TEN
) | I2C_M_RD
;
54 msgs
[1].len
= sizeof(u64
);
55 msgs
[1].buf
= (char *)&buf
;
57 rc
= i2c_transfer(client
->adapter
, msgs
, 2);
61 *(u64
*)data
= be64_to_cpu(buf
);
66 static int p8_i2c_occ_putscom(struct i2c_client
*client
, u32 address
, u8
*data
)
71 /* p8 i2c slave requires shift */
74 /* address is bus-endian; data passed through from user as-is */
76 memcpy(&buf
[1], &data
[4], sizeof(u32
));
77 memcpy(&buf
[2], data
, sizeof(u32
));
79 rc
= i2c_master_send(client
, (const char *)buf
, sizeof(buf
));
82 else if (rc
!= sizeof(buf
))
88 static int p8_i2c_occ_putscom_u32(struct i2c_client
*client
, u32 address
,
93 memcpy(buf
, &data0
, 4);
94 memcpy(buf
+ 4, &data1
, 4);
96 return p8_i2c_occ_putscom(client
, address
, buf
);
99 static int p8_i2c_occ_putscom_be(struct i2c_client
*client
, u32 address
,
100 u8
*data
, size_t len
)
102 __be32 data0
= 0, data1
= 0;
104 memcpy(&data0
, data
, min_t(size_t, len
, 4));
107 memcpy(&data1
, data
+ 4, min_t(size_t, len
, 4));
110 return p8_i2c_occ_putscom_u32(client
, address
, be32_to_cpu(data0
),
114 static int p8_i2c_occ_send_cmd(struct occ
*occ
, u8
*cmd
, size_t len
,
115 void *resp
, size_t resp_len
)
120 const unsigned long timeout
= msecs_to_jiffies(OCC_TIMEOUT_MS
);
121 const long wait_time
= msecs_to_jiffies(OCC_CMD_IN_PRG_WAIT_MS
);
122 struct p8_i2c_occ
*ctx
= to_p8_i2c_occ(occ
);
123 struct i2c_client
*client
= ctx
->client
;
124 struct occ_response
*or = (struct occ_response
*)resp
;
128 /* set sram address for command */
129 rc
= p8_i2c_occ_putscom_u32(client
, OCB_ADDR
, OCC_SRAM_ADDR_CMD
, 0);
133 /* write command (expected to already be BE), we need bus-endian... */
134 rc
= p8_i2c_occ_putscom_be(client
, OCB_DATA3
, cmd
, len
);
138 /* trigger OCC attention */
139 rc
= p8_i2c_occ_putscom_u32(client
, OCB_DATA1
, OCC_DATA_ATTN
, 0);
144 /* set sram address for response */
145 rc
= p8_i2c_occ_putscom_u32(client
, OCB_ADDR
,
146 OCC_SRAM_ADDR_RESP
, 0);
150 rc
= p8_i2c_occ_getscom(client
, OCB_DATA3
, (u8
*)resp
);
155 if (or->return_status
== OCC_RESP_CMD_IN_PRG
) {
158 if (time_after(jiffies
, start
+ timeout
))
161 set_current_state(TASK_INTERRUPTIBLE
);
162 schedule_timeout(wait_time
);
166 /* check the OCC response */
167 switch (or->return_status
) {
168 case OCC_RESP_CMD_IN_PRG
:
171 case OCC_RESP_SUCCESS
:
174 case OCC_RESP_CMD_INVAL
:
175 case OCC_RESP_CMD_LEN_INVAL
:
176 case OCC_RESP_DATA_INVAL
:
177 case OCC_RESP_CHKSUM_ERR
:
180 case OCC_RESP_INT_ERR
:
181 case OCC_RESP_BAD_STATE
:
182 case OCC_RESP_CRIT_EXCEPT
:
183 case OCC_RESP_CRIT_INIT
:
184 case OCC_RESP_CRIT_WATCHDOG
:
185 case OCC_RESP_CRIT_OCB
:
186 case OCC_RESP_CRIT_HW
:
196 data_length
= get_unaligned_be16(&or->data_length
);
197 if ((data_length
+ 7) > resp_len
)
200 /* fetch the rest of the response data */
201 for (i
= 8; i
< data_length
+ 7; i
+= 8) {
202 rc
= p8_i2c_occ_getscom(client
, OCB_DATA3
, ((u8
*)resp
) + i
);
210 static int p8_i2c_occ_probe(struct i2c_client
*client
)
213 struct p8_i2c_occ
*ctx
= devm_kzalloc(&client
->dev
, sizeof(*ctx
),
218 ctx
->client
= client
;
220 occ
->bus_dev
= &client
->dev
;
221 dev_set_drvdata(&client
->dev
, occ
);
223 occ
->powr_sample_time_us
= 250;
224 occ
->poll_cmd_data
= 0x10; /* P8 OCC poll data */
225 occ
->send_cmd
= p8_i2c_occ_send_cmd
;
227 return occ_setup(occ
);
230 static void p8_i2c_occ_remove(struct i2c_client
*client
)
232 struct occ
*occ
= dev_get_drvdata(&client
->dev
);
237 static const struct of_device_id p8_i2c_occ_of_match
[] = {
238 { .compatible
= "ibm,p8-occ-hwmon" },
241 MODULE_DEVICE_TABLE(of
, p8_i2c_occ_of_match
);
243 static struct i2c_driver p8_i2c_occ_driver
= {
246 .of_match_table
= p8_i2c_occ_of_match
,
248 .probe
= p8_i2c_occ_probe
,
249 .remove
= p8_i2c_occ_remove
,
252 module_i2c_driver(p8_i2c_occ_driver
);
254 MODULE_AUTHOR("Eddie James <eajames@linux.ibm.com>");
255 MODULE_DESCRIPTION("BMC P8 OCC hwmon driver");
256 MODULE_LICENSE("GPL");