MCP55: Cosmetic fixes, switch to u8 et al.
[coreboot.git] / src / southbridge / nvidia / mcp55 / nic.c
1 /*
2  * This file is part of the coreboot project.
3  *
4  * Copyright (C) 2004 Tyan Computer
5  * Written by Yinghai Lu <yhlu@tyan.com> for Tyan Computer.
6  * Copyright (C) 2006,2007 AMD
7  * Written by Yinghai Lu <yinghai.lu@amd.com> for AMD.
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
22  */
23
24 #include <console/console.h>
25 #include <device/device.h>
26 #include <device/smbus.h>
27 #include <device/pci.h>
28 #include <device/pci_ids.h>
29 #include <device/pci_ops.h>
30 #include <arch/io.h>
31 #include <delay.h>
32 #include "mcp55.h"
33
34 static int phy_read(u32 base, unsigned phy_addr, unsigned phy_reg)
35 {
36         u32 dword;
37         unsigned loop = 0x100;
38
39         write32(base + 0x190, 0x8000); /* Clear MDIO lock bit. */
40         mdelay(1);
41         dword = read32(base + 0x190);
42         if (dword & (1 << 15))
43                 return -1;
44
45         write32(base + 0x180, 1);
46         write32(base + 0x190, (phy_addr << 5) | (phy_reg));
47         do {
48                 dword = read32(base + 0x190);
49                 if (--loop==0)
50                         return -4;
51         } while ((dword & (1 << 15)));
52
53         dword = read32(base + 0x180);
54         if (dword & 1)
55                 return -3;
56
57         dword = read32(base + 0x194);
58
59         return dword;
60 }
61
62 static void phy_detect(u32 base)
63 {
64         u32 dword;
65         int i, val;
66         unsigned id;
67
68         dword = read32(base + 0x188);
69         dword &= ~(1 << 20);
70         write32(base + 0x188, dword);
71
72         phy_read(base, 0, 1);
73
74         for (i = 1; i <= 32; i++) {
75                 int phyaddr = i & 0x1f;
76                 val = phy_read(base, phyaddr, 1);
77                 if (val < 0)
78                         continue;
79                 if ((val & 0xffff) == 0xfffff)
80                         continue;
81                 if ((val & 0xffff) == 0)
82                         continue;
83                 if (!(val & 1))
84                         break; /* Ethernet PHY */
85
86                 val = phy_read(base, phyaddr, 3);
87                 if (val < 0 || val == 0xffff)
88                         continue;
89                 id = val & 0xfc00;
90                 val = phy_read(base, phyaddr, 2);
91                 if (val < 0 || val == 0xffff)
92                         continue;
93                 id |= ((val & 0xffff) << 16);
94                 printk(BIOS_DEBUG, "MCP55 MAC PHY ID 0x%08x PHY ADDR %d\n",
95                        id, i);
96 //              if ((id == 0xe0180000) || (id == 0x0032cc00))
97                         break;
98         }
99
100         if (i > 32)
101                 printk(BIOS_DEBUG, "MCP55 MAC PHY not found\n");
102 }
103
104 static void nic_init(struct device *dev)
105 {
106         u32 mac_h, mac_l, base;
107         int eeprom_valid = 0;
108         struct southbridge_nvidia_mcp55_config *conf;
109         static u32 nic_index = 0;
110         struct resource *res;
111
112         res = find_resource(dev, 0x10);
113
114         if (!res)
115                 return;
116
117         base = res->base;
118
119         phy_detect(base);
120
121 #define NvRegPhyInterface       0xC0
122 #define PHY_RGMII               0x10000000
123
124         write32(base + NvRegPhyInterface, PHY_RGMII);
125
126         conf = dev->chip_info;
127
128         if (conf->mac_eeprom_smbus != 0) {
129 //      read MAC address from EEPROM at first
130                 struct device *dev_eeprom;
131                 dev_eeprom = dev_find_slot_on_smbus(conf->mac_eeprom_smbus, conf->mac_eeprom_addr);
132
133                 if(dev_eeprom) {
134                 //      if that is valid we will use that
135                         unsigned char dat[6];
136                         int status;
137                         int i;
138                         for(i=0;i<6;i++) {
139                                 status = smbus_read_byte(dev_eeprom, i);
140                                 if(status < 0) break;
141                                 dat[i] = status & 0xff;
142                         }
143                         if(status >= 0) {
144                                 mac_l = 0;
145                                 for(i=3;i>=0;i--) {
146                                         mac_l <<= 8;
147                                         mac_l += dat[i];
148                                 }
149                                 if(mac_l != 0xffffffff) {
150                                         mac_l += nic_index;
151                                         mac_h = 0;
152                                         for(i=5;i>=4;i--) {
153                                                 mac_h <<= 8;
154                                                 mac_h += dat[i];
155                                         }
156                                         eeprom_valid = 1;
157                                 }
158                         }
159                 }
160         }
161 //      if that is invalid we will read that from romstrap
162         if(!eeprom_valid) {
163                 unsigned long mac_pos;
164                 mac_pos = 0xffffffd0; // refer to romstrap.inc and romstrap.lds
165                 mac_l = read32(mac_pos) + nic_index; // overflow?
166                 mac_h = read32(mac_pos + 4);
167
168         }
169 #if 1
170 //      set that into NIC MMIO
171 #define NvRegMacAddrA   0xA8
172 #define NvRegMacAddrB   0xAC
173         write32(base + NvRegMacAddrA, mac_l);
174         write32(base + NvRegMacAddrB, mac_h);
175 #else
176 //      set that into NIC
177         pci_write_config32(dev, 0xa8, mac_l);
178         pci_write_config32(dev, 0xac, mac_h);
179 #endif
180
181         nic_index++;
182
183 #if CONFIG_PCI_ROM_RUN == 1
184         pci_dev_init(dev);// it will init option rom
185 #endif
186
187 }
188
189 static struct device_operations nic_ops  = {
190         .read_resources = pci_dev_read_resources,
191         .set_resources  = pci_dev_set_resources,
192         .enable_resources       = pci_dev_enable_resources,
193         .init           = nic_init,
194         .scan_bus       = 0,
195 //      .enable         = mcp55_enable,
196         .ops_pci        = &mcp55_pci_ops,
197 };
198 static const struct pci_driver nic_driver __pci_driver = {
199         .ops    = &nic_ops,
200         .vendor = PCI_VENDOR_ID_NVIDIA,
201         .device = PCI_DEVICE_ID_NVIDIA_MCP55_NIC,
202 };
203 static const struct pci_driver nic_bridge_driver __pci_driver = {
204         .ops    = &nic_ops,
205         .vendor = PCI_VENDOR_ID_NVIDIA,
206         .device = PCI_DEVICE_ID_NVIDIA_MCP55_NIC_BRIDGE,
207 };