1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * AMD Alert Standard Format Platform Driver
5 * Copyright (c) 2024, Advanced Micro Devices, Inc.
8 * Authors: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
9 * Sanket Goswami <Sanket.Goswami@amd.com>
12 #include <linux/bitops.h>
13 #include <linux/device.h>
14 #include <linux/devm-helpers.h>
15 #include <linux/errno.h>
16 #include <linux/gfp_types.h>
17 #include <linux/i2c.h>
19 #include <linux/ioport.h>
20 #include <linux/module.h>
21 #include <linux/mod_devicetable.h>
22 #include <linux/platform_device.h>
23 #include <linux/sprintf.h>
25 #include "i2c-piix4.h"
27 /* ASF register bits */
28 #define ASF_SLV_LISTN 0
29 #define ASF_SLV_INTR 1
33 #define ASF_MSTR_EN 16
36 /* ASF address offsets */
37 #define ASFINDEX (0x07 + piix4_smba)
38 #define ASFLISADDR (0x09 + piix4_smba)
39 #define ASFSTA (0x0A + piix4_smba)
40 #define ASFSLVSTA (0x0D + piix4_smba)
41 #define ASFDATARWPTR (0x11 + piix4_smba)
42 #define ASFSETDATARDPTR (0x12 + piix4_smba)
43 #define ASFDATABNKSEL (0x13 + piix4_smba)
44 #define ASFSLVEN (0x15 + piix4_smba)
46 #define ASF_BLOCK_MAX_BYTES 72
47 #define ASF_ERROR_STATUS GENMASK(3, 1)
50 struct i2c_adapter adap
;
51 void __iomem
*eoi_base
;
52 struct i2c_client
*target
;
53 struct delayed_work work_buf
;
54 struct sb800_mmio_cfg mmio_cfg
;
55 struct resource
*port_addr
;
58 static void amd_asf_process_target(struct work_struct
*work
)
60 struct amd_asf_dev
*dev
= container_of(work
, struct amd_asf_dev
, work_buf
.work
);
61 unsigned short piix4_smba
= dev
->port_addr
->start
;
62 u8 data
[ASF_BLOCK_MAX_BYTES
];
66 /* Read target status register */
67 reg
= inb_p(ASFSLVSTA
);
69 /* Check if no error bits are set in target status register */
70 if (reg
& ASF_ERROR_STATUS
) {
71 /* Set bank as full */
74 outb_p(reg
, ASFDATABNKSEL
);
77 reg
= inb_p(ASFDATABNKSEL
);
78 bank
= (reg
& BIT(3)) ? 1 : 0;
80 /* Set read data bank */
89 /* Read command register */
90 outb_p(reg
, ASFDATABNKSEL
);
91 cmd
= inb_p(ASFINDEX
);
92 len
= inb_p(ASFDATARWPTR
);
93 for (idx
= 0; idx
< len
; idx
++)
94 data
[idx
] = inb_p(ASFINDEX
);
96 /* Clear data bank status */
99 outb_p(reg
, ASFDATABNKSEL
);
102 outb_p(reg
, ASFDATABNKSEL
);
106 outb_p(0, ASFSETDATARDPTR
);
111 * Although i2c_slave_event() returns an appropriate error code, we
112 * don't check it here because we're operating in the workqueue context.
114 i2c_slave_event(dev
->target
, I2C_SLAVE_WRITE_REQUESTED
, &val
);
115 for (idx
= 0; idx
< len
; idx
++) {
117 i2c_slave_event(dev
->target
, I2C_SLAVE_WRITE_RECEIVED
, &val
);
119 i2c_slave_event(dev
->target
, I2C_SLAVE_STOP
, &val
);
122 static void amd_asf_update_ioport_target(unsigned short piix4_smba
, u8 bit
,
123 unsigned long offset
, bool set
)
128 __assign_bit(bit
, ®
, set
);
132 static void amd_asf_update_mmio_target(struct amd_asf_dev
*dev
, u8 bit
, bool set
)
136 reg
= ioread32(dev
->mmio_cfg
.addr
);
137 __assign_bit(bit
, ®
, set
);
138 iowrite32(reg
, dev
->mmio_cfg
.addr
);
141 static void amd_asf_setup_target(struct amd_asf_dev
*dev
)
143 unsigned short piix4_smba
= dev
->port_addr
->start
;
145 /* Reset both host and target before setting up */
146 outb_p(0, SMBHSTSTS
);
147 outb_p(0, ASFSLVSTA
);
150 /* Update target address */
151 amd_asf_update_ioport_target(piix4_smba
, ASF_SLV_LISTN
, ASFLISADDR
, true);
152 /* Enable target and set the clock */
153 amd_asf_update_mmio_target(dev
, ASF_MSTR_EN
, false);
154 amd_asf_update_mmio_target(dev
, ASF_CLK_EN
, true);
155 /* Enable target interrupt */
156 amd_asf_update_ioport_target(piix4_smba
, ASF_SLV_INTR
, ASFSLVEN
, true);
157 amd_asf_update_ioport_target(piix4_smba
, ASF_SLV_RST
, ASFSLVEN
, false);
158 /* Enable PEC and PEC append */
159 amd_asf_update_ioport_target(piix4_smba
, ASF_DATA_EN
, SMBHSTCNT
, true);
160 amd_asf_update_ioport_target(piix4_smba
, ASF_PEC_SP
, SMBHSTCNT
, true);
163 static int amd_asf_access(struct i2c_adapter
*adap
, u16 addr
, u8 command
, u8
*data
)
165 struct amd_asf_dev
*dev
= i2c_get_adapdata(adap
);
166 unsigned short piix4_smba
= dev
->port_addr
->start
;
169 outb_p((addr
<< 1), SMBHSTADD
);
170 outb_p(command
, SMBHSTCMD
);
172 if (len
== 0 || len
> ASF_BLOCK_MAX_BYTES
)
175 outb_p(len
, SMBHSTDAT0
);
176 /* Reset SMBBLKDAT */
178 for (i
= 1; i
<= len
; i
++)
179 outb_p(data
[i
], SMBBLKDAT
);
181 outb_p(PIIX4_BLOCK_DATA
, SMBHSTCNT
);
182 /* Enable PEC and PEC append */
183 amd_asf_update_ioport_target(piix4_smba
, ASF_DATA_EN
, SMBHSTCNT
, true);
184 amd_asf_update_ioport_target(piix4_smba
, ASF_PEC_SP
, SMBHSTCNT
, true);
186 return piix4_transaction(adap
, piix4_smba
);
189 static int amd_asf_xfer(struct i2c_adapter
*adap
, struct i2c_msg
*msgs
, int num
)
191 struct amd_asf_dev
*dev
= i2c_get_adapdata(adap
);
192 unsigned short piix4_smba
= dev
->port_addr
->start
;
193 u8 asf_data
[ASF_BLOCK_MAX_BYTES
];
194 struct i2c_msg
*dev_msgs
= msgs
;
198 if (msgs
->flags
& I2C_M_RD
) {
199 dev_err(&adap
->dev
, "ASF: Read not supported\n");
203 /* Exclude the receive header and PEC */
204 if (msgs
->len
> ASF_BLOCK_MAX_BYTES
- 3) {
205 dev_warn(&adap
->dev
, "ASF: max message length exceeded\n");
209 asf_data
[0] = dev_msgs
->len
;
210 memcpy(asf_data
+ 1, dev_msgs
[0].buf
, dev_msgs
->len
);
212 ret
= piix4_sb800_region_request(&adap
->dev
, &dev
->mmio_cfg
);
216 amd_asf_update_ioport_target(piix4_smba
, ASF_SLV_RST
, ASFSLVEN
, true);
217 amd_asf_update_ioport_target(piix4_smba
, ASF_SLV_LISTN
, ASFLISADDR
, false);
218 /* Clear ASF target status */
219 outb_p(0, ASFSLVSTA
);
221 /* Enable ASF SMBus controller function */
222 amd_asf_update_mmio_target(dev
, ASF_MSTR_EN
, true);
223 prev_port
= piix4_sb800_port_sel(0, &dev
->mmio_cfg
);
224 ret
= amd_asf_access(adap
, msgs
->addr
, msgs
[0].buf
[0], asf_data
);
225 piix4_sb800_port_sel(prev_port
, &dev
->mmio_cfg
);
226 amd_asf_setup_target(dev
);
227 piix4_sb800_region_release(&adap
->dev
, &dev
->mmio_cfg
);
231 static int amd_asf_reg_target(struct i2c_client
*target
)
233 struct amd_asf_dev
*dev
= i2c_get_adapdata(target
->adapter
);
234 unsigned short piix4_smba
= dev
->port_addr
->start
;
241 ret
= piix4_sb800_region_request(&target
->dev
, &dev
->mmio_cfg
);
245 reg
= (target
->addr
<< 1) | I2C_M_RD
;
246 outb_p(reg
, ASFLISADDR
);
248 amd_asf_setup_target(dev
);
249 dev
->target
= target
;
250 amd_asf_update_ioport_target(piix4_smba
, ASF_DATA_EN
, ASFDATABNKSEL
, false);
251 piix4_sb800_region_release(&target
->dev
, &dev
->mmio_cfg
);
256 static int amd_asf_unreg_target(struct i2c_client
*target
)
258 struct amd_asf_dev
*dev
= i2c_get_adapdata(target
->adapter
);
259 unsigned short piix4_smba
= dev
->port_addr
->start
;
261 amd_asf_update_ioport_target(piix4_smba
, ASF_SLV_INTR
, ASFSLVEN
, false);
262 amd_asf_update_ioport_target(piix4_smba
, ASF_SLV_RST
, ASFSLVEN
, true);
268 static u32
amd_asf_func(struct i2c_adapter
*adapter
)
270 return I2C_FUNC_SMBUS_WRITE_BLOCK_DATA
| I2C_FUNC_SMBUS_BLOCK_DATA
|
271 I2C_FUNC_SMBUS_BYTE
| I2C_FUNC_SMBUS_PEC
| I2C_FUNC_SLAVE
;
274 static const struct i2c_algorithm amd_asf_smbus_algorithm
= {
275 .master_xfer
= amd_asf_xfer
,
276 .reg_slave
= amd_asf_reg_target
,
277 .unreg_slave
= amd_asf_unreg_target
,
278 .functionality
= amd_asf_func
,
281 static irqreturn_t
amd_asf_irq_handler(int irq
, void *ptr
)
283 struct amd_asf_dev
*dev
= ptr
;
284 unsigned short piix4_smba
= dev
->port_addr
->start
;
285 u8 target_int
= inb_p(ASFSTA
);
287 if (target_int
& BIT(6)) {
288 /* Target Interrupt */
289 outb_p(target_int
| BIT(6), ASFSTA
);
290 schedule_delayed_work(&dev
->work_buf
, HZ
);
292 /* Controller Interrupt */
293 amd_asf_update_ioport_target(piix4_smba
, ASF_SLV_INTR
, SMBHSTSTS
, true);
299 static int amd_asf_probe(struct platform_device
*pdev
)
301 struct device
*dev
= &pdev
->dev
;
302 struct amd_asf_dev
*asf_dev
;
303 struct resource
*eoi_addr
;
306 asf_dev
= devm_kzalloc(dev
, sizeof(*asf_dev
), GFP_KERNEL
);
308 return dev_err_probe(dev
, -ENOMEM
, "Failed to allocate memory\n");
310 asf_dev
->mmio_cfg
.use_mmio
= true;
311 asf_dev
->port_addr
= platform_get_resource(pdev
, IORESOURCE_IO
, 0);
312 if (!asf_dev
->port_addr
)
313 return dev_err_probe(dev
, -EINVAL
, "missing IO resources\n");
316 * The resource obtained via ACPI might not belong to the ASF device address space. Instead,
317 * it could be within other IP blocks of the ASIC, which are crucial for generating
318 * subsequent interrupts. Therefore, we avoid using devm_platform_ioremap_resource() and
319 * use platform_get_resource() and devm_ioremap() separately to prevent any address space
322 eoi_addr
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
324 return dev_err_probe(dev
, -EINVAL
, "missing MEM resources\n");
326 asf_dev
->eoi_base
= devm_ioremap(dev
, eoi_addr
->start
, resource_size(eoi_addr
));
327 if (!asf_dev
->eoi_base
)
328 return dev_err_probe(dev
, -EBUSY
, "failed mapping IO region\n");
330 ret
= devm_delayed_work_autocancel(dev
, &asf_dev
->work_buf
, amd_asf_process_target
);
332 return dev_err_probe(dev
, ret
, "failed to create work queue\n");
334 irq
= platform_get_irq(pdev
, 0);
336 return dev_err_probe(dev
, irq
, "missing IRQ resources\n");
338 ret
= devm_request_irq(dev
, irq
, amd_asf_irq_handler
, IRQF_SHARED
, "amd_asf", asf_dev
);
340 return dev_err_probe(dev
, ret
, "Unable to request irq: %d for use\n", irq
);
342 asf_dev
->adap
.owner
= THIS_MODULE
;
343 asf_dev
->adap
.algo
= &amd_asf_smbus_algorithm
;
344 asf_dev
->adap
.dev
.parent
= dev
;
346 i2c_set_adapdata(&asf_dev
->adap
, asf_dev
);
347 snprintf(asf_dev
->adap
.name
, sizeof(asf_dev
->adap
.name
), "AMD ASF adapter");
349 return devm_i2c_add_adapter(dev
, &asf_dev
->adap
);
352 static const struct acpi_device_id amd_asf_acpi_ids
[] = {
356 MODULE_DEVICE_TABLE(acpi
, amd_asf_acpi_ids
);
358 static struct platform_driver amd_asf_driver
= {
360 .name
= "i2c-amd-asf",
361 .acpi_match_table
= amd_asf_acpi_ids
,
363 .probe
= amd_asf_probe
,
365 module_platform_driver(amd_asf_driver
);
367 MODULE_IMPORT_NS("PIIX4_SMBUS");
368 MODULE_LICENSE("GPL");
369 MODULE_DESCRIPTION("AMD Alert Standard Format Driver");