2 * Broadcom specific AMBA
5 * Copyright 2005, 2011, Broadcom Corporation
6 * Copyright 2006, 2007, Michael Buesch <m@bues.ch>
7 * Copyright 2011, 2012, Hauke Mehrtens <hauke@hauke-m.de>
9 * Licensed under the GNU/GPL. See COPYING for details.
12 #include "bcma_private.h"
13 #include <linux/export.h>
14 #include <linux/bcma/bcma.h>
16 /**************************************************
18 **************************************************/
20 u32
bcma_pcie_read(struct bcma_drv_pci
*pc
, u32 address
)
22 pcicore_write32(pc
, BCMA_CORE_PCI_PCIEIND_ADDR
, address
);
23 pcicore_read32(pc
, BCMA_CORE_PCI_PCIEIND_ADDR
);
24 return pcicore_read32(pc
, BCMA_CORE_PCI_PCIEIND_DATA
);
28 static void bcma_pcie_write(struct bcma_drv_pci
*pc
, u32 address
, u32 data
)
30 pcicore_write32(pc
, BCMA_CORE_PCI_PCIEIND_ADDR
, address
);
31 pcicore_read32(pc
, BCMA_CORE_PCI_PCIEIND_ADDR
);
32 pcicore_write32(pc
, BCMA_CORE_PCI_PCIEIND_DATA
, data
);
36 static void bcma_pcie_mdio_set_phy(struct bcma_drv_pci
*pc
, u8 phy
)
41 v
= BCMA_CORE_PCI_MDIODATA_START
;
42 v
|= BCMA_CORE_PCI_MDIODATA_WRITE
;
43 v
|= (BCMA_CORE_PCI_MDIODATA_DEV_ADDR
<<
44 BCMA_CORE_PCI_MDIODATA_DEVADDR_SHF
);
45 v
|= (BCMA_CORE_PCI_MDIODATA_BLK_ADDR
<<
46 BCMA_CORE_PCI_MDIODATA_REGADDR_SHF
);
47 v
|= BCMA_CORE_PCI_MDIODATA_TA
;
49 pcicore_write32(pc
, BCMA_CORE_PCI_MDIO_DATA
, v
);
52 for (i
= 0; i
< 200; i
++) {
53 v
= pcicore_read32(pc
, BCMA_CORE_PCI_MDIO_CONTROL
);
54 if (v
& BCMA_CORE_PCI_MDIOCTL_ACCESS_DONE
)
60 static u16
bcma_pcie_mdio_read(struct bcma_drv_pci
*pc
, u8 device
, u8 address
)
67 /* enable mdio access to SERDES */
68 v
= BCMA_CORE_PCI_MDIOCTL_PREAM_EN
;
69 v
|= BCMA_CORE_PCI_MDIOCTL_DIVISOR_VAL
;
70 pcicore_write32(pc
, BCMA_CORE_PCI_MDIO_CONTROL
, v
);
72 if (pc
->core
->id
.rev
>= 10) {
74 bcma_pcie_mdio_set_phy(pc
, device
);
75 v
= (BCMA_CORE_PCI_MDIODATA_DEV_ADDR
<<
76 BCMA_CORE_PCI_MDIODATA_DEVADDR_SHF
);
77 v
|= (address
<< BCMA_CORE_PCI_MDIODATA_REGADDR_SHF
);
79 v
= (device
<< BCMA_CORE_PCI_MDIODATA_DEVADDR_SHF_OLD
);
80 v
|= (address
<< BCMA_CORE_PCI_MDIODATA_REGADDR_SHF_OLD
);
83 v
= BCMA_CORE_PCI_MDIODATA_START
;
84 v
|= BCMA_CORE_PCI_MDIODATA_READ
;
85 v
|= BCMA_CORE_PCI_MDIODATA_TA
;
87 pcicore_write32(pc
, BCMA_CORE_PCI_MDIO_DATA
, v
);
88 /* Wait for the device to complete the transaction */
90 for (i
= 0; i
< max_retries
; i
++) {
91 v
= pcicore_read32(pc
, BCMA_CORE_PCI_MDIO_CONTROL
);
92 if (v
& BCMA_CORE_PCI_MDIOCTL_ACCESS_DONE
) {
94 ret
= pcicore_read32(pc
, BCMA_CORE_PCI_MDIO_DATA
);
99 pcicore_write32(pc
, BCMA_CORE_PCI_MDIO_CONTROL
, 0);
103 static void bcma_pcie_mdio_write(struct bcma_drv_pci
*pc
, u8 device
,
104 u8 address
, u16 data
)
106 int max_retries
= 10;
110 /* enable mdio access to SERDES */
111 v
= BCMA_CORE_PCI_MDIOCTL_PREAM_EN
;
112 v
|= BCMA_CORE_PCI_MDIOCTL_DIVISOR_VAL
;
113 pcicore_write32(pc
, BCMA_CORE_PCI_MDIO_CONTROL
, v
);
115 if (pc
->core
->id
.rev
>= 10) {
117 bcma_pcie_mdio_set_phy(pc
, device
);
118 v
= (BCMA_CORE_PCI_MDIODATA_DEV_ADDR
<<
119 BCMA_CORE_PCI_MDIODATA_DEVADDR_SHF
);
120 v
|= (address
<< BCMA_CORE_PCI_MDIODATA_REGADDR_SHF
);
122 v
= (device
<< BCMA_CORE_PCI_MDIODATA_DEVADDR_SHF_OLD
);
123 v
|= (address
<< BCMA_CORE_PCI_MDIODATA_REGADDR_SHF_OLD
);
126 v
= BCMA_CORE_PCI_MDIODATA_START
;
127 v
|= BCMA_CORE_PCI_MDIODATA_WRITE
;
128 v
|= BCMA_CORE_PCI_MDIODATA_TA
;
130 pcicore_write32(pc
, BCMA_CORE_PCI_MDIO_DATA
, v
);
131 /* Wait for the device to complete the transaction */
133 for (i
= 0; i
< max_retries
; i
++) {
134 v
= pcicore_read32(pc
, BCMA_CORE_PCI_MDIO_CONTROL
);
135 if (v
& BCMA_CORE_PCI_MDIOCTL_ACCESS_DONE
)
139 pcicore_write32(pc
, BCMA_CORE_PCI_MDIO_CONTROL
, 0);
142 /**************************************************
144 **************************************************/
146 static u8
bcma_pcicore_polarity_workaround(struct bcma_drv_pci
*pc
)
150 tmp
= bcma_pcie_read(pc
, BCMA_CORE_PCI_PLP_STATUSREG
);
151 if (tmp
& BCMA_CORE_PCI_PLP_POLARITYINV_STAT
)
152 return BCMA_CORE_PCI_SERDES_RX_CTRL_FORCE
|
153 BCMA_CORE_PCI_SERDES_RX_CTRL_POLARITY
;
155 return BCMA_CORE_PCI_SERDES_RX_CTRL_FORCE
;
158 static void bcma_pcicore_serdes_workaround(struct bcma_drv_pci
*pc
)
162 bcma_pcie_mdio_write(pc
, BCMA_CORE_PCI_MDIODATA_DEV_RX
,
163 BCMA_CORE_PCI_SERDES_RX_CTRL
,
164 bcma_pcicore_polarity_workaround(pc
));
165 tmp
= bcma_pcie_mdio_read(pc
, BCMA_CORE_PCI_MDIODATA_DEV_PLL
,
166 BCMA_CORE_PCI_SERDES_PLL_CTRL
);
167 if (tmp
& BCMA_CORE_PCI_PLL_CTRL_FREQDET_EN
)
168 bcma_pcie_mdio_write(pc
, BCMA_CORE_PCI_MDIODATA_DEV_PLL
,
169 BCMA_CORE_PCI_SERDES_PLL_CTRL
,
170 tmp
& ~BCMA_CORE_PCI_PLL_CTRL_FREQDET_EN
);
173 /**************************************************
175 **************************************************/
177 static void __devinit
bcma_core_pci_clientmode_init(struct bcma_drv_pci
*pc
)
179 bcma_pcicore_serdes_workaround(pc
);
182 void __devinit
bcma_core_pci_init(struct bcma_drv_pci
*pc
)
187 #ifdef CONFIG_BCMA_DRIVER_PCI_HOSTMODE
188 pc
->hostmode
= bcma_core_pci_is_in_hostmode(pc
);
190 bcma_core_pci_hostmode_init(pc
);
191 #endif /* CONFIG_BCMA_DRIVER_PCI_HOSTMODE */
194 bcma_core_pci_clientmode_init(pc
);
197 int bcma_core_pci_irq_ctl(struct bcma_drv_pci
*pc
, struct bcma_device
*core
,
200 struct pci_dev
*pdev
= pc
->core
->bus
->host_pci
;
204 if (core
->bus
->hosttype
!= BCMA_HOSTTYPE_PCI
) {
205 /* This bcma device is not on a PCI host-bus. So the IRQs are
206 * not routed through the PCI core.
207 * So we must not enable routing through the PCI core. */
211 err
= pci_read_config_dword(pdev
, BCMA_PCI_IRQMASK
, &tmp
);
215 coremask
= BIT(core
->core_index
) << 8;
221 err
= pci_write_config_dword(pdev
, BCMA_PCI_IRQMASK
, tmp
);
226 EXPORT_SYMBOL_GPL(bcma_core_pci_irq_ctl
);