Skip to content
GitLab
Menu
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
xenomai
ipipe-x86
Commits
4b0d1a0b
Commit
4b0d1a0b
authored
Feb 21, 2012
by
David S. Miller
Browse files
Merge branch 'for-davem' of
git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next
parents
8de65c2a
a9802d43
Changes
141
Expand all
Hide whitespace changes
Inline
Side-by-side
Documentation/DocBook/80211.tmpl
View file @
4b0d1a0b
...
...
@@ -129,7 +129,6 @@
!Finclude/net/cfg80211.h cfg80211_pmksa
!Finclude/net/cfg80211.h cfg80211_send_rx_auth
!Finclude/net/cfg80211.h cfg80211_send_auth_timeout
!Finclude/net/cfg80211.h __cfg80211_auth_canceled
!Finclude/net/cfg80211.h cfg80211_send_rx_assoc
!Finclude/net/cfg80211.h cfg80211_send_assoc_timeout
!Finclude/net/cfg80211.h cfg80211_send_deauth
...
...
MAINTAINERS
View file @
4b0d1a0b
...
...
@@ -4914,8 +4914,6 @@ F: fs/ocfs2/
ORINOCO DRIVER
L: linux-wireless@vger.kernel.org
L: orinoco-users@lists.sourceforge.net
L: orinoco-devel@lists.sourceforge.net
W: http://linuxwireless.org/en/users/Drivers/orinoco
W: http://www.nongnu.org/orinoco/
S: Orphan
...
...
arch/mips/pci/pci-bcm47xx.c
View file @
4b0d1a0b
...
...
@@ -25,6 +25,7 @@
#include
<linux/types.h>
#include
<linux/pci.h>
#include
<linux/ssb/ssb.h>
#include
<linux/bcma/bcma.h>
#include
<bcm47xx.h>
int
__init
pcibios_map_irq
(
const
struct
pci_dev
*
dev
,
u8
slot
,
u8
pin
)
...
...
@@ -32,15 +33,12 @@ int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
return
0
;
}
int
pcibios_plat_dev_init
(
struct
pci_dev
*
dev
)
{
#ifdef CONFIG_BCM47XX_SSB
static
int
bcm47xx_pcibios_plat_dev_init_ssb
(
struct
pci_dev
*
dev
)
{
int
res
;
u8
slot
,
pin
;
if
(
bcm47xx_bus_type
!=
BCM47XX_BUS_TYPE_SSB
)
return
0
;
res
=
ssb_pcibios_plat_dev_init
(
dev
);
if
(
res
<
0
)
{
printk
(
KERN_ALERT
"PCI: Failed to init device %s
\n
"
,
...
...
@@ -60,6 +58,47 @@ int pcibios_plat_dev_init(struct pci_dev *dev)
}
dev
->
irq
=
res
;
return
0
;
}
#endif
#ifdef CONFIG_BCM47XX_BCMA
static
int
bcm47xx_pcibios_plat_dev_init_bcma
(
struct
pci_dev
*
dev
)
{
int
res
;
res
=
bcma_core_pci_plat_dev_init
(
dev
);
if
(
res
<
0
)
{
printk
(
KERN_ALERT
"PCI: Failed to init device %s
\n
"
,
pci_name
(
dev
));
return
res
;
}
res
=
bcma_core_pci_pcibios_map_irq
(
dev
);
/* IRQ-0 and IRQ-1 are software interrupts. */
if
(
res
<
2
)
{
printk
(
KERN_ALERT
"PCI: Failed to map IRQ of device %s
\n
"
,
pci_name
(
dev
));
return
res
;
}
dev
->
irq
=
res
;
return
0
;
}
#endif
int
pcibios_plat_dev_init
(
struct
pci_dev
*
dev
)
{
#ifdef CONFIG_BCM47XX_SSB
if
(
bcm47xx_bus_type
==
BCM47XX_BUS_TYPE_SSB
)
return
bcm47xx_pcibios_plat_dev_init_ssb
(
dev
);
else
#endif
#ifdef CONFIG_BCM47XX_BCMA
if
(
bcm47xx_bus_type
==
BCM47XX_BUS_TYPE_BCMA
)
return
bcm47xx_pcibios_plat_dev_init_bcma
(
dev
);
else
#endif
return
0
;
}
drivers/bcma/bcma_private.h
View file @
4b0d1a0b
...
...
@@ -13,7 +13,7 @@
struct
bcma_bus
;
/* main.c */
int
bcma_bus_register
(
struct
bcma_bus
*
bus
);
int
__devinit
bcma_bus_register
(
struct
bcma_bus
*
bus
);
void
bcma_bus_unregister
(
struct
bcma_bus
*
bus
);
int
__init
bcma_bus_early_register
(
struct
bcma_bus
*
bus
,
struct
bcma_device
*
core_cc
,
...
...
@@ -48,8 +48,12 @@ extern int __init bcma_host_pci_init(void);
extern
void
__exit
bcma_host_pci_exit
(
void
);
#endif
/* CONFIG_BCMA_HOST_PCI */
/* driver_pci.c */
u32
bcma_pcie_read
(
struct
bcma_drv_pci
*
pc
,
u32
address
);
#ifdef CONFIG_BCMA_DRIVER_PCI_HOSTMODE
void
bcma_core_pci_hostmode_init
(
struct
bcma_drv_pci
*
pc
);
bool
__devinit
bcma_core_pci_is_in_hostmode
(
struct
bcma_drv_pci
*
pc
);
void
__devinit
bcma_core_pci_hostmode_init
(
struct
bcma_drv_pci
*
pc
);
#endif
/* CONFIG_BCMA_DRIVER_PCI_HOSTMODE */
#endif
drivers/bcma/driver_pci.c
View file @
4b0d1a0b
...
...
@@ -2,8 +2,9 @@
* Broadcom specific AMBA
* PCI Core
*
* Copyright 2005, Broadcom Corporation
* Copyright 2005,
2011,
Broadcom Corporation
* Copyright 2006, 2007, Michael Buesch <m@bues.ch>
* Copyright 2011, 2012, Hauke Mehrtens <hauke@hauke-m.de>
*
* Licensed under the GNU/GPL. See COPYING for details.
*/
...
...
@@ -16,40 +17,41 @@
* R/W ops.
**************************************************/
static
u32
bcma_pcie_read
(
struct
bcma_drv_pci
*
pc
,
u32
address
)
u32
bcma_pcie_read
(
struct
bcma_drv_pci
*
pc
,
u32
address
)
{
pcicore_write32
(
pc
,
0x130
,
address
);
pcicore_read32
(
pc
,
0x130
);
return
pcicore_read32
(
pc
,
0x134
);
pcicore_write32
(
pc
,
BCMA_CORE_PCI_PCIEIND_ADDR
,
address
);
pcicore_read32
(
pc
,
BCMA_CORE_PCI_PCIEIND_ADDR
);
return
pcicore_read32
(
pc
,
BCMA_CORE_PCI_PCIEIND_DATA
);
}
#if 0
static void bcma_pcie_write(struct bcma_drv_pci *pc, u32 address, u32 data)
{
pcicore_write32(pc,
0x130
, address);
pcicore_read32(pc,
0x130
);
pcicore_write32(pc,
0x134
, data);
pcicore_write32(pc,
BCMA_CORE_PCI_PCIEIND_ADDR
, address);
pcicore_read32(pc,
BCMA_CORE_PCI_PCIEIND_ADDR
);
pcicore_write32(pc,
BCMA_CORE_PCI_PCIEIND_DATA
, data);
}
#endif
static
void
bcma_pcie_mdio_set_phy
(
struct
bcma_drv_pci
*
pc
,
u8
phy
)
{
const
u16
mdio_control
=
0x128
;
const
u16
mdio_data
=
0x12C
;
u32
v
;
int
i
;
v
=
(
1
<<
30
);
/* Start of Transaction */
v
|=
(
1
<<
28
);
/* Write Transaction */
v
|=
(
1
<<
17
);
/* Turnaround */
v
|=
(
0x1F
<<
18
);
v
=
BCMA_CORE_PCI_MDIODATA_START
;
v
|=
BCMA_CORE_PCI_MDIODATA_WRITE
;
v
|=
(
BCMA_CORE_PCI_MDIODATA_DEV_ADDR
<<
BCMA_CORE_PCI_MDIODATA_DEVADDR_SHF
);
v
|=
(
BCMA_CORE_PCI_MDIODATA_BLK_ADDR
<<
BCMA_CORE_PCI_MDIODATA_REGADDR_SHF
);
v
|=
BCMA_CORE_PCI_MDIODATA_TA
;
v
|=
(
phy
<<
4
);
pcicore_write32
(
pc
,
mdio_data
,
v
);
pcicore_write32
(
pc
,
BCMA_CORE_PCI_MDIO_DATA
,
v
);
udelay
(
10
);
for
(
i
=
0
;
i
<
200
;
i
++
)
{
v
=
pcicore_read32
(
pc
,
mdio_control
);
if
(
v
&
0x100
/* Trans complete */
)
v
=
pcicore_read32
(
pc
,
BCMA_CORE_PCI_MDIO_CONTROL
);
if
(
v
&
BCMA_CORE_PCI_MDIOCTL_ACCESS_DONE
)
break
;
msleep
(
1
);
}
...
...
@@ -57,79 +59,84 @@ static void bcma_pcie_mdio_set_phy(struct bcma_drv_pci *pc, u8 phy)
static
u16
bcma_pcie_mdio_read
(
struct
bcma_drv_pci
*
pc
,
u8
device
,
u8
address
)
{
const
u16
mdio_control
=
0x128
;
const
u16
mdio_data
=
0x12C
;
int
max_retries
=
10
;
u16
ret
=
0
;
u32
v
;
int
i
;
v
=
0x80
;
/* Enable Preamble Sequence */
v
|=
0x2
;
/* MDIO Clock Divisor */
pcicore_write32
(
pc
,
mdio_control
,
v
);
/* enable mdio access to SERDES */
v
=
BCMA_CORE_PCI_MDIOCTL_PREAM_EN
;
v
|=
BCMA_CORE_PCI_MDIOCTL_DIVISOR_VAL
;
pcicore_write32
(
pc
,
BCMA_CORE_PCI_MDIO_CONTROL
,
v
);
if
(
pc
->
core
->
id
.
rev
>=
10
)
{
max_retries
=
200
;
bcma_pcie_mdio_set_phy
(
pc
,
device
);
v
=
(
BCMA_CORE_PCI_MDIODATA_DEV_ADDR
<<
BCMA_CORE_PCI_MDIODATA_DEVADDR_SHF
);
v
|=
(
address
<<
BCMA_CORE_PCI_MDIODATA_REGADDR_SHF
);
}
else
{
v
=
(
device
<<
BCMA_CORE_PCI_MDIODATA_DEVADDR_SHF_OLD
);
v
|=
(
address
<<
BCMA_CORE_PCI_MDIODATA_REGADDR_SHF_OLD
);
}
v
=
(
1
<<
30
);
/* Start of Transaction */
v
|=
(
1
<<
29
);
/* Read Transaction */
v
|=
(
1
<<
17
);
/* Turnaround */
if
(
pc
->
core
->
id
.
rev
<
10
)
v
|=
(
u32
)
device
<<
22
;
v
|=
(
u32
)
address
<<
18
;
pcicore_write32
(
pc
,
mdio_data
,
v
);
v
=
BCMA_CORE_PCI_MDIODATA_START
;
v
|=
BCMA_CORE_PCI_MDIODATA_READ
;
v
|=
BCMA_CORE_PCI_MDIODATA_TA
;
pcicore_write32
(
pc
,
BCMA_CORE_PCI_MDIO_DATA
,
v
);
/* Wait for the device to complete the transaction */
udelay
(
10
);
for
(
i
=
0
;
i
<
max_retries
;
i
++
)
{
v
=
pcicore_read32
(
pc
,
mdio_control
);
if
(
v
&
0x100
/* Trans complete */
)
{
v
=
pcicore_read32
(
pc
,
BCMA_CORE_PCI_MDIO_CONTROL
);
if
(
v
&
BCMA_CORE_PCI_MDIOCTL_ACCESS_DONE
)
{
udelay
(
10
);
ret
=
pcicore_read32
(
pc
,
mdio_data
);
ret
=
pcicore_read32
(
pc
,
BCMA_CORE_PCI_MDIO_DATA
);
break
;
}
msleep
(
1
);
}
pcicore_write32
(
pc
,
mdio_control
,
0
);
pcicore_write32
(
pc
,
BCMA_CORE_PCI_MDIO_CONTROL
,
0
);
return
ret
;
}
static
void
bcma_pcie_mdio_write
(
struct
bcma_drv_pci
*
pc
,
u8
device
,
u8
address
,
u16
data
)
{
const
u16
mdio_control
=
0x128
;
const
u16
mdio_data
=
0x12C
;
int
max_retries
=
10
;
u32
v
;
int
i
;
v
=
0x80
;
/* Enable Preamble Sequence */
v
|=
0x2
;
/* MDIO Clock Divisor */
pcicore_write32
(
pc
,
mdio_control
,
v
);
/* enable mdio access to SERDES */
v
=
BCMA_CORE_PCI_MDIOCTL_PREAM_EN
;
v
|=
BCMA_CORE_PCI_MDIOCTL_DIVISOR_VAL
;
pcicore_write32
(
pc
,
BCMA_CORE_PCI_MDIO_CONTROL
,
v
);
if
(
pc
->
core
->
id
.
rev
>=
10
)
{
max_retries
=
200
;
bcma_pcie_mdio_set_phy
(
pc
,
device
);
v
=
(
BCMA_CORE_PCI_MDIODATA_DEV_ADDR
<<
BCMA_CORE_PCI_MDIODATA_DEVADDR_SHF
);
v
|=
(
address
<<
BCMA_CORE_PCI_MDIODATA_REGADDR_SHF
);
}
else
{
v
=
(
device
<<
BCMA_CORE_PCI_MDIODATA_DEVADDR_SHF_OLD
);
v
|=
(
address
<<
BCMA_CORE_PCI_MDIODATA_REGADDR_SHF_OLD
);
}
v
=
(
1
<<
30
);
/* Start of Transaction */
v
|=
(
1
<<
28
);
/* Write Transaction */
v
|=
(
1
<<
17
);
/* Turnaround */
if
(
pc
->
core
->
id
.
rev
<
10
)
v
|=
(
u32
)
device
<<
22
;
v
|=
(
u32
)
address
<<
18
;
v
=
BCMA_CORE_PCI_MDIODATA_START
;
v
|=
BCMA_CORE_PCI_MDIODATA_WRITE
;
v
|=
BCMA_CORE_PCI_MDIODATA_TA
;
v
|=
data
;
pcicore_write32
(
pc
,
mdio_data
,
v
);
pcicore_write32
(
pc
,
BCMA_CORE_PCI_MDIO_DATA
,
v
);
/* Wait for the device to complete the transaction */
udelay
(
10
);
for
(
i
=
0
;
i
<
max_retries
;
i
++
)
{
v
=
pcicore_read32
(
pc
,
mdio_control
);
if
(
v
&
0x100
/* Trans complete */
)
v
=
pcicore_read32
(
pc
,
BCMA_CORE_PCI_MDIO_CONTROL
);
if
(
v
&
BCMA_CORE_PCI_MDIOCTL_ACCESS_DONE
)
break
;
msleep
(
1
);
}
pcicore_write32
(
pc
,
mdio_control
,
0
);
pcicore_write32
(
pc
,
BCMA_CORE_PCI_MDIO_CONTROL
,
0
);
}
/**************************************************
...
...
@@ -138,72 +145,53 @@ static void bcma_pcie_mdio_write(struct bcma_drv_pci *pc, u8 device,
static
u8
bcma_pcicore_polarity_workaround
(
struct
bcma_drv_pci
*
pc
)
{
return
(
bcma_pcie_read
(
pc
,
0x204
)
&
0x10
)
?
0xC0
:
0x80
;
u32
tmp
;
tmp
=
bcma_pcie_read
(
pc
,
BCMA_CORE_PCI_PLP_STATUSREG
);
if
(
tmp
&
BCMA_CORE_PCI_PLP_POLARITYINV_STAT
)
return
BCMA_CORE_PCI_SERDES_RX_CTRL_FORCE
|
BCMA_CORE_PCI_SERDES_RX_CTRL_POLARITY
;
else
return
BCMA_CORE_PCI_SERDES_RX_CTRL_FORCE
;
}
static
void
bcma_pcicore_serdes_workaround
(
struct
bcma_drv_pci
*
pc
)
{
const
u8
serdes_pll_device
=
0x1D
;
const
u8
serdes_rx_device
=
0x1F
;
u16
tmp
;
bcma_pcie_mdio_write
(
pc
,
serdes_rx_device
,
1
/* Control */
,
bcma_pcicore_polarity_workaround
(
pc
));
tmp
=
bcma_pcie_mdio_read
(
pc
,
serdes_pll_device
,
1
/* Control */
);
if
(
tmp
&
0x4000
)
bcma_pcie_mdio_write
(
pc
,
serdes_pll_device
,
1
,
tmp
&
~
0x4000
);
bcma_pcie_mdio_write
(
pc
,
BCMA_CORE_PCI_MDIODATA_DEV_RX
,
BCMA_CORE_PCI_SERDES_RX_CTRL
,
bcma_pcicore_polarity_workaround
(
pc
));
tmp
=
bcma_pcie_mdio_read
(
pc
,
BCMA_CORE_PCI_MDIODATA_DEV_PLL
,
BCMA_CORE_PCI_SERDES_PLL_CTRL
);
if
(
tmp
&
BCMA_CORE_PCI_PLL_CTRL_FREQDET_EN
)
bcma_pcie_mdio_write
(
pc
,
BCMA_CORE_PCI_MDIODATA_DEV_PLL
,
BCMA_CORE_PCI_SERDES_PLL_CTRL
,
tmp
&
~
BCMA_CORE_PCI_PLL_CTRL_FREQDET_EN
);
}
/**************************************************
* Init.
**************************************************/
static
void
bcma_core_pci_clientmode_init
(
struct
bcma_drv_pci
*
pc
)
static
void
__devinit
bcma_core_pci_clientmode_init
(
struct
bcma_drv_pci
*
pc
)
{
bcma_pcicore_serdes_workaround
(
pc
);
}
static
bool
bcma_core_pci_is_in_hostmode
(
struct
bcma_drv_pci
*
pc
)
{
struct
bcma_bus
*
bus
=
pc
->
core
->
bus
;
u16
chipid_top
;
chipid_top
=
(
bus
->
chipinfo
.
id
&
0xFF00
);
if
(
chipid_top
!=
0x4700
&&
chipid_top
!=
0x5300
)
return
false
;
#ifdef CONFIG_SSB_DRIVER_PCICORE
if
(
bus
->
sprom
.
boardflags_lo
&
SSB_BFL_NOPCI
)
return
false
;
#endif
/* CONFIG_SSB_DRIVER_PCICORE */
#if 0
/* TODO: on BCMA we use address from EROM instead of magic formula */
u32 tmp;
return !mips_busprobe32(tmp, (bus->mmio +
(pc->core->core_index * BCMA_CORE_SIZE)));
#endif
return
true
;
}
void
bcma_core_pci_init
(
struct
bcma_drv_pci
*
pc
)
void
__devinit
bcma_core_pci_init
(
struct
bcma_drv_pci
*
pc
)
{
if
(
pc
->
setup_done
)
return
;
if
(
bcma_core_pci_is_in_hostmode
(
pc
))
{
#ifdef CONFIG_BCMA_DRIVER_PCI_HOSTMODE
pc
->
hostmode
=
bcma_core_pci_is_in_hostmode
(
pc
);
if
(
pc
->
hostmode
)
bcma_core_pci_hostmode_init
(
pc
);
#else
pr_err
(
"Driver compiled without support for hostmode PCI
\n
"
);
#endif
/* CONFIG_BCMA_DRIVER_PCI_HOSTMODE */
}
else
{
bcma_core_pci_clientmode_init
(
pc
);
}
pc
->
setup_done
=
true
;
if
(
!
pc
->
hostmode
)
bcma_core_pci_clientmode_init
(
pc
);
}
int
bcma_core_pci_irq_ctl
(
struct
bcma_drv_pci
*
pc
,
struct
bcma_device
*
core
,
...
...
drivers/bcma/driver_pci_host.c
View file @
4b0d1a0b
...
...
@@ -2,13 +2,587 @@
* Broadcom specific AMBA
* PCI Core in hostmode
*
* Copyright 2005 - 2011, Broadcom Corporation
* Copyright 2006, 2007, Michael Buesch <m@bues.ch>
* Copyright 2011, 2012, Hauke Mehrtens <hauke@hauke-m.de>
*
* Licensed under the GNU/GPL. See COPYING for details.
*/
#include
"bcma_private.h"
#include
<linux/export.h>
#include
<linux/bcma/bcma.h>
#include
<asm/paccess.h>
/* Probe a 32bit value on the bus and catch bus exceptions.
* Returns nonzero on a bus exception.
* This is MIPS specific */
#define mips_busprobe32(val, addr) get_dbe((val), ((u32 *)(addr)))
/* Assume one-hot slot wiring */
#define BCMA_PCI_SLOT_MAX 16
#define PCI_CONFIG_SPACE_SIZE 256
bool
__devinit
bcma_core_pci_is_in_hostmode
(
struct
bcma_drv_pci
*
pc
)
{
struct
bcma_bus
*
bus
=
pc
->
core
->
bus
;
u16
chipid_top
;
u32
tmp
;
chipid_top
=
(
bus
->
chipinfo
.
id
&
0xFF00
);
if
(
chipid_top
!=
0x4700
&&
chipid_top
!=
0x5300
)
return
false
;
if
(
bus
->
sprom
.
boardflags_lo
&
BCMA_CORE_PCI_BFL_NOPCI
)
{
pr_info
(
"This PCI core is disabled and not working
\n
"
);
return
false
;
}
bcma_core_enable
(
pc
->
core
,
0
);
return
!
mips_busprobe32
(
tmp
,
pc
->
core
->
io_addr
);
}
static
u32
bcma_pcie_read_config
(
struct
bcma_drv_pci
*
pc
,
u32
address
)
{
pcicore_write32
(
pc
,
BCMA_CORE_PCI_CONFIG_ADDR
,
address
);
pcicore_read32
(
pc
,
BCMA_CORE_PCI_CONFIG_ADDR
);
return
pcicore_read32
(
pc
,
BCMA_CORE_PCI_CONFIG_DATA
);
}
static
void
bcma_pcie_write_config
(
struct
bcma_drv_pci
*
pc
,
u32
address
,
u32
data
)
{
pcicore_write32
(
pc
,
BCMA_CORE_PCI_CONFIG_ADDR
,
address
);
pcicore_read32
(
pc
,
BCMA_CORE_PCI_CONFIG_ADDR
);
pcicore_write32
(
pc
,
BCMA_CORE_PCI_CONFIG_DATA
,
data
);
}
static
u32
bcma_get_cfgspace_addr
(
struct
bcma_drv_pci
*
pc
,
unsigned
int
dev
,
unsigned
int
func
,
unsigned
int
off
)
{
u32
addr
=
0
;
/* Issue config commands only when the data link is up (atleast
* one external pcie device is present).
*/
if
(
dev
>=
2
||
!
(
bcma_pcie_read
(
pc
,
BCMA_CORE_PCI_DLLP_LSREG
)
&
BCMA_CORE_PCI_DLLP_LSREG_LINKUP
))
goto
out
;
/* Type 0 transaction */
/* Slide the PCI window to the appropriate slot */
pcicore_write32
(
pc
,
BCMA_CORE_PCI_SBTOPCI1
,
BCMA_CORE_PCI_SBTOPCI_CFG0
);
/* Calculate the address */
addr
=
pc
->
host_controller
->
host_cfg_addr
;
addr
|=
(
dev
<<
BCMA_CORE_PCI_CFG_SLOT_SHIFT
);
addr
|=
(
func
<<
BCMA_CORE_PCI_CFG_FUN_SHIFT
);
addr
|=
(
off
&
~
3
);
out:
return
addr
;
}
void
bcma_core_pci_hostmode_init
(
struct
bcma_drv_pci
*
pc
)
static
int
bcma_extpci_read_config
(
struct
bcma_drv_pci
*
pc
,
unsigned
int
dev
,
unsigned
int
func
,
unsigned
int
off
,
void
*
buf
,
int
len
)
{
pr_err
(
"No support for PCI core in hostmode yet
\n
"
);
int
err
=
-
EINVAL
;
u32
addr
,
val
;
void
__iomem
*
mmio
=
0
;
WARN_ON
(
!
pc
->
hostmode
);
if
(
unlikely
(
len
!=
1
&&
len
!=
2
&&
len
!=
4
))
goto
out
;
if
(
dev
==
0
)
{
/* we support only two functions on device 0 */
if
(
func
>
1
)
return
-
EINVAL
;
/* accesses to config registers with offsets >= 256
* requires indirect access.
*/
if
(
off
>=
PCI_CONFIG_SPACE_SIZE
)
{
addr
=
(
func
<<
12
);
addr
|=
(
off
&
0x0FFF
);
val
=
bcma_pcie_read_config
(
pc
,
addr
);
}
else
{
addr
=
BCMA_CORE_PCI_PCICFG0
;
addr
|=
(
func
<<
8
);
addr
|=
(
off
&
0xfc
);
val
=
pcicore_read32
(
pc
,
addr
);
}
}
else
{
addr
=
bcma_get_cfgspace_addr
(
pc
,
dev
,
func
,
off
);
if
(
unlikely
(
!
addr
))
goto
out
;
err
=
-
ENOMEM
;
mmio
=
ioremap_nocache
(
addr
,
len
);
if
(
!
mmio
)
goto
out
;
if
(
mips_busprobe32
(
val
,
mmio
))
{
val
=
0xffffffff
;
goto
unmap
;
}
val
=
readl
(
mmio
);
}
val
>>=
(
8
*
(
off
&
3
));
switch
(
len
)
{
case
1
:
*
((
u8
*
)
buf
)
=
(
u8
)
val
;
break
;
case
2
:
*
((
u16
*
)
buf
)
=
(
u16
)
val
;
break
;
case
4
:
*
((
u32
*
)
buf
)
=
(
u32
)
val
;
break
;
}
err
=
0
;
unmap:
if
(
mmio
)
iounmap
(
mmio
);
out:
return
err
;
}
static
int
bcma_extpci_write_config
(
struct
bcma_drv_pci
*
pc
,
unsigned
int
dev
,
unsigned
int
func
,
unsigned
int
off
,
const
void
*
buf
,
int
len
)
{
int
err
=
-
EINVAL
;
u32
addr
=
0
,
val
=
0
;
void
__iomem
*
mmio
=
0
;
u16
chipid
=
pc
->
core
->
bus
->
chipinfo
.
id
;
WARN_ON
(
!
pc
->
hostmode
);
if
(
unlikely
(
len
!=
1
&&
len
!=
2
&&
len
!=
4
))
goto
out
;
if
(
dev
==
0
)
{
/* accesses to config registers with offsets >= 256
* requires indirect access.
*/
if
(
off
<
PCI_CONFIG_SPACE_SIZE
)
{
addr
=
pc
->
core
->
addr
+
BCMA_CORE_PCI_PCICFG0
;
addr
|=
(
func
<<
8
);
addr
|=
(
off
&
0xfc
);
mmio
=
ioremap_nocache
(
addr
,
len
);
if
(
!
mmio
)
goto
out
;
}
}
else
{
addr
=
bcma_get_cfgspace_addr
(
pc
,
dev
,
func
,
off
);
if
(
unlikely
(
!
addr
))
goto
out
;
err
=
-
ENOMEM
;
mmio
=
ioremap_nocache
(
addr
,
len
);
if
(
!
mmio
)
goto
out
;
if
(
mips_busprobe32
(
val
,
mmio
))
{
val
=
0xffffffff
;
goto
unmap
;
}
}
switch
(
len
)
{
case
1
:
val
=
readl
(
mmio
);
val
&=
~
(
0xFF
<<
(
8
*
(
off
&
3
)));
val
|=
*
((
const
u8
*
)
buf
)
<<
(
8
*
(
off
&
3
));
break
;
case
2
:
val
=
readl
(
mmio
);
val
&=
~
(
0xFFFF
<<
(
8
*
(
off
&
3
)));
val
|=
*
((
const
u16
*
)
buf
)
<<
(
8
*
(
off
&
3
));
break
;
case
4
:
val
=
*
((
const
u32
*
)
buf
);
break
;
}
if
(
dev
==
0
&&
!
addr
)
{
/* accesses to config registers with offsets >= 256
* requires indirect access.
*/
addr
=
(
func
<<
12
);
addr
|=
(
off
&
0x0FFF
);
bcma_pcie_write_config
(
pc
,
addr
,
val
);
}
else
{
writel
(
val
,
mmio
);
if
(
chipid
==
0x4716
||
chipid
==
0x4748
)
readl
(
mmio
);
}
err
=
0
;
unmap:
if
(
mmio
)
iounmap
(
mmio
);