2 * This file is part of the coreboot project.
4 * Copyright (C) 2004 Tyan
5 * (Written by Yinghai Lu <yhlu@tyan.com> for Tyan)
6 * Copyright (C) 2004 Li-Ta Lo <ollie@lanl.gov>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; version 2 of the License.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
18 #include <console/console.h>
20 #include <device/device.h>
21 #include <device/path.h>
22 #include <device/smbus.h>
24 struct bus
*get_pbus_smbus(device_t dev
)
26 struct bus
*pbus
= dev
->bus
;
28 while (pbus
&& pbus
->dev
&& !ops_smbus_bus(pbus
)) {
29 if (pbus
->dev
->bus
!= pbus
) {
30 pbus
= pbus
->dev
->bus
;
34 "%s Find SMBus bus operations: unable to proceed\n",
40 if (!pbus
|| !pbus
->dev
|| !pbus
->dev
->ops
41 || !pbus
->dev
->ops
->ops_smbus_bus
) {
42 printk(BIOS_ALERT
, "%s Cannot find SMBus bus operations",
51 * Multi-level I2C MUX? May need to find the first I2C device and then set link
52 * down to current dev.
54 * 1 store get_pbus_smbus list link
55 * 2 reverse the link and call set link.
59 int smbus_set_link(device_t dev
)
61 struct bus
*pbus_a
[4]; // 4 level mux only. Enough?
62 struct bus
*pbus
= dev
->bus
;
66 while (pbus
&& pbus
->dev
&& (pbus
->dev
->path
.type
== DEVICE_PATH_I2C
)) {
67 pbus_a
[pbus_num
++] = pbus
;
68 pbus
= pbus
->dev
->bus
;
71 // printk(BIOS_INFO, "smbus_set_link: ");
72 for (i
= pbus_num
- 1; i
>= 0; i
--) {
73 // printk(BIOS_INFO, " %s[%d] -> ", dev_path(pbus_a[i]->dev),
75 if (ops_smbus_bus(get_pbus_smbus(pbus_a
[i
]->dev
))) {
76 if (pbus_a
[i
]->dev
->ops
77 && pbus_a
[i
]->dev
->ops
->set_link
)
78 pbus_a
[i
]->dev
->ops
->set_link(pbus_a
[i
]->dev
,
82 // printk(BIOS_INFO, " %s\n", dev_path(dev));
87 #define CHECK_PRESENCE(x) \
88 if (!ops_smbus_bus(get_pbus_smbus(dev))->x) { \
89 printk(BIOS_ERR, "%s missing " #x "\n", \
95 int smbus_quick_read(device_t dev
)
97 CHECK_PRESENCE(quick_read
);
99 return ops_smbus_bus(get_pbus_smbus(dev
))->quick_read(dev
);
102 int smbus_quick_write(device_t dev
)
104 CHECK_PRESENCE(quick_write
);
106 return ops_smbus_bus(get_pbus_smbus(dev
))->quick_write(dev
);
109 int smbus_recv_byte(device_t dev
)
111 CHECK_PRESENCE(recv_byte
);
113 return ops_smbus_bus(get_pbus_smbus(dev
))->recv_byte(dev
);
116 int smbus_send_byte(device_t dev
, u8 byte
)
118 CHECK_PRESENCE(send_byte
);
120 return ops_smbus_bus(get_pbus_smbus(dev
))->send_byte(dev
, byte
);
123 int smbus_read_byte(device_t dev
, u8 addr
)
125 CHECK_PRESENCE(read_byte
);
127 return ops_smbus_bus(get_pbus_smbus(dev
))->read_byte(dev
, addr
);
130 int smbus_write_byte(device_t dev
, u8 addr
, u8 val
)
132 CHECK_PRESENCE(write_byte
);
134 return ops_smbus_bus(get_pbus_smbus(dev
))->write_byte(dev
, addr
, val
);
137 int smbus_read_word(device_t dev
, u8 addr
)
139 CHECK_PRESENCE(read_word
);
141 return ops_smbus_bus(get_pbus_smbus(dev
))->read_word(dev
, addr
);
144 int smbus_write_word(device_t dev
, u8 addr
, u16 val
)
146 CHECK_PRESENCE(write_word
);
148 return ops_smbus_bus(get_pbus_smbus(dev
))->write_word(dev
, addr
, val
);
151 int smbus_process_call(device_t dev
, u8 cmd
, u16 data
)
153 CHECK_PRESENCE(process_call
);
155 return ops_smbus_bus(get_pbus_smbus(dev
))->process_call(dev
, cmd
, data
);
158 int smbus_block_read(device_t dev
, u8 cmd
, u8 bytes
, u8
*buffer
)
160 CHECK_PRESENCE(block_read
);
162 return ops_smbus_bus(get_pbus_smbus(dev
))->block_read(dev
, cmd
,
166 int smbus_block_write(device_t dev
, u8 cmd
, u8 bytes
, const u8
*buffer
)
168 CHECK_PRESENCE(block_write
);
170 return ops_smbus_bus(get_pbus_smbus(dev
))->block_write(dev
, cmd
,