mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-11-28 07:31:15 +00:00
net: smc911x: Inline all functions from header file
Inline all the functions from the header file, as they are not used outside of the driver or the standalone EEPROM example. Note that this does introduce considerable amount of duplication in the standalone EEPROM example, however that one has to be rewritten anyway, roughly such that the SMC911x driver would expose DM EEPROM interface and the standalone example would use that. Signed-off-by: Marek Vasut <marek.vasut+renesas@gmail.com> Cc: Joe Hershberger <joe.hershberger@ni.com> Cc: Masahiro Yamada <yamada.masahiro@socionext.com>
This commit is contained in:
parent
f51a2f8496
commit
eb46efa381
3 changed files with 312 additions and 158 deletions
|
@ -10,9 +10,165 @@
|
|||
#include <malloc.h>
|
||||
#include <net.h>
|
||||
#include <miiphy.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
#include "smc911x.h"
|
||||
|
||||
struct chip_id {
|
||||
u16 id;
|
||||
char *name;
|
||||
};
|
||||
|
||||
static const struct chip_id chip_ids[] = {
|
||||
{ CHIP_89218, "LAN89218" },
|
||||
{ CHIP_9115, "LAN9115" },
|
||||
{ CHIP_9116, "LAN9116" },
|
||||
{ CHIP_9117, "LAN9117" },
|
||||
{ CHIP_9118, "LAN9118" },
|
||||
{ CHIP_9211, "LAN9211" },
|
||||
{ CHIP_9215, "LAN9215" },
|
||||
{ CHIP_9216, "LAN9216" },
|
||||
{ CHIP_9217, "LAN9217" },
|
||||
{ CHIP_9218, "LAN9218" },
|
||||
{ CHIP_9220, "LAN9220" },
|
||||
{ CHIP_9221, "LAN9221" },
|
||||
{ 0, NULL },
|
||||
};
|
||||
|
||||
#define DRIVERNAME "smc911x"
|
||||
|
||||
#if defined (CONFIG_SMC911X_32_BIT) && \
|
||||
defined (CONFIG_SMC911X_16_BIT)
|
||||
#error "SMC911X: Only one of CONFIG_SMC911X_32_BIT and \
|
||||
CONFIG_SMC911X_16_BIT shall be set"
|
||||
#endif
|
||||
|
||||
#if defined (CONFIG_SMC911X_32_BIT)
|
||||
static inline u32 __smc911x_reg_read(struct eth_device *dev, u32 offset)
|
||||
{
|
||||
return *(volatile u32*)(dev->iobase + offset);
|
||||
}
|
||||
u32 smc911x_reg_read(struct eth_device *dev, u32 offset)
|
||||
__attribute__((weak, alias("__smc911x_reg_read")));
|
||||
|
||||
static inline void __smc911x_reg_write(struct eth_device *dev,
|
||||
u32 offset, u32 val)
|
||||
{
|
||||
*(volatile u32*)(dev->iobase + offset) = val;
|
||||
}
|
||||
void smc911x_reg_write(struct eth_device *dev, u32 offset, u32 val)
|
||||
__attribute__((weak, alias("__smc911x_reg_write")));
|
||||
#elif defined (CONFIG_SMC911X_16_BIT)
|
||||
static inline u32 smc911x_reg_read(struct eth_device *dev, u32 offset)
|
||||
{
|
||||
volatile u16 *addr_16 = (u16 *)(dev->iobase + offset);
|
||||
return ((*addr_16 & 0x0000ffff) | (*(addr_16 + 1) << 16));
|
||||
}
|
||||
static inline void smc911x_reg_write(struct eth_device *dev,
|
||||
u32 offset, u32 val)
|
||||
{
|
||||
*(volatile u16 *)(dev->iobase + offset) = (u16)val;
|
||||
*(volatile u16 *)(dev->iobase + offset + 2) = (u16)(val >> 16);
|
||||
}
|
||||
#else
|
||||
#error "SMC911X: undefined bus width"
|
||||
#endif /* CONFIG_SMC911X_16_BIT */
|
||||
|
||||
static u32 smc911x_get_mac_csr(struct eth_device *dev, u8 reg)
|
||||
{
|
||||
while (smc911x_reg_read(dev, MAC_CSR_CMD) & MAC_CSR_CMD_CSR_BUSY)
|
||||
;
|
||||
smc911x_reg_write(dev, MAC_CSR_CMD,
|
||||
MAC_CSR_CMD_CSR_BUSY | MAC_CSR_CMD_R_NOT_W | reg);
|
||||
while (smc911x_reg_read(dev, MAC_CSR_CMD) & MAC_CSR_CMD_CSR_BUSY)
|
||||
;
|
||||
|
||||
return smc911x_reg_read(dev, MAC_CSR_DATA);
|
||||
}
|
||||
|
||||
static void smc911x_set_mac_csr(struct eth_device *dev, u8 reg, u32 data)
|
||||
{
|
||||
while (smc911x_reg_read(dev, MAC_CSR_CMD) & MAC_CSR_CMD_CSR_BUSY)
|
||||
;
|
||||
smc911x_reg_write(dev, MAC_CSR_DATA, data);
|
||||
smc911x_reg_write(dev, MAC_CSR_CMD, MAC_CSR_CMD_CSR_BUSY | reg);
|
||||
while (smc911x_reg_read(dev, MAC_CSR_CMD) & MAC_CSR_CMD_CSR_BUSY)
|
||||
;
|
||||
}
|
||||
|
||||
static int smc911x_detect_chip(struct eth_device *dev)
|
||||
{
|
||||
unsigned long val, i;
|
||||
|
||||
val = smc911x_reg_read(dev, BYTE_TEST);
|
||||
if (val == 0xffffffff) {
|
||||
/* Special case -- no chip present */
|
||||
return -1;
|
||||
} else if (val != 0x87654321) {
|
||||
printf(DRIVERNAME ": Invalid chip endian 0x%08lx\n", val);
|
||||
return -1;
|
||||
}
|
||||
|
||||
val = smc911x_reg_read(dev, ID_REV) >> 16;
|
||||
for (i = 0; chip_ids[i].id != 0; i++) {
|
||||
if (chip_ids[i].id == val) break;
|
||||
}
|
||||
if (!chip_ids[i].id) {
|
||||
printf(DRIVERNAME ": Unknown chip ID %04lx\n", val);
|
||||
return -1;
|
||||
}
|
||||
|
||||
dev->priv = (void *)&chip_ids[i];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void smc911x_reset(struct eth_device *dev)
|
||||
{
|
||||
int timeout;
|
||||
|
||||
/*
|
||||
* Take out of PM setting first
|
||||
* Device is already wake up if PMT_CTRL_READY bit is set
|
||||
*/
|
||||
if ((smc911x_reg_read(dev, PMT_CTRL) & PMT_CTRL_READY) == 0) {
|
||||
/* Write to the bytetest will take out of powerdown */
|
||||
smc911x_reg_write(dev, BYTE_TEST, 0x0);
|
||||
|
||||
timeout = 10;
|
||||
|
||||
while (timeout-- &&
|
||||
!(smc911x_reg_read(dev, PMT_CTRL) & PMT_CTRL_READY))
|
||||
udelay(10);
|
||||
if (timeout < 0) {
|
||||
printf(DRIVERNAME
|
||||
": timeout waiting for PM restore\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Disable interrupts */
|
||||
smc911x_reg_write(dev, INT_EN, 0);
|
||||
|
||||
smc911x_reg_write(dev, HW_CFG, HW_CFG_SRST);
|
||||
|
||||
timeout = 1000;
|
||||
while (timeout-- && smc911x_reg_read(dev, E2P_CMD) & E2P_CMD_EPC_BUSY)
|
||||
udelay(10);
|
||||
|
||||
if (timeout < 0) {
|
||||
printf(DRIVERNAME ": reset timeout\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Reset the FIFO level and flow control settings */
|
||||
smc911x_set_mac_csr(dev, FLOW, FLOW_FCPT | FLOW_FCEN);
|
||||
smc911x_reg_write(dev, AFC_CFG, 0x0050287F);
|
||||
|
||||
/* Set to LED outputs */
|
||||
smc911x_reg_write(dev, GPIO_CFG, 0x70070000);
|
||||
}
|
||||
|
||||
static void smc911x_handle_mac_address(struct eth_device *dev)
|
||||
{
|
||||
unsigned long addrh, addrl;
|
||||
|
@ -117,7 +273,6 @@ static void smc911x_enable(struct eth_device *dev)
|
|||
|
||||
smc911x_set_mac_csr(dev, MAC_CR, MAC_CR_TXEN | MAC_CR_RXEN |
|
||||
MAC_CR_HBDIS);
|
||||
|
||||
}
|
||||
|
||||
static int smc911x_init(struct eth_device *dev, bd_t * bd)
|
||||
|
|
|
@ -8,47 +8,6 @@
|
|||
#ifndef _SMC911X_H_
|
||||
#define _SMC911X_H_
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
#define DRIVERNAME "smc911x"
|
||||
|
||||
#if defined (CONFIG_SMC911X_32_BIT) && \
|
||||
defined (CONFIG_SMC911X_16_BIT)
|
||||
#error "SMC911X: Only one of CONFIG_SMC911X_32_BIT and \
|
||||
CONFIG_SMC911X_16_BIT shall be set"
|
||||
#endif
|
||||
|
||||
#if defined (CONFIG_SMC911X_32_BIT)
|
||||
static inline u32 __smc911x_reg_read(struct eth_device *dev, u32 offset)
|
||||
{
|
||||
return *(volatile u32*)(dev->iobase + offset);
|
||||
}
|
||||
u32 smc911x_reg_read(struct eth_device *dev, u32 offset)
|
||||
__attribute__((weak, alias("__smc911x_reg_read")));
|
||||
|
||||
static inline void __smc911x_reg_write(struct eth_device *dev,
|
||||
u32 offset, u32 val)
|
||||
{
|
||||
*(volatile u32*)(dev->iobase + offset) = val;
|
||||
}
|
||||
void smc911x_reg_write(struct eth_device *dev, u32 offset, u32 val)
|
||||
__attribute__((weak, alias("__smc911x_reg_write")));
|
||||
#elif defined (CONFIG_SMC911X_16_BIT)
|
||||
static inline u32 smc911x_reg_read(struct eth_device *dev, u32 offset)
|
||||
{
|
||||
volatile u16 *addr_16 = (u16 *)(dev->iobase + offset);
|
||||
return ((*addr_16 & 0x0000ffff) | (*(addr_16 + 1) << 16));
|
||||
}
|
||||
static inline void smc911x_reg_write(struct eth_device *dev,
|
||||
u32 offset, u32 val)
|
||||
{
|
||||
*(volatile u16 *)(dev->iobase + offset) = (u16)val;
|
||||
*(volatile u16 *)(dev->iobase + offset + 2) = (u16)(val >> 16);
|
||||
}
|
||||
#else
|
||||
#error "SMC911X: undefined bus width"
|
||||
#endif /* CONFIG_SMC911X_16_BIT */
|
||||
|
||||
/* Below are the register offsets and bit definitions
|
||||
* of the Lan911x memory space
|
||||
*/
|
||||
|
@ -380,120 +339,4 @@ static inline void smc911x_reg_write(struct eth_device *dev,
|
|||
#define CHIP_9220 0x9220
|
||||
#define CHIP_9221 0x9221
|
||||
|
||||
struct chip_id {
|
||||
u16 id;
|
||||
char *name;
|
||||
};
|
||||
|
||||
static const struct chip_id chip_ids[] = {
|
||||
{ CHIP_89218, "LAN89218" },
|
||||
{ CHIP_9115, "LAN9115" },
|
||||
{ CHIP_9116, "LAN9116" },
|
||||
{ CHIP_9117, "LAN9117" },
|
||||
{ CHIP_9118, "LAN9118" },
|
||||
{ CHIP_9211, "LAN9211" },
|
||||
{ CHIP_9215, "LAN9215" },
|
||||
{ CHIP_9216, "LAN9216" },
|
||||
{ CHIP_9217, "LAN9217" },
|
||||
{ CHIP_9218, "LAN9218" },
|
||||
{ CHIP_9220, "LAN9220" },
|
||||
{ CHIP_9221, "LAN9221" },
|
||||
{ 0, NULL },
|
||||
};
|
||||
|
||||
static u32 smc911x_get_mac_csr(struct eth_device *dev, u8 reg)
|
||||
{
|
||||
while (smc911x_reg_read(dev, MAC_CSR_CMD) & MAC_CSR_CMD_CSR_BUSY)
|
||||
;
|
||||
smc911x_reg_write(dev, MAC_CSR_CMD,
|
||||
MAC_CSR_CMD_CSR_BUSY | MAC_CSR_CMD_R_NOT_W | reg);
|
||||
while (smc911x_reg_read(dev, MAC_CSR_CMD) & MAC_CSR_CMD_CSR_BUSY)
|
||||
;
|
||||
|
||||
return smc911x_reg_read(dev, MAC_CSR_DATA);
|
||||
}
|
||||
|
||||
static void smc911x_set_mac_csr(struct eth_device *dev, u8 reg, u32 data)
|
||||
{
|
||||
while (smc911x_reg_read(dev, MAC_CSR_CMD) & MAC_CSR_CMD_CSR_BUSY)
|
||||
;
|
||||
smc911x_reg_write(dev, MAC_CSR_DATA, data);
|
||||
smc911x_reg_write(dev, MAC_CSR_CMD, MAC_CSR_CMD_CSR_BUSY | reg);
|
||||
while (smc911x_reg_read(dev, MAC_CSR_CMD) & MAC_CSR_CMD_CSR_BUSY)
|
||||
;
|
||||
}
|
||||
|
||||
static int smc911x_detect_chip(struct eth_device *dev)
|
||||
{
|
||||
unsigned long val, i;
|
||||
|
||||
val = smc911x_reg_read(dev, BYTE_TEST);
|
||||
if (val == 0xffffffff) {
|
||||
/* Special case -- no chip present */
|
||||
return -1;
|
||||
} else if (val != 0x87654321) {
|
||||
printf(DRIVERNAME ": Invalid chip endian 0x%08lx\n", val);
|
||||
return -1;
|
||||
}
|
||||
|
||||
val = smc911x_reg_read(dev, ID_REV) >> 16;
|
||||
for (i = 0; chip_ids[i].id != 0; i++) {
|
||||
if (chip_ids[i].id == val) break;
|
||||
}
|
||||
if (!chip_ids[i].id) {
|
||||
printf(DRIVERNAME ": Unknown chip ID %04lx\n", val);
|
||||
return -1;
|
||||
}
|
||||
|
||||
dev->priv = (void *)&chip_ids[i];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void smc911x_reset(struct eth_device *dev)
|
||||
{
|
||||
int timeout;
|
||||
|
||||
/*
|
||||
* Take out of PM setting first
|
||||
* Device is already wake up if PMT_CTRL_READY bit is set
|
||||
*/
|
||||
if ((smc911x_reg_read(dev, PMT_CTRL) & PMT_CTRL_READY) == 0) {
|
||||
/* Write to the bytetest will take out of powerdown */
|
||||
smc911x_reg_write(dev, BYTE_TEST, 0x0);
|
||||
|
||||
timeout = 10;
|
||||
|
||||
while (timeout-- &&
|
||||
!(smc911x_reg_read(dev, PMT_CTRL) & PMT_CTRL_READY))
|
||||
udelay(10);
|
||||
if (timeout < 0) {
|
||||
printf(DRIVERNAME
|
||||
": timeout waiting for PM restore\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Disable interrupts */
|
||||
smc911x_reg_write(dev, INT_EN, 0);
|
||||
|
||||
smc911x_reg_write(dev, HW_CFG, HW_CFG_SRST);
|
||||
|
||||
timeout = 1000;
|
||||
while (timeout-- && smc911x_reg_read(dev, E2P_CMD) & E2P_CMD_EPC_BUSY)
|
||||
udelay(10);
|
||||
|
||||
if (timeout < 0) {
|
||||
printf(DRIVERNAME ": reset timeout\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Reset the FIFO level and flow control settings */
|
||||
smc911x_set_mac_csr(dev, FLOW, FLOW_FCPT | FLOW_FCEN);
|
||||
smc911x_reg_write(dev, AFC_CFG, 0x0050287F);
|
||||
|
||||
/* Set to LED outputs */
|
||||
smc911x_reg_write(dev, GPIO_CFG, 0x70070000);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -18,8 +18,164 @@
|
|||
#include <console.h>
|
||||
#include <exports.h>
|
||||
#include <linux/ctype.h>
|
||||
#include <linux/types.h>
|
||||
#include "../drivers/net/smc911x.h"
|
||||
|
||||
#define DRIVERNAME "smc911x"
|
||||
|
||||
#if defined (CONFIG_SMC911X_32_BIT) && \
|
||||
defined (CONFIG_SMC911X_16_BIT)
|
||||
#error "SMC911X: Only one of CONFIG_SMC911X_32_BIT and \
|
||||
CONFIG_SMC911X_16_BIT shall be set"
|
||||
#endif
|
||||
|
||||
struct chip_id {
|
||||
u16 id;
|
||||
char *name;
|
||||
};
|
||||
|
||||
static const struct chip_id chip_ids[] = {
|
||||
{ CHIP_89218, "LAN89218" },
|
||||
{ CHIP_9115, "LAN9115" },
|
||||
{ CHIP_9116, "LAN9116" },
|
||||
{ CHIP_9117, "LAN9117" },
|
||||
{ CHIP_9118, "LAN9118" },
|
||||
{ CHIP_9211, "LAN9211" },
|
||||
{ CHIP_9215, "LAN9215" },
|
||||
{ CHIP_9216, "LAN9216" },
|
||||
{ CHIP_9217, "LAN9217" },
|
||||
{ CHIP_9218, "LAN9218" },
|
||||
{ CHIP_9220, "LAN9220" },
|
||||
{ CHIP_9221, "LAN9221" },
|
||||
{ 0, NULL },
|
||||
};
|
||||
|
||||
#if defined (CONFIG_SMC911X_32_BIT)
|
||||
static inline u32 __smc911x_reg_read(struct eth_device *dev, u32 offset)
|
||||
{
|
||||
return *(volatile u32*)(dev->iobase + offset);
|
||||
}
|
||||
u32 smc911x_reg_read(struct eth_device *dev, u32 offset)
|
||||
__attribute__((weak, alias("__smc911x_reg_read")));
|
||||
|
||||
static inline void __smc911x_reg_write(struct eth_device *dev,
|
||||
u32 offset, u32 val)
|
||||
{
|
||||
*(volatile u32*)(dev->iobase + offset) = val;
|
||||
}
|
||||
void smc911x_reg_write(struct eth_device *dev, u32 offset, u32 val)
|
||||
__attribute__((weak, alias("__smc911x_reg_write")));
|
||||
#elif defined (CONFIG_SMC911X_16_BIT)
|
||||
static inline u32 smc911x_reg_read(struct eth_device *dev, u32 offset)
|
||||
{
|
||||
volatile u16 *addr_16 = (u16 *)(dev->iobase + offset);
|
||||
return ((*addr_16 & 0x0000ffff) | (*(addr_16 + 1) << 16));
|
||||
}
|
||||
static inline void smc911x_reg_write(struct eth_device *dev,
|
||||
u32 offset, u32 val)
|
||||
{
|
||||
*(volatile u16 *)(dev->iobase + offset) = (u16)val;
|
||||
*(volatile u16 *)(dev->iobase + offset + 2) = (u16)(val >> 16);
|
||||
}
|
||||
#else
|
||||
#error "SMC911X: undefined bus width"
|
||||
#endif /* CONFIG_SMC911X_16_BIT */
|
||||
|
||||
static u32 smc911x_get_mac_csr(struct eth_device *dev, u8 reg)
|
||||
{
|
||||
while (smc911x_reg_read(dev, MAC_CSR_CMD) & MAC_CSR_CMD_CSR_BUSY)
|
||||
;
|
||||
smc911x_reg_write(dev, MAC_CSR_CMD,
|
||||
MAC_CSR_CMD_CSR_BUSY | MAC_CSR_CMD_R_NOT_W | reg);
|
||||
while (smc911x_reg_read(dev, MAC_CSR_CMD) & MAC_CSR_CMD_CSR_BUSY)
|
||||
;
|
||||
|
||||
return smc911x_reg_read(dev, MAC_CSR_DATA);
|
||||
}
|
||||
|
||||
static void smc911x_set_mac_csr(struct eth_device *dev, u8 reg, u32 data)
|
||||
{
|
||||
while (smc911x_reg_read(dev, MAC_CSR_CMD) & MAC_CSR_CMD_CSR_BUSY)
|
||||
;
|
||||
smc911x_reg_write(dev, MAC_CSR_DATA, data);
|
||||
smc911x_reg_write(dev, MAC_CSR_CMD, MAC_CSR_CMD_CSR_BUSY | reg);
|
||||
while (smc911x_reg_read(dev, MAC_CSR_CMD) & MAC_CSR_CMD_CSR_BUSY)
|
||||
;
|
||||
}
|
||||
|
||||
static int smc911x_detect_chip(struct eth_device *dev)
|
||||
{
|
||||
unsigned long val, i;
|
||||
|
||||
val = smc911x_reg_read(dev, BYTE_TEST);
|
||||
if (val == 0xffffffff) {
|
||||
/* Special case -- no chip present */
|
||||
return -1;
|
||||
} else if (val != 0x87654321) {
|
||||
printf(DRIVERNAME ": Invalid chip endian 0x%08lx\n", val);
|
||||
return -1;
|
||||
}
|
||||
|
||||
val = smc911x_reg_read(dev, ID_REV) >> 16;
|
||||
for (i = 0; chip_ids[i].id != 0; i++) {
|
||||
if (chip_ids[i].id == val) break;
|
||||
}
|
||||
if (!chip_ids[i].id) {
|
||||
printf(DRIVERNAME ": Unknown chip ID %04lx\n", val);
|
||||
return -1;
|
||||
}
|
||||
|
||||
dev->priv = (void *)&chip_ids[i];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void smc911x_reset(struct eth_device *dev)
|
||||
{
|
||||
int timeout;
|
||||
|
||||
/*
|
||||
* Take out of PM setting first
|
||||
* Device is already wake up if PMT_CTRL_READY bit is set
|
||||
*/
|
||||
if ((smc911x_reg_read(dev, PMT_CTRL) & PMT_CTRL_READY) == 0) {
|
||||
/* Write to the bytetest will take out of powerdown */
|
||||
smc911x_reg_write(dev, BYTE_TEST, 0x0);
|
||||
|
||||
timeout = 10;
|
||||
|
||||
while (timeout-- &&
|
||||
!(smc911x_reg_read(dev, PMT_CTRL) & PMT_CTRL_READY))
|
||||
udelay(10);
|
||||
if (timeout < 0) {
|
||||
printf(DRIVERNAME
|
||||
": timeout waiting for PM restore\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Disable interrupts */
|
||||
smc911x_reg_write(dev, INT_EN, 0);
|
||||
|
||||
smc911x_reg_write(dev, HW_CFG, HW_CFG_SRST);
|
||||
|
||||
timeout = 1000;
|
||||
while (timeout-- && smc911x_reg_read(dev, E2P_CMD) & E2P_CMD_EPC_BUSY)
|
||||
udelay(10);
|
||||
|
||||
if (timeout < 0) {
|
||||
printf(DRIVERNAME ": reset timeout\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Reset the FIFO level and flow control settings */
|
||||
smc911x_set_mac_csr(dev, FLOW, FLOW_FCPT | FLOW_FCEN);
|
||||
smc911x_reg_write(dev, AFC_CFG, 0x0050287F);
|
||||
|
||||
/* Set to LED outputs */
|
||||
smc911x_reg_write(dev, GPIO_CFG, 0x70070000);
|
||||
}
|
||||
|
||||
/**
|
||||
* smsc_ctrlc - detect press of CTRL+C (common ctrlc() isnt exported!?)
|
||||
*/
|
||||
|
|
Loading…
Reference in a new issue