^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * SMBus 2.0 driver for AMD-8111 IO-Hub.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (c) 2002 Vojtech Pavlik
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/pci.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/stddef.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/ioport.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/i2c.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/acpi.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) MODULE_AUTHOR ("Vojtech Pavlik <vojtech@suse.cz>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) MODULE_DESCRIPTION("AMD8111 SMBus 2.0 driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) struct amd_smbus {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) struct pci_dev *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) struct i2c_adapter adapter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) int base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) int size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) static struct pci_driver amd8111_driver;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) * AMD PCI control registers definitions.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #define AMD_PCI_MISC 0x48
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #define AMD_PCI_MISC_SCI 0x04 /* deliver SCI */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #define AMD_PCI_MISC_INT 0x02 /* deliver PCI IRQ */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #define AMD_PCI_MISC_SPEEDUP 0x01 /* 16x clock speedup */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) * ACPI 2.0 chapter 13 PCI interface definitions.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #define AMD_EC_DATA 0x00 /* data register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #define AMD_EC_SC 0x04 /* status of controller */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #define AMD_EC_CMD 0x04 /* command register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) #define AMD_EC_ICR 0x08 /* interrupt control register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) #define AMD_EC_SC_SMI 0x04 /* smi event pending */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) #define AMD_EC_SC_SCI 0x02 /* sci event pending */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) #define AMD_EC_SC_BURST 0x01 /* burst mode enabled */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) #define AMD_EC_SC_CMD 0x08 /* byte in data reg is command */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) #define AMD_EC_SC_IBF 0x02 /* data ready for embedded controller */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) #define AMD_EC_SC_OBF 0x01 /* data ready for host */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) #define AMD_EC_CMD_RD 0x80 /* read EC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) #define AMD_EC_CMD_WR 0x81 /* write EC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) #define AMD_EC_CMD_BE 0x82 /* enable burst mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) #define AMD_EC_CMD_BD 0x83 /* disable burst mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) #define AMD_EC_CMD_QR 0x84 /* query EC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) * ACPI 2.0 chapter 13 access of registers of the EC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) static int amd_ec_wait_write(struct amd_smbus *smbus)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) int timeout = 500;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) while ((inb(smbus->base + AMD_EC_SC) & AMD_EC_SC_IBF) && --timeout)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) udelay(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) if (!timeout) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) dev_warn(&smbus->dev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) "Timeout while waiting for IBF to clear\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) return -ETIMEDOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) static int amd_ec_wait_read(struct amd_smbus *smbus)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) int timeout = 500;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) while ((~inb(smbus->base + AMD_EC_SC) & AMD_EC_SC_OBF) && --timeout)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) udelay(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) if (!timeout) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) dev_warn(&smbus->dev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) "Timeout while waiting for OBF to set\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) return -ETIMEDOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) static int amd_ec_read(struct amd_smbus *smbus, unsigned char address,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) unsigned char *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) int status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) status = amd_ec_wait_write(smbus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) if (status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) outb(AMD_EC_CMD_RD, smbus->base + AMD_EC_CMD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) status = amd_ec_wait_write(smbus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) if (status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) outb(address, smbus->base + AMD_EC_DATA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) status = amd_ec_wait_read(smbus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) if (status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) *data = inb(smbus->base + AMD_EC_DATA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) static int amd_ec_write(struct amd_smbus *smbus, unsigned char address,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) unsigned char data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) int status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) status = amd_ec_wait_write(smbus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) if (status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) outb(AMD_EC_CMD_WR, smbus->base + AMD_EC_CMD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) status = amd_ec_wait_write(smbus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) if (status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) outb(address, smbus->base + AMD_EC_DATA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) status = amd_ec_wait_write(smbus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) if (status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) outb(data, smbus->base + AMD_EC_DATA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) * ACPI 2.0 chapter 13 SMBus 2.0 EC register model
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) #define AMD_SMB_PRTCL 0x00 /* protocol, PEC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) #define AMD_SMB_STS 0x01 /* status */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) #define AMD_SMB_ADDR 0x02 /* address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) #define AMD_SMB_CMD 0x03 /* command */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) #define AMD_SMB_DATA 0x04 /* 32 data registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) #define AMD_SMB_BCNT 0x24 /* number of data bytes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) #define AMD_SMB_ALRM_A 0x25 /* alarm address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) #define AMD_SMB_ALRM_D 0x26 /* 2 bytes alarm data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) #define AMD_SMB_STS_DONE 0x80
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) #define AMD_SMB_STS_ALRM 0x40
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) #define AMD_SMB_STS_RES 0x20
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) #define AMD_SMB_STS_STATUS 0x1f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) #define AMD_SMB_STATUS_OK 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) #define AMD_SMB_STATUS_FAIL 0x07
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) #define AMD_SMB_STATUS_DNAK 0x10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) #define AMD_SMB_STATUS_DERR 0x11
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) #define AMD_SMB_STATUS_CMD_DENY 0x12
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) #define AMD_SMB_STATUS_UNKNOWN 0x13
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) #define AMD_SMB_STATUS_ACC_DENY 0x17
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) #define AMD_SMB_STATUS_TIMEOUT 0x18
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) #define AMD_SMB_STATUS_NOTSUP 0x19
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) #define AMD_SMB_STATUS_BUSY 0x1A
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) #define AMD_SMB_STATUS_PEC 0x1F
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) #define AMD_SMB_PRTCL_WRITE 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) #define AMD_SMB_PRTCL_READ 0x01
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) #define AMD_SMB_PRTCL_QUICK 0x02
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) #define AMD_SMB_PRTCL_BYTE 0x04
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) #define AMD_SMB_PRTCL_BYTE_DATA 0x06
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) #define AMD_SMB_PRTCL_WORD_DATA 0x08
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) #define AMD_SMB_PRTCL_BLOCK_DATA 0x0a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) #define AMD_SMB_PRTCL_PROC_CALL 0x0c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) #define AMD_SMB_PRTCL_BLOCK_PROC_CALL 0x0d
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) #define AMD_SMB_PRTCL_I2C_BLOCK_DATA 0x4a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) #define AMD_SMB_PRTCL_PEC 0x80
^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) static s32 amd8111_access(struct i2c_adapter * adap, u16 addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) unsigned short flags, char read_write, u8 command, int size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) union i2c_smbus_data * data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) struct amd_smbus *smbus = adap->algo_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) unsigned char protocol, len, pec, temp[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) int i, status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) protocol = (read_write == I2C_SMBUS_READ) ? AMD_SMB_PRTCL_READ
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) : AMD_SMB_PRTCL_WRITE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) pec = (flags & I2C_CLIENT_PEC) ? AMD_SMB_PRTCL_PEC : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) switch (size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) case I2C_SMBUS_QUICK:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) protocol |= AMD_SMB_PRTCL_QUICK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) read_write = I2C_SMBUS_WRITE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) case I2C_SMBUS_BYTE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) if (read_write == I2C_SMBUS_WRITE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) status = amd_ec_write(smbus, AMD_SMB_CMD,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) command);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) if (status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) protocol |= AMD_SMB_PRTCL_BYTE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) case I2C_SMBUS_BYTE_DATA:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) status = amd_ec_write(smbus, AMD_SMB_CMD, command);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) if (status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) if (read_write == I2C_SMBUS_WRITE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) status = amd_ec_write(smbus, AMD_SMB_DATA,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) data->byte);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) if (status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) protocol |= AMD_SMB_PRTCL_BYTE_DATA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) case I2C_SMBUS_WORD_DATA:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) status = amd_ec_write(smbus, AMD_SMB_CMD, command);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) if (status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) if (read_write == I2C_SMBUS_WRITE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) status = amd_ec_write(smbus, AMD_SMB_DATA,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) data->word & 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) if (status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) status = amd_ec_write(smbus, AMD_SMB_DATA + 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) data->word >> 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) if (status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) protocol |= AMD_SMB_PRTCL_WORD_DATA | pec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) case I2C_SMBUS_BLOCK_DATA:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) status = amd_ec_write(smbus, AMD_SMB_CMD, command);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) if (status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) if (read_write == I2C_SMBUS_WRITE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) len = min_t(u8, data->block[0],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) I2C_SMBUS_BLOCK_MAX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) status = amd_ec_write(smbus, AMD_SMB_BCNT, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) if (status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) for (i = 0; i < len; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) status =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) amd_ec_write(smbus, AMD_SMB_DATA + i,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) data->block[i + 1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) if (status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) protocol |= AMD_SMB_PRTCL_BLOCK_DATA | pec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) case I2C_SMBUS_I2C_BLOCK_DATA:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) len = min_t(u8, data->block[0],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) I2C_SMBUS_BLOCK_MAX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) status = amd_ec_write(smbus, AMD_SMB_CMD, command);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) if (status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) status = amd_ec_write(smbus, AMD_SMB_BCNT, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) if (status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) if (read_write == I2C_SMBUS_WRITE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) for (i = 0; i < len; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) status =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) amd_ec_write(smbus, AMD_SMB_DATA + i,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) data->block[i + 1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) if (status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) protocol |= AMD_SMB_PRTCL_I2C_BLOCK_DATA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) case I2C_SMBUS_PROC_CALL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) status = amd_ec_write(smbus, AMD_SMB_CMD, command);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) if (status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) status = amd_ec_write(smbus, AMD_SMB_DATA,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) data->word & 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) if (status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) status = amd_ec_write(smbus, AMD_SMB_DATA + 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) data->word >> 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) if (status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) protocol = AMD_SMB_PRTCL_PROC_CALL | pec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) read_write = I2C_SMBUS_READ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) case I2C_SMBUS_BLOCK_PROC_CALL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) len = min_t(u8, data->block[0],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) I2C_SMBUS_BLOCK_MAX - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) status = amd_ec_write(smbus, AMD_SMB_CMD, command);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) if (status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) status = amd_ec_write(smbus, AMD_SMB_BCNT, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) if (status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) for (i = 0; i < len; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) status = amd_ec_write(smbus, AMD_SMB_DATA + i,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) data->block[i + 1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) if (status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) protocol = AMD_SMB_PRTCL_BLOCK_PROC_CALL | pec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) read_write = I2C_SMBUS_READ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) dev_warn(&adap->dev, "Unsupported transaction %d\n", size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) status = amd_ec_write(smbus, AMD_SMB_ADDR, addr << 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) if (status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) status = amd_ec_write(smbus, AMD_SMB_PRTCL, protocol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) if (status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) status = amd_ec_read(smbus, AMD_SMB_STS, temp + 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) if (status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) if (~temp[0] & AMD_SMB_STS_DONE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) udelay(500);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) status = amd_ec_read(smbus, AMD_SMB_STS, temp + 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) if (status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) if (~temp[0] & AMD_SMB_STS_DONE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) msleep(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) status = amd_ec_read(smbus, AMD_SMB_STS, temp + 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) if (status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) if ((~temp[0] & AMD_SMB_STS_DONE) || (temp[0] & AMD_SMB_STS_STATUS))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) if (read_write == I2C_SMBUS_WRITE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) switch (size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) case I2C_SMBUS_BYTE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) case I2C_SMBUS_BYTE_DATA:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) status = amd_ec_read(smbus, AMD_SMB_DATA, &data->byte);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) if (status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) case I2C_SMBUS_WORD_DATA:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) case I2C_SMBUS_PROC_CALL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) status = amd_ec_read(smbus, AMD_SMB_DATA, temp + 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) if (status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) status = amd_ec_read(smbus, AMD_SMB_DATA + 1, temp + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) if (status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) data->word = (temp[1] << 8) | temp[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) case I2C_SMBUS_BLOCK_DATA:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) case I2C_SMBUS_BLOCK_PROC_CALL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) status = amd_ec_read(smbus, AMD_SMB_BCNT, &len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) if (status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) len = min_t(u8, len, I2C_SMBUS_BLOCK_MAX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) case I2C_SMBUS_I2C_BLOCK_DATA:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) for (i = 0; i < len; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) status = amd_ec_read(smbus, AMD_SMB_DATA + i,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) data->block + i + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) if (status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) data->block[0] = len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) static u32 amd8111_func(struct i2c_adapter *adapter)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) I2C_FUNC_SMBUS_BYTE_DATA |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) I2C_FUNC_SMBUS_WORD_DATA | I2C_FUNC_SMBUS_BLOCK_DATA |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) I2C_FUNC_SMBUS_PROC_CALL | I2C_FUNC_SMBUS_BLOCK_PROC_CALL |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) I2C_FUNC_SMBUS_I2C_BLOCK | I2C_FUNC_SMBUS_PEC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) static const struct i2c_algorithm smbus_algorithm = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) .smbus_xfer = amd8111_access,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) .functionality = amd8111_func,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) static const struct pci_device_id amd8111_ids[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8111_SMBUS2) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) { 0, }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) MODULE_DEVICE_TABLE (pci, amd8111_ids);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) static int amd8111_probe(struct pci_dev *dev, const struct pci_device_id *id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) struct amd_smbus *smbus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) if (!(pci_resource_flags(dev, 0) & IORESOURCE_IO))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) smbus = kzalloc(sizeof(struct amd_smbus), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) if (!smbus)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) smbus->dev = dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) smbus->base = pci_resource_start(dev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) smbus->size = pci_resource_len(dev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) error = acpi_check_resource_conflict(&dev->resource[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) if (error) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) error = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) goto out_kfree;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) if (!request_region(smbus->base, smbus->size, amd8111_driver.name)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) error = -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) goto out_kfree;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) smbus->adapter.owner = THIS_MODULE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) snprintf(smbus->adapter.name, sizeof(smbus->adapter.name),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) "SMBus2 AMD8111 adapter at %04x", smbus->base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) smbus->adapter.class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) smbus->adapter.algo = &smbus_algorithm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) smbus->adapter.algo_data = smbus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) /* set up the sysfs linkage to our parent device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) smbus->adapter.dev.parent = &dev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) pci_write_config_dword(smbus->dev, AMD_PCI_MISC, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) error = i2c_add_adapter(&smbus->adapter);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) goto out_release_region;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) pci_set_drvdata(dev, smbus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) out_release_region:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) release_region(smbus->base, smbus->size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) out_kfree:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) kfree(smbus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) static void amd8111_remove(struct pci_dev *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) struct amd_smbus *smbus = pci_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) i2c_del_adapter(&smbus->adapter);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) release_region(smbus->base, smbus->size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) kfree(smbus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) static struct pci_driver amd8111_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) .name = "amd8111_smbus2",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) .id_table = amd8111_ids,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) .probe = amd8111_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) .remove = amd8111_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) module_pci_driver(amd8111_driver);