^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0+
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) // Copyright IBM Corp 2019
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) #include <linux/device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) #include <linux/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include <linux/fsi-occ.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <linux/i2c.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/jiffies.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/sched.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <asm/unaligned.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include "common.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #define OCC_TIMEOUT_MS 1000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #define OCC_CMD_IN_PRG_WAIT_MS 50
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) /* OCB (on-chip control bridge - interface to OCC) registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #define OCB_DATA1 0x6B035
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #define OCB_ADDR 0x6B070
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #define OCB_DATA3 0x6B075
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) /* OCC SRAM address space */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #define OCC_SRAM_ADDR_CMD 0xFFFF6000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #define OCC_SRAM_ADDR_RESP 0xFFFF7000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #define OCC_DATA_ATTN 0x20010000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) struct p8_i2c_occ {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) struct occ occ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) struct i2c_client *client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #define to_p8_i2c_occ(x) container_of((x), struct p8_i2c_occ, occ)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) static int p8_i2c_occ_getscom(struct i2c_client *client, u32 address, u8 *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) ssize_t rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) __be64 buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) struct i2c_msg msgs[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) /* p8 i2c slave requires shift */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) address <<= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) msgs[0].addr = client->addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) msgs[0].flags = client->flags & I2C_M_TEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) msgs[0].len = sizeof(u32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) /* address is a scom address; bus-endian */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) msgs[0].buf = (char *)&address;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) /* data from OCC is big-endian */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) msgs[1].addr = client->addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) msgs[1].flags = (client->flags & I2C_M_TEN) | I2C_M_RD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) msgs[1].len = sizeof(u64);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) msgs[1].buf = (char *)&buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) rc = i2c_transfer(client->adapter, msgs, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) *(u64 *)data = be64_to_cpu(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) static int p8_i2c_occ_putscom(struct i2c_client *client, u32 address, u8 *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) u32 buf[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) ssize_t rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) /* p8 i2c slave requires shift */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) address <<= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) /* address is bus-endian; data passed through from user as-is */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) buf[0] = address;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) memcpy(&buf[1], &data[4], sizeof(u32));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) memcpy(&buf[2], data, sizeof(u32));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) rc = i2c_master_send(client, (const char *)buf, sizeof(buf));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) else if (rc != sizeof(buf))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) static int p8_i2c_occ_putscom_u32(struct i2c_client *client, u32 address,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) u32 data0, u32 data1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) u8 buf[8];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) memcpy(buf, &data0, 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) memcpy(buf + 4, &data1, 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) return p8_i2c_occ_putscom(client, address, buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) static int p8_i2c_occ_putscom_be(struct i2c_client *client, u32 address,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) u8 *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) __be32 data0, data1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) memcpy(&data0, data, 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) memcpy(&data1, data + 4, 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) return p8_i2c_occ_putscom_u32(client, address, be32_to_cpu(data0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) be32_to_cpu(data1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) static int p8_i2c_occ_send_cmd(struct occ *occ, u8 *cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) int i, rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) unsigned long start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) u16 data_length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) const unsigned long timeout = msecs_to_jiffies(OCC_TIMEOUT_MS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) const long wait_time = msecs_to_jiffies(OCC_CMD_IN_PRG_WAIT_MS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) struct p8_i2c_occ *ctx = to_p8_i2c_occ(occ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) struct i2c_client *client = ctx->client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) struct occ_response *resp = &occ->resp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) start = jiffies;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) /* set sram address for command */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) rc = p8_i2c_occ_putscom_u32(client, OCB_ADDR, OCC_SRAM_ADDR_CMD, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) /* write command (expected to already be BE), we need bus-endian... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) rc = p8_i2c_occ_putscom_be(client, OCB_DATA3, cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) /* trigger OCC attention */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) rc = p8_i2c_occ_putscom_u32(client, OCB_DATA1, OCC_DATA_ATTN, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) /* set sram address for response */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) rc = p8_i2c_occ_putscom_u32(client, OCB_ADDR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) OCC_SRAM_ADDR_RESP, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) rc = p8_i2c_occ_getscom(client, OCB_DATA3, (u8 *)resp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) /* wait for OCC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) if (resp->return_status == OCC_RESP_CMD_IN_PRG) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) rc = -EALREADY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) if (time_after(jiffies, start + timeout))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) set_current_state(TASK_INTERRUPTIBLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) schedule_timeout(wait_time);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) } while (rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) /* check the OCC response */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) switch (resp->return_status) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) case OCC_RESP_CMD_IN_PRG:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) rc = -ETIMEDOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) case OCC_RESP_SUCCESS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) case OCC_RESP_CMD_INVAL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) case OCC_RESP_CMD_LEN_INVAL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) case OCC_RESP_DATA_INVAL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) case OCC_RESP_CHKSUM_ERR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) rc = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) case OCC_RESP_INT_ERR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) case OCC_RESP_BAD_STATE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) case OCC_RESP_CRIT_EXCEPT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) case OCC_RESP_CRIT_INIT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) case OCC_RESP_CRIT_WATCHDOG:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) case OCC_RESP_CRIT_OCB:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) case OCC_RESP_CRIT_HW:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) rc = -EREMOTEIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) rc = -EPROTO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) data_length = get_unaligned_be16(&resp->data_length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) if (data_length > OCC_RESP_DATA_BYTES)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) return -EMSGSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) /* fetch the rest of the response data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) for (i = 8; i < data_length + 7; i += 8) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) rc = p8_i2c_occ_getscom(client, OCB_DATA3, ((u8 *)resp) + i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) static int p8_i2c_occ_probe(struct i2c_client *client)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) struct occ *occ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) struct p8_i2c_occ *ctx = devm_kzalloc(&client->dev, sizeof(*ctx),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) if (!ctx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) ctx->client = client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) occ = &ctx->occ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) occ->bus_dev = &client->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) dev_set_drvdata(&client->dev, occ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) occ->powr_sample_time_us = 250;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) occ->poll_cmd_data = 0x10; /* P8 OCC poll data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) occ->send_cmd = p8_i2c_occ_send_cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) return occ_setup(occ, "p8_occ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) static int p8_i2c_occ_remove(struct i2c_client *client)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) struct occ *occ = dev_get_drvdata(&client->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) occ_shutdown(occ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) static const struct of_device_id p8_i2c_occ_of_match[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) { .compatible = "ibm,p8-occ-hwmon" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) {}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) MODULE_DEVICE_TABLE(of, p8_i2c_occ_of_match);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) static struct i2c_driver p8_i2c_occ_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) .class = I2C_CLASS_HWMON,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) .name = "occ-hwmon",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) .of_match_table = p8_i2c_occ_of_match,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) .probe_new = p8_i2c_occ_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) .remove = p8_i2c_occ_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) module_i2c_driver(p8_i2c_occ_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) MODULE_AUTHOR("Eddie James <eajames@linux.ibm.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) MODULE_DESCRIPTION("BMC P8 OCC hwmon driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) MODULE_LICENSE("GPL");