mirror of
git://projects.qi-hardware.com/openwrt-xburst.git
synced 2024-09-04 01:41:30 +03:00
atheros: USB support
git-svn-id: svn://svn.openwrt.org/openwrt/trunk@11113 3c298f89-4303-0410-b956-a3cf2f4a3e73
This commit is contained in:
parent
10a828fab0
commit
541ff27cfb
@ -9,9 +9,9 @@ include $(TOPDIR)/rules.mk
|
||||
ARCH:=mips
|
||||
BOARD:=atheros
|
||||
BOARDNAME:=Atheros 231x/5312
|
||||
FEATURES:=squashfs jffs2
|
||||
FEATURES:=squashfs jffs2 pci usb
|
||||
|
||||
LINUX_VERSION:=2.6.23.16
|
||||
LINUX_VERSION:=2.6.25.1
|
||||
|
||||
include $(INCLUDE_DIR)/target.mk
|
||||
|
||||
|
@ -10,8 +10,11 @@ CONFIG_ARCH_SUSPEND_POSSIBLE=y
|
||||
CONFIG_ATHEROS=y
|
||||
CONFIG_ATHEROS_AR5312=y
|
||||
CONFIG_ATHEROS_AR5315=y
|
||||
CONFIG_ATHEROS_AR5315_PCI=y
|
||||
# CONFIG_ATM is not set
|
||||
# CONFIG_ATMEL is not set
|
||||
CONFIG_BASE_SMALL=0
|
||||
# CONFIG_BCM43XX is not set
|
||||
# CONFIG_BCM47XX is not set
|
||||
CONFIG_BITREVERSE=y
|
||||
# CONFIG_BROADCOM_PHY is not set
|
||||
@ -52,6 +55,7 @@ CONFIG_CRYPTO_AEAD=m
|
||||
CONFIG_CRYPTO_AUTHENC=m
|
||||
CONFIG_CRYPTO_GF128MUL=m
|
||||
CONFIG_CSRC_R4K=y
|
||||
CONFIG_DEVPORT=y
|
||||
# CONFIG_DM9000 is not set
|
||||
CONFIG_DMA_NEED_PCI_MAP_STATE=y
|
||||
CONFIG_DMA_NONCOHERENT=y
|
||||
@ -71,7 +75,9 @@ CONFIG_HAVE_IDE=y
|
||||
# CONFIG_HAVE_KPROBES is not set
|
||||
# CONFIG_HAVE_KRETPROBES is not set
|
||||
CONFIG_HAVE_OPROFILE=y
|
||||
# CONFIG_HERMES is not set
|
||||
# CONFIG_HOSTAP is not set
|
||||
CONFIG_HW_HAS_PCI=y
|
||||
CONFIG_HW_RANDOM=y
|
||||
# CONFIG_I2C is not set
|
||||
# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
|
||||
@ -80,8 +86,9 @@ CONFIG_HW_RANDOM=y
|
||||
# CONFIG_IBM_NEW_EMAC_ZMII is not set
|
||||
CONFIG_ICPLUS_PHY=y
|
||||
# CONFIG_IDE is not set
|
||||
# CONFIG_IEEE80211 is not set
|
||||
CONFIG_INITRAMFS_SOURCE=""
|
||||
# CONFIG_IPW2100 is not set
|
||||
# CONFIG_IPW2200 is not set
|
||||
CONFIG_IRQ_CPU=y
|
||||
# CONFIG_LEDS_ALIX is not set
|
||||
# CONFIG_LEDS_GPIO is not set
|
||||
@ -94,6 +101,7 @@ CONFIG_LZO_DECOMPRESS=m
|
||||
# CONFIG_MACH_VR41XX is not set
|
||||
# CONFIG_MDIO_BITBANG is not set
|
||||
# CONFIG_MEMSTICK is not set
|
||||
CONFIG_MII=m
|
||||
CONFIG_MIPS=y
|
||||
# CONFIG_MIPS_ATLAS is not set
|
||||
# CONFIG_MIPS_COBALT is not set
|
||||
@ -143,12 +151,14 @@ CONFIG_MTD_MAP_BANK_WIDTH_4=y
|
||||
# CONFIG_MTD_ONENAND is not set
|
||||
# CONFIG_MTD_OTP is not set
|
||||
CONFIG_MTD_PARTITIONS=y
|
||||
# CONFIG_MTD_PCI is not set
|
||||
# CONFIG_MTD_PHRAM is not set
|
||||
CONFIG_MTD_PHYSMAP=y
|
||||
CONFIG_MTD_PHYSMAP_BANKWIDTH=0
|
||||
CONFIG_MTD_PHYSMAP_LEN=0x0
|
||||
CONFIG_MTD_PHYSMAP_START=0x0
|
||||
# CONFIG_MTD_PLATRAM is not set
|
||||
# CONFIG_MTD_PMC551 is not set
|
||||
# CONFIG_MTD_RAM is not set
|
||||
CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-3
|
||||
CONFIG_MTD_REDBOOT_PARTS=y
|
||||
@ -156,17 +166,23 @@ CONFIG_MTD_REDBOOT_PARTS_READONLY=y
|
||||
# CONFIG_MTD_ROM is not set
|
||||
# CONFIG_MTD_SLRAM is not set
|
||||
CONFIG_MTD_SPIFLASH=y
|
||||
# CONFIG_NET_PCI is not set
|
||||
# CONFIG_NET_VENDOR_3COM is not set
|
||||
CONFIG_NEW_GPIO=y
|
||||
# CONFIG_NO_IOPORT is not set
|
||||
# CONFIG_PAGE_SIZE_16KB is not set
|
||||
CONFIG_PAGE_SIZE_4KB=y
|
||||
# CONFIG_PAGE_SIZE_64KB is not set
|
||||
# CONFIG_PAGE_SIZE_8KB is not set
|
||||
CONFIG_PCI=y
|
||||
# CONFIG_PCIPCWATCHDOG is not set
|
||||
CONFIG_PCI_DOMAINS=y
|
||||
CONFIG_PHYLIB=y
|
||||
# CONFIG_PMC_MSP is not set
|
||||
# CONFIG_PMC_YOSEMITE is not set
|
||||
# CONFIG_PNX8550_JBS is not set
|
||||
# CONFIG_PNX8550_STB810 is not set
|
||||
# CONFIG_PRISM54 is not set
|
||||
# CONFIG_QSEMI_PHY is not set
|
||||
# CONFIG_REALTEK_PHY is not set
|
||||
# CONFIG_RTC is not set
|
||||
@ -206,9 +222,11 @@ CONFIG_TICK_ONESHOT=y
|
||||
# CONFIG_TOSHIBA_RBTX4927 is not set
|
||||
# CONFIG_TOSHIBA_RBTX4938 is not set
|
||||
CONFIG_TRAD_SIGNALS=y
|
||||
# CONFIG_USB_ARCH_HAS_EHCI is not set
|
||||
# CONFIG_USB_ARCH_HAS_HCD is not set
|
||||
# CONFIG_USB_ARCH_HAS_OHCI is not set
|
||||
CONFIG_USB=m
|
||||
# CONFIG_USBPCWATCHDOG is not set
|
||||
# CONFIG_USB_EHCI_HCD is not set
|
||||
# CONFIG_USB_R8A66597_HCD is not set
|
||||
# CONFIG_USB_UHCI_HCD is not set
|
||||
# CONFIG_VGASTATE is not set
|
||||
CONFIG_VIDEO_V4L2_COMMON=m
|
||||
CONFIG_ZONE_DMA_FLAG=0
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
config ATHEROS_AR5312
|
||||
bool "Atheros 5312/2312+ support"
|
||||
depends on ATHEROS
|
||||
@ -7,7 +6,22 @@ config ATHEROS_AR5312
|
||||
config ATHEROS_AR5315
|
||||
bool "Atheros 5315/2315+ support"
|
||||
depends on ATHEROS
|
||||
select DMA_NONCOHERENT
|
||||
select CEVT_R4K
|
||||
select CSRC_R4K
|
||||
select IRQ_CPU
|
||||
select SYS_HAS_CPU_MIPS32_R1
|
||||
select SYS_SUPPORTS_32BIT_KERNEL
|
||||
select SYS_SUPPORTS_BIG_ENDIAN
|
||||
select GENERIC_GPIO
|
||||
default y
|
||||
|
||||
|
||||
|
||||
config ATHEROS_AR5315_PCI
|
||||
bool "PCI support"
|
||||
select HW_HAS_PCI
|
||||
select PCI
|
||||
select USB_ARCH_HAS_HCD
|
||||
select USB_ARCH_HAS_OHCI
|
||||
select USB_ARCH_HAS_EHCI
|
||||
depends on ATHEROS_AR5315
|
||||
default n
|
||||
|
@ -9,3 +9,4 @@
|
||||
#
|
||||
|
||||
obj-y := board.o irq.o
|
||||
obj-$(CONFIG_ATHEROS_AR5315_PCI) += pci.o
|
||||
|
@ -60,6 +60,10 @@ asmlinkage void ar5315_irq_dispatch(void)
|
||||
do_IRQ(AR5315_IRQ_WLAN0_INTRS);
|
||||
else if (pending & CAUSEF_IP4)
|
||||
do_IRQ(AR5315_IRQ_ENET0_INTRS);
|
||||
#ifdef CONFIG_PCI
|
||||
else if (pending & CAUSEF_IP5)
|
||||
ar5315_pci_irq(AR5315_IRQ_LCBUS_PCI);
|
||||
#endif
|
||||
else if (pending & CAUSEF_IP2) {
|
||||
unsigned int ar531x_misc_intrs = sysRegRead(AR5315_ISR) & sysRegRead(AR5315_IMR);
|
||||
|
||||
@ -81,6 +85,30 @@ asmlinkage void ar5315_irq_dispatch(void)
|
||||
do_IRQ(AR531X_IRQ_CPU_CLOCK);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PCI
|
||||
static inline void pci_abort_irq(void)
|
||||
{
|
||||
sysRegWrite(AR5315_PCI_INT_STATUS, AR5315_PCI_ABORT_INT);
|
||||
(void)sysRegRead(AR5315_PCI_INT_STATUS); /* flush write to hardware */
|
||||
}
|
||||
|
||||
static inline void pci_ack_irq(void)
|
||||
{
|
||||
sysRegWrite(AR5315_PCI_INT_STATUS, AR5315_PCI_EXT_INT);
|
||||
(void)sysRegRead(AR5315_PCI_INT_STATUS); /* flush write to hardware */
|
||||
}
|
||||
|
||||
void ar5315_pci_irq(int irq)
|
||||
{
|
||||
if (sysRegRead(AR5315_PCI_INT_STATUS) == AR5315_PCI_ABORT_INT)
|
||||
pci_abort_irq();
|
||||
else {
|
||||
do_IRQ(irq);
|
||||
pci_ack_irq();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static void ar5315_gpio_intr_enable(unsigned int irq)
|
||||
{
|
||||
u32 gpio, mask;
|
||||
|
253
target/linux/atheros/files/arch/mips/atheros/ar5315/pci.c
Normal file
253
target/linux/atheros/files/arch/mips/atheros/ar5315/pci.c
Normal file
@ -0,0 +1,253 @@
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/irq.h>
|
||||
#include <asm/paccess.h>
|
||||
#include <asm/irq_cpu.h>
|
||||
#include <asm/io.h>
|
||||
#include "ar531x.h"
|
||||
|
||||
#define AR531X_MEM_BASE 0x80800000UL
|
||||
#define AR531X_MEM_SIZE 0x00ffffffUL
|
||||
#define AR531X_IO_SIZE 0x00007fffUL
|
||||
|
||||
#define IDSEL_SHIFT 13
|
||||
|
||||
static spinlock_t ar531x_pci_lock = SPIN_LOCK_UNLOCKED;
|
||||
static u32 cfgaddr;
|
||||
|
||||
static int config_access(int busno, int dev, int func, int where, int size, u32 ptr, int write)
|
||||
{
|
||||
u32 address; /* Address to read from */
|
||||
u32 reg;
|
||||
unsigned long flags;
|
||||
int ret = -1;
|
||||
|
||||
if ((busno != 0) || (dev > 3) || (func > 2))
|
||||
return ret;
|
||||
|
||||
spin_lock_irqsave(&ar531x_pci_lock, flags);
|
||||
|
||||
/* Select Configuration access */
|
||||
reg = sysRegRead(AR5315_PCI_MISC_CONFIG);
|
||||
reg |= AR5315_PCIMISC_CFG_SEL;
|
||||
sysRegWrite(AR5315_PCI_MISC_CONFIG, reg);
|
||||
(void)sysRegRead(AR5315_PCI_MISC_CONFIG);
|
||||
|
||||
address = (u32)cfgaddr + (1 << (IDSEL_SHIFT + dev)) + (func << 8) + where;
|
||||
|
||||
if (size == 1)
|
||||
address ^= 0x3;
|
||||
else if (size == 2)
|
||||
address ^= 0x2;
|
||||
|
||||
if (write) {
|
||||
if (size == 1)
|
||||
ret = put_dbe(ptr, (u8 *) address);
|
||||
else if (size == 2)
|
||||
ret = put_dbe(ptr, (u16 *) address);
|
||||
else if (size == 4)
|
||||
ret = put_dbe(ptr, (u32 *) address);
|
||||
} else {
|
||||
if (size == 1)
|
||||
ret = get_dbe(*((u32 *)ptr), (u8 *) address);
|
||||
else if (size == 2)
|
||||
ret = get_dbe(*((u32 *)ptr), (u16 *) address);
|
||||
else if (size == 4)
|
||||
ret = get_dbe(*((u32 *)ptr), (u32 *) address);
|
||||
}
|
||||
|
||||
/* Select Memory access */
|
||||
reg = sysRegRead(AR5315_PCI_MISC_CONFIG);
|
||||
reg &= ~AR5315_PCIMISC_CFG_SEL;
|
||||
sysRegWrite(AR5315_PCI_MISC_CONFIG, reg);
|
||||
(void)sysRegRead(AR5315_PCI_MISC_CONFIG);
|
||||
|
||||
spin_unlock_irqrestore(&ar531x_pci_lock, flags);
|
||||
|
||||
if (ret) {
|
||||
*((u32 *)ptr) = 0xffffffff;
|
||||
return PCIBIOS_DEVICE_NOT_FOUND;
|
||||
}
|
||||
|
||||
return PCIBIOS_SUCCESSFUL;
|
||||
}
|
||||
|
||||
static int ar531x_pci_read(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 * value)
|
||||
{
|
||||
return config_access(bus->number, PCI_SLOT(devfn), PCI_FUNC(devfn), where, size, (u32) value, 0);
|
||||
}
|
||||
|
||||
static int ar531x_pci_write(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 value)
|
||||
{
|
||||
return config_access(bus->number, PCI_SLOT(devfn), PCI_FUNC(devfn), where, size, value, 1);
|
||||
}
|
||||
|
||||
struct pci_ops ar531x_pci_ops = {
|
||||
.read = ar531x_pci_read,
|
||||
.write = ar531x_pci_write,
|
||||
};
|
||||
|
||||
static struct resource ar531x_mem_resource = {
|
||||
.name = "AR531x PCI MEM",
|
||||
.start = AR531X_MEM_BASE,
|
||||
.end = AR531X_MEM_BASE + AR531X_MEM_SIZE - AR531X_IO_SIZE - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
};
|
||||
|
||||
static struct resource ar531x_io_resource = {
|
||||
.name = "AR531x PCI I/O",
|
||||
.start = 0,
|
||||
.end = AR531X_IO_SIZE,
|
||||
.flags = IORESOURCE_IO,
|
||||
};
|
||||
|
||||
struct pci_controller ar531x_pci_controller = {
|
||||
.pci_ops = &ar531x_pci_ops,
|
||||
.mem_resource = &ar531x_mem_resource,
|
||||
.io_resource = &ar531x_io_resource,
|
||||
};
|
||||
|
||||
int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
|
||||
{
|
||||
return AR5315_IRQ_LCBUS_PCI;
|
||||
}
|
||||
|
||||
int pcibios_plat_dev_init(struct pci_dev *dev)
|
||||
{
|
||||
u32 reg;
|
||||
|
||||
pci_write_config_byte(dev, PCI_INTERRUPT_LINE, 5);
|
||||
pci_write_config_word(dev, 0x40, 0);
|
||||
|
||||
/* Clear any pending Abort or external Interrupts
|
||||
* and enable interrupt processing */
|
||||
reg = sysRegRead(AR5315_PCI_INTEN_REG);
|
||||
reg &= ~AR5315_PCI_INT_ENABLE;
|
||||
sysRegWrite(AR5315_PCI_INTEN_REG, reg);
|
||||
|
||||
reg = sysRegRead(AR5315_PCI_INT_STATUS);
|
||||
reg |= (AR5315_PCI_ABORT_INT | AR5315_PCI_EXT_INT);
|
||||
sysRegWrite(AR5315_PCI_INT_STATUS, reg);
|
||||
|
||||
reg = sysRegRead(AR5315_PCI_INT_MASK);
|
||||
reg |= (AR5315_PCI_EXT_INT | AR5315_PCI_ABORT_INT);
|
||||
sysRegWrite(AR5315_PCI_INT_MASK, reg);
|
||||
|
||||
reg = sysRegRead(AR5315_PCI_INTEN_REG);
|
||||
reg |= AR5315_PCI_INT_ENABLE;
|
||||
sysRegWrite(AR5315_PCI_INTEN_REG, reg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ar5315_pci_fixup(struct pci_dev *dev)
|
||||
{
|
||||
struct pci_bus *bus = dev->bus;
|
||||
|
||||
if ((PCI_SLOT(dev->devfn) != 3) || (PCI_FUNC(dev->devfn) != 0) || (bus->number != 0))
|
||||
return;
|
||||
|
||||
#define _DEV bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn)
|
||||
printk("PCI: fixing up device %d,%d,%d\n", _DEV);
|
||||
/* fix up mbars */
|
||||
config_access(_DEV, PCI_BASE_ADDRESS_0, 4, HOST_PCI_MBAR0, 1);
|
||||
config_access(_DEV, PCI_BASE_ADDRESS_1, 4, HOST_PCI_MBAR1, 1);
|
||||
config_access(_DEV, PCI_BASE_ADDRESS_2, 4, HOST_PCI_MBAR2, 1);
|
||||
config_access(_DEV, PCI_COMMAND, 4,
|
||||
PCI_COMMAND_MEMORY|PCI_COMMAND_MASTER|PCI_COMMAND_SPECIAL|
|
||||
PCI_COMMAND_INVALIDATE|PCI_COMMAND_PARITY|PCI_COMMAND_SERR|
|
||||
PCI_COMMAND_FAST_BACK, 1);
|
||||
#undef _DEV
|
||||
}
|
||||
DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, ar5315_pci_fixup);
|
||||
|
||||
int __init ar5315_pci_init(void)
|
||||
{
|
||||
u32 reg;
|
||||
|
||||
printk("AR531x PCI init... ");
|
||||
|
||||
cfgaddr = (u32) ioremap_nocache(0x80000000, 1*1024*1024); /* Remap PCI config space */
|
||||
set_io_port_base((unsigned long) ioremap_nocache(AR531X_MEM_BASE + AR531X_IO_SIZE - 1, AR531X_IO_SIZE)); /* PCI I/O space */
|
||||
|
||||
reg = sysRegRead(AR5315_RESET);
|
||||
sysRegWrite(AR5315_RESET, reg | AR5315_RESET_PCIDMA);
|
||||
|
||||
udelay(10*1000);
|
||||
|
||||
sysRegWrite(AR5315_RESET, reg & ~AR5315_RESET_PCIDMA);
|
||||
sysRegRead(AR5315_RESET); /* read after */
|
||||
|
||||
udelay(10*1000);
|
||||
|
||||
reg = sysRegRead(AR5315_ENDIAN_CTL);
|
||||
reg |= AR5315_CONFIG_PCIAHB | AR5315_CONFIG_PCIAHB_BRIDGE;
|
||||
|
||||
sysRegWrite(AR5315_ENDIAN_CTL, reg);
|
||||
|
||||
reg = sysRegRead(AR5315_PCICLK);
|
||||
reg = 4;
|
||||
sysRegWrite(AR5315_PCICLK, reg);
|
||||
|
||||
reg = sysRegRead(AR5315_AHB_ARB_CTL);
|
||||
reg |= (ARB_PCI);
|
||||
sysRegWrite(AR5315_AHB_ARB_CTL, reg);
|
||||
|
||||
reg = sysRegRead(AR5315_IF_CTL);
|
||||
reg &= ~(IF_PCI_CLK_MASK | IF_MASK);
|
||||
reg |= (IF_PCI | IF_PCI_HOST | IF_PCI_INTR | (IF_PCI_CLK_OUTPUT_CLK << IF_PCI_CLK_SHIFT));
|
||||
|
||||
sysRegWrite(AR5315_IF_CTL, reg);
|
||||
|
||||
/* Reset the PCI bus by setting bits 5-4 in PCI_MCFG */
|
||||
reg = sysRegRead(AR5315_PCI_MISC_CONFIG);
|
||||
reg &= ~(AR5315_PCIMISC_RST_MODE);
|
||||
reg |= AR5315_PCIRST_LOW;
|
||||
sysRegWrite(AR5315_PCI_MISC_CONFIG, reg);
|
||||
|
||||
/* wait for 100 ms */
|
||||
udelay(100*1000);
|
||||
|
||||
/* Bring the PCI out of reset */
|
||||
reg = sysRegRead(AR5315_PCI_MISC_CONFIG);
|
||||
reg &= ~(AR5315_PCIMISC_RST_MODE);
|
||||
reg |= (AR5315_PCIRST_HIGH | AR5315_PCICACHE_DIS | 0x8);
|
||||
sysRegWrite(AR5315_PCI_MISC_CONFIG, reg);
|
||||
|
||||
sysRegWrite(AR5315_PCI_UNCACHE_CFG,
|
||||
0x1E | /* 1GB uncached */
|
||||
(1 << 5) | /* Enable uncached */
|
||||
(0x2 << 30) /* Base: 0x80000000 */
|
||||
);
|
||||
(void)sysRegRead(AR5315_PCI_UNCACHE_CFG); /* flush */
|
||||
|
||||
udelay(500*1000);
|
||||
|
||||
register_pci_controller(&ar531x_pci_controller);
|
||||
|
||||
printk("done\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
arch_initcall(ar5315_pci_init);
|
@ -10,11 +10,7 @@
|
||||
#ifndef __ASM_MACH_GENERIC_DMA_COHERENCE_H
|
||||
#define __ASM_MACH_GENERIC_DMA_COHERENCE_H
|
||||
|
||||
#if 0
|
||||
#define PCI_DMA_OFFSET 0x20000000
|
||||
#else
|
||||
#define PCI_DMA_OFFSET 0x00000000
|
||||
#endif
|
||||
|
||||
struct device;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user