blob: 1898ca627a7ec9021eaa41d4d40a85135cde2899 [file] [log] [blame]
Yinghai Luafd34e62006-02-16 17:22:19 +00001/*
Uwe Hermannc6a10622010-10-17 19:30:58 +00002 * This file is part of the coreboot project.
3 *
4 * Copyright (C) 2005 AMD
5 * Written by Yinghai Lu <yinghai.lu@amd.com> for AMD.
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; version 2 of 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.
Yinghai Luafd34e62006-02-16 17:22:19 +000015 */
16
17#include <console/console.h>
18#include <device/device.h>
19#include <device/pci.h>
20#include <device/pnp.h>
21#include <device/pci_ids.h>
22#include <device/pci_ops.h>
23#include <pc80/mc146818rtc.h>
24#include <pc80/isa-dma.h>
Yinghai Luafd34e62006-02-16 17:22:19 +000025#include <arch/io.h>
26#include <device/smbus.h>
27#include "bcm5785.h"
stepan836ae292010-12-08 05:42:47 +000028#include "smbus.h"
Yinghai Luafd34e62006-02-16 17:22:19 +000029
30#define NMI_OFF 0
31
32static void sb_init(device_t dev)
33{
34 uint8_t byte;
35 uint8_t byte_old;
Luc Verhaegena9c5ea02009-06-03 14:19:33 +000036 int nmi_option;
Yinghai Luafd34e62006-02-16 17:22:19 +000037
Yinghai Luafd34e62006-02-16 17:22:19 +000038 /* Set up NMI on errors */
39 byte = inb(0x70); // RTC70
40 byte_old = byte;
41 nmi_option = NMI_OFF;
Luc Verhaegena9c5ea02009-06-03 14:19:33 +000042 get_option(&nmi_option, "nmi");
Stefan Reinauer14e22772010-04-27 06:56:47 +000043 if (nmi_option) {
Yinghai Luafd34e62006-02-16 17:22:19 +000044 byte &= ~(1 << 7); /* set NMI */
45 } else {
46 byte |= ( 1 << 7); // Can not mask NMI from PCI-E and NMI_NOW
47 }
48 if( byte != byte_old) {
Ed Swierke42e1422009-07-10 15:05:35 +000049 outb(byte, 0x70);
Yinghai Luafd34e62006-02-16 17:22:19 +000050 }
51
52
53}
54
55static void bcm5785_sb_read_resources(device_t dev)
56{
57 struct resource *res;
Yinghai Luafd34e62006-02-16 17:22:19 +000058
59 /* Get the normal pci resources of this device */
Stefan Reinauer14e22772010-04-27 06:56:47 +000060 pci_dev_read_resources(dev);
61 /* Get Resource for SMBUS */
62 pci_get_resource(dev, 0x90);
Yinghai Luafd34e62006-02-16 17:22:19 +000063
Stefan Reinauer14e22772010-04-27 06:56:47 +000064 compact_resources(dev);
Yinghai Luafd34e62006-02-16 17:22:19 +000065
66 /* Add an extra subtractive resource for both memory and I/O */
67 res = new_resource(dev, IOINDEX_SUBTRACTIVE(0, 0));
68 res->flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE | IORESOURCE_ASSIGNED;
Stefan Reinauer14e22772010-04-27 06:56:47 +000069
Yinghai Luafd34e62006-02-16 17:22:19 +000070 res = new_resource(dev, IOINDEX_SUBTRACTIVE(1, 0));
71 res->flags = IORESOURCE_MEM | IORESOURCE_SUBTRACTIVE | IORESOURCE_ASSIGNED;
72
73}
Stefan Reinauerc51dc442010-04-07 01:44:04 +000074
Yinghai Luafd34e62006-02-16 17:22:19 +000075static int lsmbus_recv_byte(device_t dev)
76{
77 unsigned device;
78 struct resource *res;
79 struct bus *pbus;
80
Stefan Reinauer2b34db82009-02-28 20:10:20 +000081 device = dev->path.i2c.device;
Yinghai Luafd34e62006-02-16 17:22:19 +000082 pbus = get_pbus_smbus(dev);
83
84 res = find_resource(pbus->dev, 0x90);
85
86 return do_smbus_recv_byte(res->base, device);
87}
Stefan Reinauer14e22772010-04-27 06:56:47 +000088
Yinghai Luafd34e62006-02-16 17:22:19 +000089static int lsmbus_send_byte(device_t dev, uint8_t val)
90{
91 unsigned device;
92 struct resource *res;
93 struct bus *pbus;
94
Stefan Reinauer2b34db82009-02-28 20:10:20 +000095 device = dev->path.i2c.device;
Yinghai Luafd34e62006-02-16 17:22:19 +000096 pbus = get_pbus_smbus(dev);
97
98 res = find_resource(pbus->dev, 0x90);
99
100 return do_smbus_send_byte(res->base, device, val);
101}
Uwe Hermannc6a10622010-10-17 19:30:58 +0000102
Yinghai Luafd34e62006-02-16 17:22:19 +0000103static int lsmbus_read_byte(device_t dev, uint8_t address)
104{
105 unsigned device;
106 struct resource *res;
107 struct bus *pbus;
108
Stefan Reinauer2b34db82009-02-28 20:10:20 +0000109 device = dev->path.i2c.device;
Yinghai Luafd34e62006-02-16 17:22:19 +0000110 pbus = get_pbus_smbus(dev);
111
112 res = find_resource(pbus->dev, 0x90);
113
114 return do_smbus_read_byte(res->base, device, address);
115}
Uwe Hermannc6a10622010-10-17 19:30:58 +0000116
Yinghai Luafd34e62006-02-16 17:22:19 +0000117static int lsmbus_write_byte(device_t dev, uint8_t address, uint8_t val)
118{
119 unsigned device;
120 struct resource *res;
121 struct bus *pbus;
122
Stefan Reinauer2b34db82009-02-28 20:10:20 +0000123 device = dev->path.i2c.device;
Yinghai Luafd34e62006-02-16 17:22:19 +0000124 pbus = get_pbus_smbus(dev);
125
126 res = find_resource(pbus->dev, 0x90);
127
128 return do_smbus_write_byte(res->base, device, address, val);
129}
Uwe Hermannc6a10622010-10-17 19:30:58 +0000130
Yinghai Luafd34e62006-02-16 17:22:19 +0000131static struct smbus_bus_operations lops_smbus_bus = {
132 .recv_byte = lsmbus_recv_byte,
133 .send_byte = lsmbus_send_byte,
134 .read_byte = lsmbus_read_byte,
135 .write_byte = lsmbus_write_byte,
136};
137
138static void lpci_set_subsystem(device_t dev, unsigned vendor, unsigned device)
139{
140 pci_write_config32(dev, 0x2c,
141 ((device & 0xffff) << 16) | (vendor & 0xffff));
142}
143
144static struct pci_operations lops_pci = {
145 .set_subsystem = lpci_set_subsystem,
146};
147
148static struct device_operations sb_ops = {
149 .read_resources = bcm5785_sb_read_resources,
150 .set_resources = pci_dev_set_resources,
151 .enable_resources = pci_dev_enable_resources,
152 .init = sb_init,
Kyösti Mälkkid0e212c2015-02-26 20:47:47 +0200153 .scan_bus = scan_smbus,
Yinghai Luafd34e62006-02-16 17:22:19 +0000154// .enable = bcm5785_enable,
155 .ops_pci = &lops_pci,
156 .ops_smbus_bus = &lops_smbus_bus,
157};
Uwe Hermannc6a10622010-10-17 19:30:58 +0000158
Stefan Reinauerf1cf1f72007-10-24 09:08:58 +0000159static const struct pci_driver sb_driver __pci_driver = {
Yinghai Luafd34e62006-02-16 17:22:19 +0000160 .ops = &sb_ops,
161 .vendor = PCI_VENDOR_ID_SERVERWORKS,
162 .device = PCI_DEVICE_ID_SERVERWORKS_BCM5785_SB_PCI_MAIN,
163};