7678fb50fb9337de59d2e2c68156f321b3f5b775
[coreboot.git] / src / southbridge / nvidia / ck804 / ck804_nic.c
1 /*
2  * Copyright 2004 Tyan Computer
3  *  by yhlu@tyan.com
4  */
5
6 #include <console/console.h>
7 #include <device/device.h>
8 #include <device/smbus.h>
9 #include <device/pci.h>
10 #include <device/pci_ids.h>
11 #include <device/pci_ops.h>
12 #include <arch/io.h>
13 #include "ck804.h"
14
15 static void nic_init(struct device *dev)
16 {
17         uint32_t dword, old, mac_h, mac_l;
18         int eeprom_valid = 0;
19         struct southbridge_nvidia_ck804_config *conf;
20         static uint32_t nic_index = 0;
21         unsigned long base;
22         struct resource *res;
23
24         res = find_resource(dev, 0x10);
25         base = (unsigned long)res->base;
26
27 #define NvRegPhyInterface  0xC0
28 #define PHY_RGMII          0x10000000
29
30         write32(base + NvRegPhyInterface, PHY_RGMII);
31
32         old = dword = pci_read_config32(dev, 0x30);
33         dword &= ~(0xf);
34         dword |= 0xf;
35         if (old != dword)
36                 pci_write_config32(dev, 0x30, dword);
37
38         conf = dev->chip_info;
39
40         if (conf->mac_eeprom_smbus != 0) {
41                 /* Read MAC address from EEPROM at first. */
42                 struct device *dev_eeprom;
43                 dev_eeprom = dev_find_slot_on_smbus(conf->mac_eeprom_smbus,
44                                            conf->mac_eeprom_addr);
45
46                 if (dev_eeprom) {
47                         /* If that is valid we will use that. */
48                         unsigned char dat[6];
49                         int i, status;
50                         for (i = 0; i < 6; i++) {
51                                 status = smbus_read_byte(dev_eeprom, i);
52                                 if (status < 0)
53                                         break;
54                                 dat[i] = status & 0xff;
55                         }
56                         if (status >= 0) {
57                                 mac_l = 0;
58                                 for (i = 3; i >= 0; i--) {
59                                         mac_l <<= 8;
60                                         mac_l += dat[i];
61                                 }
62                                 if (mac_l != 0xffffffff) {
63                                         mac_l += nic_index;
64                                         mac_h = 0;
65                                         for (i = 5; i >= 4; i--) {
66                                                 mac_h <<= 8;
67                                                 mac_h += dat[i];
68                                         }
69                                         eeprom_valid = 1;
70                                 }
71                         }
72                 }
73         }
74
75         /* If that is invalid we will read that from romstrap. */
76         if (!eeprom_valid) {
77                 unsigned long mac_pos;
78                 mac_pos = 0xffffffd0; /* See romstrap.inc and romstrap.lds. */
79                 mac_l = read32(mac_pos) + nic_index;
80                 mac_h = read32(mac_pos + 4);
81         }
82 #if 1
83         /* Set that into NIC MMIO. */
84 #define NvRegMacAddrA  0xA8
85 #define NvRegMacAddrB  0xAC
86         write32(base + NvRegMacAddrA, mac_l);
87         write32(base + NvRegMacAddrB, mac_h);
88 #else
89         /* Set that into NIC. */
90         pci_write_config32(dev, 0xa8, mac_l);
91         pci_write_config32(dev, 0xac, mac_h);
92 #endif
93
94         nic_index++;
95
96 #if CONFIG_PCI_ROM_RUN == 1
97         pci_dev_init(dev);      /* It will init Option ROM. */
98 #endif
99 }
100
101 static void lpci_set_subsystem(device_t dev, unsigned vendor, unsigned device)
102 {
103         pci_write_config32(dev, 0x40,
104                            ((device & 0xffff) << 16) | (vendor & 0xffff));
105 }
106
107 static struct pci_operations lops_pci = {
108         .set_subsystem = lpci_set_subsystem,
109 };
110
111 static struct device_operations nic_ops = {
112         .read_resources   = pci_dev_read_resources,
113         .set_resources    = pci_dev_set_resources,
114         .enable_resources = pci_dev_enable_resources,
115         .init             = nic_init,
116         .scan_bus         = 0,
117         // .enable        = ck804_enable,
118         .ops_pci          = &lops_pci,
119 };
120
121 static const struct pci_driver nic_driver __pci_driver = {
122         .ops    = &nic_ops,
123         .vendor = PCI_VENDOR_ID_NVIDIA,
124         .device = PCI_DEVICE_ID_NVIDIA_CK804_NIC,
125 };
126
127 static const struct pci_driver nic_bridge_driver __pci_driver = {
128         .ops    = &nic_ops,
129         .vendor = PCI_VENDOR_ID_NVIDIA,
130         .device = PCI_DEVICE_ID_NVIDIA_CK804_NIC_BRIDGE,
131 };