xref: /aosp_15_r20/external/coreboot/src/drivers/i2c/ck505/ck505.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <assert.h>
4 #include <console/console.h>
5 #include <device/device.h>
6 #include <device/smbus.h>
7 #include "chip.h"
8 
9 #define SMBUS_BLOCK_SIZE 32
10 
ck505_init(struct device * dev)11 static void ck505_init(struct device *dev)
12 {
13 	struct drivers_i2c_ck505_config *config;
14 	int dev_nregs, nregs;
15 	u8 block[SMBUS_BLOCK_SIZE];
16 	int i;
17 
18 	if (!dev->enabled || dev->path.type != DEVICE_PATH_I2C)
19 		return;
20 
21 	config = dev->chip_info;
22 
23 	dev_nregs = smbus_block_read(dev, 0, sizeof(block), block);
24 
25 	if (dev_nregs < 0) {
26 		printk(BIOS_ERR, "Failed reading ck505 configuration!\n");
27 		return;
28 	}
29 
30 	/* This means that the devicetree doesn't have to specify nregs */
31 	nregs = MIN(MIN(dev_nregs, config->nregs == 0 ? SMBUS_BLOCK_SIZE
32 				: config->nregs), ARRAY_SIZE(config->mask));
33 
34 	printk(BIOS_DEBUG, "Changing %d of the %d ck505 config bytes.\n",
35 		nregs, dev_nregs);
36 
37 	assert(ARRAY_SIZE(config->mask) == ARRAY_SIZE(config->regs));
38 
39 	for (i = 0; i < nregs && i < SMBUS_BLOCK_SIZE; i++)
40 		block[i] = (block[i] & ~config->mask[i]) | config->regs[i];
41 
42 	if (smbus_block_write(dev, 0, dev_nregs, block) < 0)
43 		printk(BIOS_ERR, "Failed writing ck505 configuration!\n");
44 }
45 
46 static struct device_operations ck505_operations = {
47 	.read_resources		= noop_read_resources,
48 	.set_resources		= noop_set_resources,
49 	.init			= ck505_init,
50 };
51 
enable_dev(struct device * dev)52 static void enable_dev(struct device *dev)
53 {
54 	dev->ops = &ck505_operations;
55 }
56 
57 struct chip_operations drivers_i2c_ck505_ops = {
58 	.name = "CK505 Clock generator",
59 	.enable_dev = enable_dev,
60 };
61