driver_gige.c revision cd15598707aff52da4302d9b6a3fc878bca27383
1aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch/*
2aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch * Sonics Silicon Backplane
3aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch * Broadcom Gigabit Ethernet core driver
4aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch *
5aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch * Copyright 2008, Broadcom Corporation
6aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch * Copyright 2008, Michael Buesch <mb@bu3sch.de>
7aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch *
8aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch * Licensed under the GNU/GPL. See COPYING for details.
9aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch */
10aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch
11aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch#include <linux/ssb/ssb.h>
12aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch#include <linux/ssb/ssb_driver_gige.h>
13aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch#include <linux/pci.h>
14aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch#include <linux/pci_regs.h>
155a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h>
16aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch
17aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch
18aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch/*
19aab547ce0d1493d400b6468c521a0137cd8c1edfMichael BueschMODULE_DESCRIPTION("SSB Broadcom Gigabit Ethernet driver");
20aab547ce0d1493d400b6468c521a0137cd8c1edfMichael BueschMODULE_AUTHOR("Michael Buesch");
21aab547ce0d1493d400b6468c521a0137cd8c1edfMichael BueschMODULE_LICENSE("GPL");
22aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch*/
23aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch
24aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Bueschstatic const struct ssb_device_id ssb_gige_tbl[] = {
25aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch	SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_ETHERNET_GBIT, SSB_ANY_REV),
26aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch	SSB_DEVTABLE_END
27aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch};
28aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch/* MODULE_DEVICE_TABLE(ssb, ssb_gige_tbl); */
29aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch
30aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch
31aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Bueschstatic inline u8 gige_read8(struct ssb_gige *dev, u16 offset)
32aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch{
33aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch	return ssb_read8(dev->dev, offset);
34aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch}
35aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch
36aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Bueschstatic inline u16 gige_read16(struct ssb_gige *dev, u16 offset)
37aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch{
38aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch	return ssb_read16(dev->dev, offset);
39aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch}
40aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch
41aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Bueschstatic inline u32 gige_read32(struct ssb_gige *dev, u16 offset)
42aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch{
43aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch	return ssb_read32(dev->dev, offset);
44aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch}
45aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch
46aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Bueschstatic inline void gige_write8(struct ssb_gige *dev,
47aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch			       u16 offset, u8 value)
48aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch{
49aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch	ssb_write8(dev->dev, offset, value);
50aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch}
51aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch
52aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Bueschstatic inline void gige_write16(struct ssb_gige *dev,
53aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch				u16 offset, u16 value)
54aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch{
55aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch	ssb_write16(dev->dev, offset, value);
56aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch}
57aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch
58aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Bueschstatic inline void gige_write32(struct ssb_gige *dev,
59aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch				u16 offset, u32 value)
60aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch{
61aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch	ssb_write32(dev->dev, offset, value);
62aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch}
63aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch
64aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Bueschstatic inline
65aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Bueschu8 gige_pcicfg_read8(struct ssb_gige *dev, unsigned int offset)
66aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch{
67aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch	BUG_ON(offset >= 256);
68aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch	return gige_read8(dev, SSB_GIGE_PCICFG + offset);
69aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch}
70aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch
71aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Bueschstatic inline
72aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Bueschu16 gige_pcicfg_read16(struct ssb_gige *dev, unsigned int offset)
73aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch{
74aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch	BUG_ON(offset >= 256);
75aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch	return gige_read16(dev, SSB_GIGE_PCICFG + offset);
76aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch}
77aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch
78aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Bueschstatic inline
79aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Bueschu32 gige_pcicfg_read32(struct ssb_gige *dev, unsigned int offset)
80aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch{
81aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch	BUG_ON(offset >= 256);
82aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch	return gige_read32(dev, SSB_GIGE_PCICFG + offset);
83aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch}
84aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch
85aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Bueschstatic inline
86aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Bueschvoid gige_pcicfg_write8(struct ssb_gige *dev,
87aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch			unsigned int offset, u8 value)
88aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch{
89aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch	BUG_ON(offset >= 256);
90aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch	gige_write8(dev, SSB_GIGE_PCICFG + offset, value);
91aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch}
92aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch
93aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Bueschstatic inline
94aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Bueschvoid gige_pcicfg_write16(struct ssb_gige *dev,
95aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch			 unsigned int offset, u16 value)
96aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch{
97aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch	BUG_ON(offset >= 256);
98aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch	gige_write16(dev, SSB_GIGE_PCICFG + offset, value);
99aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch}
100aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch
101aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Bueschstatic inline
102aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Bueschvoid gige_pcicfg_write32(struct ssb_gige *dev,
103aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch			 unsigned int offset, u32 value)
104aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch{
105aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch	BUG_ON(offset >= 256);
106aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch	gige_write32(dev, SSB_GIGE_PCICFG + offset, value);
107aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch}
108aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch
109cd15598707aff52da4302d9b6a3fc878bca27383Hauke Mehrtensstatic int __devinit ssb_gige_pci_read_config(struct pci_bus *bus,
110cd15598707aff52da4302d9b6a3fc878bca27383Hauke Mehrtens					      unsigned int devfn, int reg,
111cd15598707aff52da4302d9b6a3fc878bca27383Hauke Mehrtens					      int size, u32 *val)
112aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch{
113aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch	struct ssb_gige *dev = container_of(bus->ops, struct ssb_gige, pci_ops);
114aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch	unsigned long flags;
115aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch
116aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch	if ((PCI_SLOT(devfn) > 0) || (PCI_FUNC(devfn) > 0))
117aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch		return PCIBIOS_DEVICE_NOT_FOUND;
118aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch	if (reg >= 256)
119aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch		return PCIBIOS_DEVICE_NOT_FOUND;
120aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch
121aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch	spin_lock_irqsave(&dev->lock, flags);
122aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch	switch (size) {
123aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch	case 1:
124aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch		*val = gige_pcicfg_read8(dev, reg);
125aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch		break;
126aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch	case 2:
127aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch		*val = gige_pcicfg_read16(dev, reg);
128aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch		break;
129aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch	case 4:
130aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch		*val = gige_pcicfg_read32(dev, reg);
131aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch		break;
132aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch	default:
133aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch		WARN_ON(1);
134aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch	}
135aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch	spin_unlock_irqrestore(&dev->lock, flags);
136aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch
137aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch	return PCIBIOS_SUCCESSFUL;
138aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch}
139aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch
140cd15598707aff52da4302d9b6a3fc878bca27383Hauke Mehrtensstatic int __devinit ssb_gige_pci_write_config(struct pci_bus *bus,
141cd15598707aff52da4302d9b6a3fc878bca27383Hauke Mehrtens					       unsigned int devfn, int reg,
142cd15598707aff52da4302d9b6a3fc878bca27383Hauke Mehrtens					       int size, u32 val)
143aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch{
144aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch	struct ssb_gige *dev = container_of(bus->ops, struct ssb_gige, pci_ops);
145aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch	unsigned long flags;
146aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch
147aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch	if ((PCI_SLOT(devfn) > 0) || (PCI_FUNC(devfn) > 0))
148aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch		return PCIBIOS_DEVICE_NOT_FOUND;
149aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch	if (reg >= 256)
150aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch		return PCIBIOS_DEVICE_NOT_FOUND;
151aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch
152aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch	spin_lock_irqsave(&dev->lock, flags);
153aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch	switch (size) {
154aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch	case 1:
155aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch		gige_pcicfg_write8(dev, reg, val);
156aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch		break;
157aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch	case 2:
158aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch		gige_pcicfg_write16(dev, reg, val);
159aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch		break;
160aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch	case 4:
161aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch		gige_pcicfg_write32(dev, reg, val);
162aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch		break;
163aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch	default:
164aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch		WARN_ON(1);
165aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch	}
166aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch	spin_unlock_irqrestore(&dev->lock, flags);
167aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch
168aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch	return PCIBIOS_SUCCESSFUL;
169aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch}
170aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch
171cd15598707aff52da4302d9b6a3fc878bca27383Hauke Mehrtensstatic int __devinit ssb_gige_probe(struct ssb_device *sdev,
172cd15598707aff52da4302d9b6a3fc878bca27383Hauke Mehrtens				    const struct ssb_device_id *id)
173aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch{
174aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch	struct ssb_gige *dev;
175aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch	u32 base, tmslow, tmshigh;
176aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch
177aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
178aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch	if (!dev)
179aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch		return -ENOMEM;
180aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch	dev->dev = sdev;
181aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch
182aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch	spin_lock_init(&dev->lock);
183aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch	dev->pci_controller.pci_ops = &dev->pci_ops;
184aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch	dev->pci_controller.io_resource = &dev->io_resource;
185aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch	dev->pci_controller.mem_resource = &dev->mem_resource;
186aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch	dev->pci_controller.io_map_base = 0x800;
187aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch	dev->pci_ops.read = ssb_gige_pci_read_config;
188aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch	dev->pci_ops.write = ssb_gige_pci_write_config;
189aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch
190aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch	dev->io_resource.name = SSB_GIGE_IO_RES_NAME;
191aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch	dev->io_resource.start = 0x800;
192aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch	dev->io_resource.end = 0x8FF;
193aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch	dev->io_resource.flags = IORESOURCE_IO | IORESOURCE_PCI_FIXED;
194aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch
195aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch	if (!ssb_device_is_enabled(sdev))
196aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch		ssb_device_enable(sdev, 0);
197aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch
198aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch	/* Setup BAR0. This is a 64k MMIO region. */
199aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch	base = ssb_admatch_base(ssb_read32(sdev, SSB_ADMATCH1));
200aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch	gige_pcicfg_write32(dev, PCI_BASE_ADDRESS_0, base);
201aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch	gige_pcicfg_write32(dev, PCI_BASE_ADDRESS_1, 0);
202aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch
203aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch	dev->mem_resource.name = SSB_GIGE_MEM_RES_NAME;
204aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch	dev->mem_resource.start = base;
205aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch	dev->mem_resource.end = base + 0x10000 - 1;
206aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch	dev->mem_resource.flags = IORESOURCE_MEM | IORESOURCE_PCI_FIXED;
207aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch
208aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch	/* Enable the memory region. */
209aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch	gige_pcicfg_write16(dev, PCI_COMMAND,
210aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch			    gige_pcicfg_read16(dev, PCI_COMMAND)
211aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch			    | PCI_COMMAND_MEMORY);
212aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch
213aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch	/* Write flushing is controlled by the Flush Status Control register.
214aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch	 * We want to flush every register write with a timeout and we want
215aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch	 * to disable the IRQ mask while flushing to avoid concurrency.
216aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch	 * Note that automatic write flushing does _not_ work from
217aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch	 * an IRQ handler. The driver must flush manually by reading a register.
218aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch	 */
219aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch	gige_write32(dev, SSB_GIGE_SHIM_FLUSHSTAT, 0x00000068);
220aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch
221aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch	/* Check if we have an RGMII or GMII PHY-bus.
222aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch	 * On RGMII do not bypass the DLLs */
223aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch	tmslow = ssb_read32(sdev, SSB_TMSLOW);
224aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch	tmshigh = ssb_read32(sdev, SSB_TMSHIGH);
225aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch	if (tmshigh & SSB_GIGE_TMSHIGH_RGMII) {
226aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch		tmslow &= ~SSB_GIGE_TMSLOW_TXBYPASS;
227aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch		tmslow &= ~SSB_GIGE_TMSLOW_RXBYPASS;
228aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch		dev->has_rgmii = 1;
229aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch	} else {
230aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch		tmslow |= SSB_GIGE_TMSLOW_TXBYPASS;
231aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch		tmslow |= SSB_GIGE_TMSLOW_RXBYPASS;
232aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch		dev->has_rgmii = 0;
233aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch	}
234aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch	tmslow |= SSB_GIGE_TMSLOW_DLLEN;
235aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch	ssb_write32(sdev, SSB_TMSLOW, tmslow);
236aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch
237aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch	ssb_set_drvdata(sdev, dev);
238aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch	register_pci_controller(&dev->pci_controller);
239aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch
240aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch	return 0;
241aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch}
242aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch
243aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Bueschbool pdev_is_ssb_gige_core(struct pci_dev *pdev)
244aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch{
245aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch	if (!pdev->resource[0].name)
246aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch		return 0;
247aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch	return (strcmp(pdev->resource[0].name, SSB_GIGE_MEM_RES_NAME) == 0);
248aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch}
249aab547ce0d1493d400b6468c521a0137cd8c1edfMichael BueschEXPORT_SYMBOL(pdev_is_ssb_gige_core);
250aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch
251aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Bueschint ssb_gige_pcibios_plat_dev_init(struct ssb_device *sdev,
252aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch				   struct pci_dev *pdev)
253aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch{
254aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch	struct ssb_gige *dev = ssb_get_drvdata(sdev);
255aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch	struct resource *res;
256aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch
257aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch	if (pdev->bus->ops != &dev->pci_ops) {
258aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch		/* The PCI device is not on this SSB GigE bridge device. */
259aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch		return -ENODEV;
260aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch	}
261aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch
262aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch	/* Fixup the PCI resources. */
263aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch	res = &(pdev->resource[0]);
264aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch	res->flags = IORESOURCE_MEM | IORESOURCE_PCI_FIXED;
265aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch	res->name = dev->mem_resource.name;
266aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch	res->start = dev->mem_resource.start;
267aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch	res->end = dev->mem_resource.end;
268aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch
269aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch	/* Fixup interrupt lines. */
270aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch	pdev->irq = ssb_mips_irq(sdev) + 2;
271aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch	pci_write_config_byte(pdev, PCI_INTERRUPT_LINE, pdev->irq);
272aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch
273aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch	return 0;
274aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch}
275aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch
276aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Bueschint ssb_gige_map_irq(struct ssb_device *sdev,
277aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch		     const struct pci_dev *pdev)
278aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch{
279aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch	struct ssb_gige *dev = ssb_get_drvdata(sdev);
280aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch
281aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch	if (pdev->bus->ops != &dev->pci_ops) {
282aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch		/* The PCI device is not on this SSB GigE bridge device. */
283aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch		return -ENODEV;
284aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch	}
285aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch
286aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch	return ssb_mips_irq(sdev) + 2;
287aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch}
288aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch
289aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Bueschstatic struct ssb_driver ssb_gige_driver = {
290aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch	.name		= "BCM-GigE",
291aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch	.id_table	= ssb_gige_tbl,
292aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch	.probe		= ssb_gige_probe,
293aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch};
294aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch
295aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Bueschint ssb_gige_init(void)
296aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch{
297aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch	return ssb_driver_register(&ssb_gige_driver);
298aab547ce0d1493d400b6468c521a0137cd8c1edfMichael Buesch}
299