blob: 4f1e51e02a31d91178471e49eaa06c70dc2d77a6 [file] [log] [blame]
Arthur Heymans24231ac2017-06-06 09:46:01 +02001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright (C) 2011 Sven Schnelle <svens@stackframe.org>
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; version 2 of
9 * the License.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 */
16
17#include <assert.h>
18#include <console/console.h>
19#include <device/device.h>
20#include <device/smbus.h>
21#include <device/pci.h>
22#include <device/pci_ids.h>
23#include <device/pci_ops.h>
24#include <cpu/x86/msr.h>
25#include "chip.h"
26#include <string.h>
27
28#define SMBUS_BLOCK_SIZE 32
29
30static void ck505_init(struct device *dev)
31{
32 struct drivers_i2c_ck505_config *config;
33 int dev_nregs, nregs;
34 u8 block[SMBUS_BLOCK_SIZE];
35 int i;
36
37 if (!dev->enabled || dev->path.type != DEVICE_PATH_I2C)
38 return;
39
40 config = dev->chip_info;
41
42 dev_nregs = smbus_block_read(dev, 0, sizeof(block), block);
43
44 if (dev_nregs < 0) {
45 printk(BIOS_ERR, "Failed reading ck505 configuration!\n");
46 return;
47 }
48
49 /* This means that the devicetree doesn't have to specify nregs */
50 nregs = MIN(MIN(dev_nregs, config->nregs == 0 ? SMBUS_BLOCK_SIZE
51 : config->nregs), ARRAY_SIZE(config->mask));
52
53
54 printk(BIOS_DEBUG, "Changing %d of the %d ck505 config bytes.\n",
55 nregs, dev_nregs);
56
57 assert(ARRAY_SIZE(config->mask) == ARRAY_SIZE(config->regs));
58
59 for (i = 0; i < nregs && i < SMBUS_BLOCK_SIZE; i++)
60 block[i] = (block[i] & ~config->mask[i]) | config->regs[i];
61
62 if (smbus_block_write(dev, 0, dev_nregs, block) < 0)
63 printk(BIOS_ERR, "Failed writing ck505 configuration!\n");
64}
65
66static struct device_operations ck505_operations = {
67 .read_resources = DEVICE_NOOP,
68 .set_resources = DEVICE_NOOP,
69 .enable_resources = DEVICE_NOOP,
70 .init = ck505_init,
71};
72
73static void enable_dev(struct device *dev)
74{
75 dev->ops = &ck505_operations;
76}
77
78struct chip_operations drivers_i2c_ck505_ops = {
79 CHIP_NAME("CK505 Clock generator")
80 .enable_dev = enable_dev,
81};