blob: bcef4cd3ccae4682b4934743719123ac58145516 [file] [log] [blame]
Uwe Hermannb80dbf02007-04-22 19:08:13 +00001/*
Stefan Reinauer7e61e452008-01-18 10:35:56 +00002 * This file is part of the coreboot project.
Uwe Hermannb80dbf02007-04-22 19:08:13 +00003 *
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>
7 *
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.
11 *
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.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
Paul Menzela46a7122013-02-23 18:37:27 +010019 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Uwe Hermannb80dbf02007-04-22 19:08:13 +000020 */
21
Yinghai Lu7213d0f2004-12-03 03:39:04 +000022#include <console/console.h>
23#include <stdint.h>
24#include <device/device.h>
25#include <device/path.h>
26#include <device/smbus.h>
27
28struct bus *get_pbus_smbus(device_t dev)
29{
30 struct bus *pbus = dev->bus;
Uwe Hermannd453dd02010-10-18 00:00:57 +000031
32 while (pbus && pbus->dev && !ops_smbus_bus(pbus))
Yinghai Lu7213d0f2004-12-03 03:39:04 +000033 pbus = pbus->dev->bus;
Uwe Hermannd453dd02010-10-18 00:00:57 +000034
35 if (!pbus || !pbus->dev || !pbus->dev->ops
36 || !pbus->dev->ops->ops_smbus_bus) {
37 printk(BIOS_ALERT, "%s Cannot find SMBus bus operations",
38 dev_path(dev));
Yinghai Lu7213d0f2004-12-03 03:39:04 +000039 die("");
Yinghai Lu7213d0f2004-12-03 03:39:04 +000040 }
Uwe Hermannd453dd02010-10-18 00:00:57 +000041
Yinghai Lu7213d0f2004-12-03 03:39:04 +000042 return pbus;
43}
44
Uwe Hermannc1ee4292010-10-17 19:01:48 +000045/*
Uwe Hermanne4870472010-11-04 23:23:47 +000046 * Multi-level I2C MUX? May need to find the first I2C device and then set link
Uwe Hermannc1ee4292010-10-17 19:01:48 +000047 * down to current dev.
48 *
49 * 1 store get_pbus_smbus list link
50 * 2 reverse the link and call set link.
51 *
52 * @param dev TODO.
53 */
Yinghai Lu7213d0f2004-12-03 03:39:04 +000054int smbus_set_link(device_t dev)
55{
56 struct bus *pbus_a[4]; // 4 level mux only. Enough?
Uwe Hermannd453dd02010-10-18 00:00:57 +000057 struct bus *pbus = dev->bus;
58 int pbus_num = 0;
Yinghai Lu7213d0f2004-12-03 03:39:04 +000059 int i;
Uwe Hermannd453dd02010-10-18 00:00:57 +000060
61 while (pbus && pbus->dev && (pbus->dev->path.type == DEVICE_PATH_I2C)) {
Yinghai Lu7213d0f2004-12-03 03:39:04 +000062 pbus_a[pbus_num++] = pbus;
Uwe Hermannd453dd02010-10-18 00:00:57 +000063 pbus = pbus->dev->bus;
64 }
65
66 // printk(BIOS_INFO, "smbus_set_link: ");
67 for (i = pbus_num - 1; i >= 0; i--) {
68 // printk(BIOS_INFO, " %s[%d] -> ", dev_path(pbus_a[i]->dev),
69 // pbus_a[i]->link);
70 if (ops_smbus_bus(get_pbus_smbus(pbus_a[i]->dev))) {
71 if (pbus_a[i]->dev->ops
72 && pbus_a[i]->dev->ops->set_link)
73 pbus_a[i]->dev->ops->set_link(pbus_a[i]->dev,
74 pbus_a[i]->link_num);
Yinghai Lu7213d0f2004-12-03 03:39:04 +000075 }
76 }
Uwe Hermannd453dd02010-10-18 00:00:57 +000077 // printk(BIOS_INFO, " %s\n", dev_path(dev));
Yinghai Lu7213d0f2004-12-03 03:39:04 +000078
Uwe Hermannd453dd02010-10-18 00:00:57 +000079 return pbus_num;
Yinghai Lu7213d0f2004-12-03 03:39:04 +000080}
81
82int smbus_quick_read(device_t dev)
83{
84 return ops_smbus_bus(get_pbus_smbus(dev))->quick_read(dev);
85}
Uwe Hermannd453dd02010-10-18 00:00:57 +000086
Yinghai Lu7213d0f2004-12-03 03:39:04 +000087int smbus_quick_write(device_t dev)
88{
89 return ops_smbus_bus(get_pbus_smbus(dev))->quick_write(dev);
90}
Uwe Hermannd453dd02010-10-18 00:00:57 +000091
Yinghai Lu7213d0f2004-12-03 03:39:04 +000092int smbus_recv_byte(device_t dev)
93{
94 return ops_smbus_bus(get_pbus_smbus(dev))->recv_byte(dev);
95}
Uwe Hermannd453dd02010-10-18 00:00:57 +000096
97int smbus_send_byte(device_t dev, u8 byte)
Yinghai Lu7213d0f2004-12-03 03:39:04 +000098{
99 return ops_smbus_bus(get_pbus_smbus(dev))->send_byte(dev, byte);
100}
Uwe Hermannd453dd02010-10-18 00:00:57 +0000101
102int smbus_read_byte(device_t dev, u8 addr)
Yinghai Lu7213d0f2004-12-03 03:39:04 +0000103{
104 return ops_smbus_bus(get_pbus_smbus(dev))->read_byte(dev, addr);
105}
Uwe Hermannd453dd02010-10-18 00:00:57 +0000106
107int smbus_write_byte(device_t dev, u8 addr, u8 val)
Yinghai Lu7213d0f2004-12-03 03:39:04 +0000108{
109 return ops_smbus_bus(get_pbus_smbus(dev))->write_byte(dev, addr, val);
110}
Uwe Hermannd453dd02010-10-18 00:00:57 +0000111
112int smbus_read_word(device_t dev, u8 addr)
Yinghai Lu7213d0f2004-12-03 03:39:04 +0000113{
114 return ops_smbus_bus(get_pbus_smbus(dev))->read_word(dev, addr);
115}
Uwe Hermannd453dd02010-10-18 00:00:57 +0000116
117int smbus_write_word(device_t dev, u8 addr, u16 val)
Yinghai Lu7213d0f2004-12-03 03:39:04 +0000118{
119 return ops_smbus_bus(get_pbus_smbus(dev))->write_word(dev, addr, val);
120}
Uwe Hermannd453dd02010-10-18 00:00:57 +0000121
122int smbus_process_call(device_t dev, u8 cmd, u16 data)
Yinghai Lu7213d0f2004-12-03 03:39:04 +0000123{
124 return ops_smbus_bus(get_pbus_smbus(dev))->process_call(dev, cmd, data);
125}
Uwe Hermannd453dd02010-10-18 00:00:57 +0000126
127int smbus_block_read(device_t dev, u8 cmd, u8 bytes, u8 *buffer)
Yinghai Lu7213d0f2004-12-03 03:39:04 +0000128{
Uwe Hermannd453dd02010-10-18 00:00:57 +0000129 return ops_smbus_bus(get_pbus_smbus(dev))->block_read(dev, cmd,
130 bytes, buffer);
Yinghai Lu7213d0f2004-12-03 03:39:04 +0000131}
Uwe Hermannd453dd02010-10-18 00:00:57 +0000132
133int smbus_block_write(device_t dev, u8 cmd, u8 bytes, const u8 *buffer)
Yinghai Lu7213d0f2004-12-03 03:39:04 +0000134{
Uwe Hermannd453dd02010-10-18 00:00:57 +0000135 return ops_smbus_bus(get_pbus_smbus(dev))->block_write(dev, cmd,
136 bytes, buffer);
Yinghai Lu7213d0f2004-12-03 03:39:04 +0000137}