162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
262306a36Sopenharmony_ci#ifndef LINUX_SSB_DRIVER_GIGE_H_
362306a36Sopenharmony_ci#define LINUX_SSB_DRIVER_GIGE_H_
462306a36Sopenharmony_ci
562306a36Sopenharmony_ci#include <linux/ssb/ssb.h>
662306a36Sopenharmony_ci#include <linux/bug.h>
762306a36Sopenharmony_ci#include <linux/pci.h>
862306a36Sopenharmony_ci#include <linux/spinlock.h>
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ci
1162306a36Sopenharmony_ci#ifdef CONFIG_SSB_DRIVER_GIGE
1262306a36Sopenharmony_ci
1362306a36Sopenharmony_ci
1462306a36Sopenharmony_ci#define SSB_GIGE_PCIIO			0x0000 /* PCI I/O Registers (1024 bytes) */
1562306a36Sopenharmony_ci#define SSB_GIGE_RESERVED		0x0400 /* Reserved (1024 bytes) */
1662306a36Sopenharmony_ci#define SSB_GIGE_PCICFG			0x0800 /* PCI config space (256 bytes) */
1762306a36Sopenharmony_ci#define SSB_GIGE_SHIM_FLUSHSTAT		0x0C00 /* PCI to OCP: Flush status control (32bit) */
1862306a36Sopenharmony_ci#define SSB_GIGE_SHIM_FLUSHRDA		0x0C04 /* PCI to OCP: Flush read address (32bit) */
1962306a36Sopenharmony_ci#define SSB_GIGE_SHIM_FLUSHTO		0x0C08 /* PCI to OCP: Flush timeout counter (32bit) */
2062306a36Sopenharmony_ci#define SSB_GIGE_SHIM_BARRIER		0x0C0C /* PCI to OCP: Barrier register (32bit) */
2162306a36Sopenharmony_ci#define SSB_GIGE_SHIM_MAOCPSI		0x0C10 /* PCI to OCP: MaocpSI Control (32bit) */
2262306a36Sopenharmony_ci#define SSB_GIGE_SHIM_SIOCPMA		0x0C14 /* PCI to OCP: SiocpMa Control (32bit) */
2362306a36Sopenharmony_ci
2462306a36Sopenharmony_ci/* TM Status High flags */
2562306a36Sopenharmony_ci#define SSB_GIGE_TMSHIGH_RGMII		0x00010000 /* Have an RGMII PHY-bus */
2662306a36Sopenharmony_ci/* TM Status Low flags */
2762306a36Sopenharmony_ci#define SSB_GIGE_TMSLOW_TXBYPASS	0x00080000 /* TX bypass (no delay) */
2862306a36Sopenharmony_ci#define SSB_GIGE_TMSLOW_RXBYPASS	0x00100000 /* RX bypass (no delay) */
2962306a36Sopenharmony_ci#define SSB_GIGE_TMSLOW_DLLEN		0x01000000 /* Enable DLL controls */
3062306a36Sopenharmony_ci
3162306a36Sopenharmony_ci/* Boardflags (low) */
3262306a36Sopenharmony_ci#define SSB_GIGE_BFL_ROBOSWITCH		0x0010
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_ci#define SSB_GIGE_MEM_RES_NAME		"SSB Broadcom 47xx GigE memory"
3662306a36Sopenharmony_ci#define SSB_GIGE_IO_RES_NAME		"SSB Broadcom 47xx GigE I/O"
3762306a36Sopenharmony_ci
3862306a36Sopenharmony_cistruct ssb_gige {
3962306a36Sopenharmony_ci	struct ssb_device *dev;
4062306a36Sopenharmony_ci
4162306a36Sopenharmony_ci	spinlock_t lock;
4262306a36Sopenharmony_ci
4362306a36Sopenharmony_ci	/* True, if the device has an RGMII bus.
4462306a36Sopenharmony_ci	 * False, if the device has a GMII bus. */
4562306a36Sopenharmony_ci	bool has_rgmii;
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_ci	/* The PCI controller device. */
4862306a36Sopenharmony_ci	struct pci_controller pci_controller;
4962306a36Sopenharmony_ci	struct pci_ops pci_ops;
5062306a36Sopenharmony_ci	struct resource mem_resource;
5162306a36Sopenharmony_ci	struct resource io_resource;
5262306a36Sopenharmony_ci};
5362306a36Sopenharmony_ci
5462306a36Sopenharmony_ci/* Check whether a PCI device is a SSB Gigabit Ethernet core. */
5562306a36Sopenharmony_ciextern bool pdev_is_ssb_gige_core(struct pci_dev *pdev);
5662306a36Sopenharmony_ci
5762306a36Sopenharmony_ci/* Convert a pci_dev pointer to a ssb_gige pointer. */
5862306a36Sopenharmony_cistatic inline struct ssb_gige * pdev_to_ssb_gige(struct pci_dev *pdev)
5962306a36Sopenharmony_ci{
6062306a36Sopenharmony_ci	if (!pdev_is_ssb_gige_core(pdev))
6162306a36Sopenharmony_ci		return NULL;
6262306a36Sopenharmony_ci	return container_of(pdev->bus->ops, struct ssb_gige, pci_ops);
6362306a36Sopenharmony_ci}
6462306a36Sopenharmony_ci
6562306a36Sopenharmony_ci/* Returns whether the PHY is connected by an RGMII bus. */
6662306a36Sopenharmony_cistatic inline bool ssb_gige_is_rgmii(struct pci_dev *pdev)
6762306a36Sopenharmony_ci{
6862306a36Sopenharmony_ci	struct ssb_gige *dev = pdev_to_ssb_gige(pdev);
6962306a36Sopenharmony_ci	return (dev ? dev->has_rgmii : 0);
7062306a36Sopenharmony_ci}
7162306a36Sopenharmony_ci
7262306a36Sopenharmony_ci/* Returns whether we have a Roboswitch. */
7362306a36Sopenharmony_cistatic inline bool ssb_gige_have_roboswitch(struct pci_dev *pdev)
7462306a36Sopenharmony_ci{
7562306a36Sopenharmony_ci	struct ssb_gige *dev = pdev_to_ssb_gige(pdev);
7662306a36Sopenharmony_ci	if (dev)
7762306a36Sopenharmony_ci		return !!(dev->dev->bus->sprom.boardflags_lo &
7862306a36Sopenharmony_ci			  SSB_GIGE_BFL_ROBOSWITCH);
7962306a36Sopenharmony_ci	return false;
8062306a36Sopenharmony_ci}
8162306a36Sopenharmony_ci
8262306a36Sopenharmony_ci/* Returns whether we can only do one DMA at once. */
8362306a36Sopenharmony_cistatic inline bool ssb_gige_one_dma_at_once(struct pci_dev *pdev)
8462306a36Sopenharmony_ci{
8562306a36Sopenharmony_ci	struct ssb_gige *dev = pdev_to_ssb_gige(pdev);
8662306a36Sopenharmony_ci	if (dev)
8762306a36Sopenharmony_ci		return ((dev->dev->bus->chip_id == 0x4785) &&
8862306a36Sopenharmony_ci			(dev->dev->bus->chip_rev < 2));
8962306a36Sopenharmony_ci	return false;
9062306a36Sopenharmony_ci}
9162306a36Sopenharmony_ci
9262306a36Sopenharmony_ci/* Returns whether we must flush posted writes. */
9362306a36Sopenharmony_cistatic inline bool ssb_gige_must_flush_posted_writes(struct pci_dev *pdev)
9462306a36Sopenharmony_ci{
9562306a36Sopenharmony_ci	struct ssb_gige *dev = pdev_to_ssb_gige(pdev);
9662306a36Sopenharmony_ci	if (dev)
9762306a36Sopenharmony_ci		return (dev->dev->bus->chip_id == 0x4785);
9862306a36Sopenharmony_ci	return false;
9962306a36Sopenharmony_ci}
10062306a36Sopenharmony_ci
10162306a36Sopenharmony_ci/* Get the device MAC address */
10262306a36Sopenharmony_cistatic inline int ssb_gige_get_macaddr(struct pci_dev *pdev, u8 *macaddr)
10362306a36Sopenharmony_ci{
10462306a36Sopenharmony_ci	struct ssb_gige *dev = pdev_to_ssb_gige(pdev);
10562306a36Sopenharmony_ci	if (!dev)
10662306a36Sopenharmony_ci		return -ENODEV;
10762306a36Sopenharmony_ci
10862306a36Sopenharmony_ci	memcpy(macaddr, dev->dev->bus->sprom.et0mac, 6);
10962306a36Sopenharmony_ci	return 0;
11062306a36Sopenharmony_ci}
11162306a36Sopenharmony_ci
11262306a36Sopenharmony_ci/* Get the device phy address */
11362306a36Sopenharmony_cistatic inline int ssb_gige_get_phyaddr(struct pci_dev *pdev)
11462306a36Sopenharmony_ci{
11562306a36Sopenharmony_ci	struct ssb_gige *dev = pdev_to_ssb_gige(pdev);
11662306a36Sopenharmony_ci	if (!dev)
11762306a36Sopenharmony_ci		return -ENODEV;
11862306a36Sopenharmony_ci
11962306a36Sopenharmony_ci	return dev->dev->bus->sprom.et0phyaddr;
12062306a36Sopenharmony_ci}
12162306a36Sopenharmony_ci
12262306a36Sopenharmony_ciextern int ssb_gige_pcibios_plat_dev_init(struct ssb_device *sdev,
12362306a36Sopenharmony_ci					  struct pci_dev *pdev);
12462306a36Sopenharmony_ciextern int ssb_gige_map_irq(struct ssb_device *sdev,
12562306a36Sopenharmony_ci			    const struct pci_dev *pdev);
12662306a36Sopenharmony_ci
12762306a36Sopenharmony_ci/* The GigE driver is not a standalone module, because we don't have support
12862306a36Sopenharmony_ci * for unregistering the driver. So we could not unload the module anyway. */
12962306a36Sopenharmony_ciextern int ssb_gige_init(void);
13062306a36Sopenharmony_cistatic inline void ssb_gige_exit(void)
13162306a36Sopenharmony_ci{
13262306a36Sopenharmony_ci	/* Currently we can not unregister the GigE driver,
13362306a36Sopenharmony_ci	 * because we can not unregister the PCI bridge. */
13462306a36Sopenharmony_ci	BUG();
13562306a36Sopenharmony_ci}
13662306a36Sopenharmony_ci
13762306a36Sopenharmony_ci
13862306a36Sopenharmony_ci#else /* CONFIG_SSB_DRIVER_GIGE */
13962306a36Sopenharmony_ci/* Gigabit Ethernet driver disabled */
14062306a36Sopenharmony_ci
14162306a36Sopenharmony_ci
14262306a36Sopenharmony_cistatic inline int ssb_gige_pcibios_plat_dev_init(struct ssb_device *sdev,
14362306a36Sopenharmony_ci						 struct pci_dev *pdev)
14462306a36Sopenharmony_ci{
14562306a36Sopenharmony_ci	return -ENOSYS;
14662306a36Sopenharmony_ci}
14762306a36Sopenharmony_cistatic inline int ssb_gige_map_irq(struct ssb_device *sdev,
14862306a36Sopenharmony_ci				   const struct pci_dev *pdev)
14962306a36Sopenharmony_ci{
15062306a36Sopenharmony_ci	return -ENOSYS;
15162306a36Sopenharmony_ci}
15262306a36Sopenharmony_cistatic inline int ssb_gige_init(void)
15362306a36Sopenharmony_ci{
15462306a36Sopenharmony_ci	return 0;
15562306a36Sopenharmony_ci}
15662306a36Sopenharmony_cistatic inline void ssb_gige_exit(void)
15762306a36Sopenharmony_ci{
15862306a36Sopenharmony_ci}
15962306a36Sopenharmony_ci
16062306a36Sopenharmony_cistatic inline bool pdev_is_ssb_gige_core(struct pci_dev *pdev)
16162306a36Sopenharmony_ci{
16262306a36Sopenharmony_ci	return false;
16362306a36Sopenharmony_ci}
16462306a36Sopenharmony_cistatic inline struct ssb_gige * pdev_to_ssb_gige(struct pci_dev *pdev)
16562306a36Sopenharmony_ci{
16662306a36Sopenharmony_ci	return NULL;
16762306a36Sopenharmony_ci}
16862306a36Sopenharmony_cistatic inline bool ssb_gige_is_rgmii(struct pci_dev *pdev)
16962306a36Sopenharmony_ci{
17062306a36Sopenharmony_ci	return false;
17162306a36Sopenharmony_ci}
17262306a36Sopenharmony_cistatic inline bool ssb_gige_have_roboswitch(struct pci_dev *pdev)
17362306a36Sopenharmony_ci{
17462306a36Sopenharmony_ci	return false;
17562306a36Sopenharmony_ci}
17662306a36Sopenharmony_cistatic inline bool ssb_gige_one_dma_at_once(struct pci_dev *pdev)
17762306a36Sopenharmony_ci{
17862306a36Sopenharmony_ci	return false;
17962306a36Sopenharmony_ci}
18062306a36Sopenharmony_cistatic inline bool ssb_gige_must_flush_posted_writes(struct pci_dev *pdev)
18162306a36Sopenharmony_ci{
18262306a36Sopenharmony_ci	return false;
18362306a36Sopenharmony_ci}
18462306a36Sopenharmony_cistatic inline int ssb_gige_get_macaddr(struct pci_dev *pdev, u8 *macaddr)
18562306a36Sopenharmony_ci{
18662306a36Sopenharmony_ci	return -ENODEV;
18762306a36Sopenharmony_ci}
18862306a36Sopenharmony_cistatic inline int ssb_gige_get_phyaddr(struct pci_dev *pdev)
18962306a36Sopenharmony_ci{
19062306a36Sopenharmony_ci	return -ENODEV;
19162306a36Sopenharmony_ci}
19262306a36Sopenharmony_ci
19362306a36Sopenharmony_ci#endif /* CONFIG_SSB_DRIVER_GIGE */
19462306a36Sopenharmony_ci#endif /* LINUX_SSB_DRIVER_GIGE_H_ */
195