Staging driver fixes for 5.1-rc3
Here are some small staging driver fixes for 5.1-rc3, and one driver removal. The biggest thing here is the removal of the mt7621-eth driver as a "real" network driver was merged in 5.1-rc1 for this hardware, so this old driver can now be removed. Other than that, there are just a number of small fixes, all resolving reported issues and some potential corner cases for error handling paths. All of these have been in linux-next with no reported issues. Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> -----BEGIN PGP SIGNATURE----- iG0EABECAC0WIQT0tgzFv3jCIUoxPcsxR9QN2y37KQUCXJ8vpg8cZ3JlZ0Brcm9h aC5jb20ACgkQMUfUDdst+yksHgCeJATLFpgiWqGvR8K/PfiG2QixudEAoMivMAM2 s1Obj1TFIQK+xTAINt6U =uJaK -----END PGP SIGNATURE----- Merge tag 'staging-5.1-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging Pull staging driver fixes from Greg KH: "Here are some small staging driver fixes for 5.1-rc3, and one driver removal. The biggest thing here is the removal of the mt7621-eth driver as a "real" network driver was merged in 5.1-rc1 for this hardware, so this old driver can now be removed. Other than that, there are just a number of small fixes, all resolving reported issues and some potential corner cases for error handling paths. All of these have been in linux-next with no reported issues" * tag 'staging-5.1-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging: staging: vt6655: Remove vif check from vnt_interrupt staging: erofs: keep corrupted fs from crashing kernel in erofs_readdir() staging: octeon-ethernet: fix incorrect PHY mode staging: vc04_services: Fix an error code in vchiq_probe() staging: erofs: fix error handling when failed to read compresssed data staging: vt6655: Fix interrupt race condition on device start up. staging: rtlwifi: Fix potential NULL pointer dereference of kzalloc staging: rtl8712: uninitialized memory in read_bbreg_hdl() staging: rtlwifi: rtl8822b: fix to avoid potential NULL pointer dereference staging: rtl8188eu: Fix potential NULL pointer dereference of kcalloc staging, mt7621-pci: fix build without pci support staging: speakup_soft: Fix alternate speech with other synths staging: axis-fifo: add CONFIG_OF dependency staging: olpc_dcon_xo_1: add missing 'const' qualifier staging: comedi: ni_mio_common: Fix divide-by-zero for DIO cmdtest staging: erofs: fix to handle error path of erofs_vmap() staging: mt7621-dts: update ethernet settings. staging: remove mt7621-eth
This commit is contained in:
commit
32faca66bd
|
@ -114,8 +114,6 @@ source "drivers/staging/ralink-gdma/Kconfig"
|
|||
|
||||
source "drivers/staging/mt7621-mmc/Kconfig"
|
||||
|
||||
source "drivers/staging/mt7621-eth/Kconfig"
|
||||
|
||||
source "drivers/staging/mt7621-dts/Kconfig"
|
||||
|
||||
source "drivers/staging/gasket/Kconfig"
|
||||
|
|
|
@ -47,7 +47,6 @@ obj-$(CONFIG_SPI_MT7621) += mt7621-spi/
|
|||
obj-$(CONFIG_SOC_MT7621) += mt7621-dma/
|
||||
obj-$(CONFIG_DMA_RALINK) += ralink-gdma/
|
||||
obj-$(CONFIG_MTK_MMC) += mt7621-mmc/
|
||||
obj-$(CONFIG_NET_MEDIATEK_SOC_STAGING) += mt7621-eth/
|
||||
obj-$(CONFIG_SOC_MT7621) += mt7621-dts/
|
||||
obj-$(CONFIG_STAGING_GASKET_FRAMEWORK) += gasket/
|
||||
obj-$(CONFIG_XIL_AXIS_FIFO) += axis-fifo/
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#
|
||||
config XIL_AXIS_FIFO
|
||||
tristate "Xilinx AXI-Stream FIFO IP core driver"
|
||||
depends on OF
|
||||
default n
|
||||
help
|
||||
This adds support for the Xilinx AXI-Stream
|
||||
|
|
|
@ -1001,6 +1001,8 @@ int comedi_dio_insn_config(struct comedi_device *dev,
|
|||
unsigned int mask);
|
||||
unsigned int comedi_dio_update_state(struct comedi_subdevice *s,
|
||||
unsigned int *data);
|
||||
unsigned int comedi_bytes_per_scan_cmd(struct comedi_subdevice *s,
|
||||
struct comedi_cmd *cmd);
|
||||
unsigned int comedi_bytes_per_scan(struct comedi_subdevice *s);
|
||||
unsigned int comedi_nscans_left(struct comedi_subdevice *s,
|
||||
unsigned int nscans);
|
||||
|
|
|
@ -394,11 +394,13 @@ unsigned int comedi_dio_update_state(struct comedi_subdevice *s,
|
|||
EXPORT_SYMBOL_GPL(comedi_dio_update_state);
|
||||
|
||||
/**
|
||||
* comedi_bytes_per_scan() - Get length of asynchronous command "scan" in bytes
|
||||
* comedi_bytes_per_scan_cmd() - Get length of asynchronous command "scan" in
|
||||
* bytes
|
||||
* @s: COMEDI subdevice.
|
||||
* @cmd: COMEDI command.
|
||||
*
|
||||
* Determines the overall scan length according to the subdevice type and the
|
||||
* number of channels in the scan.
|
||||
* number of channels in the scan for the specified command.
|
||||
*
|
||||
* For digital input, output or input/output subdevices, samples for
|
||||
* multiple channels are assumed to be packed into one or more unsigned
|
||||
|
@ -408,9 +410,9 @@ EXPORT_SYMBOL_GPL(comedi_dio_update_state);
|
|||
*
|
||||
* Returns the overall scan length in bytes.
|
||||
*/
|
||||
unsigned int comedi_bytes_per_scan(struct comedi_subdevice *s)
|
||||
unsigned int comedi_bytes_per_scan_cmd(struct comedi_subdevice *s,
|
||||
struct comedi_cmd *cmd)
|
||||
{
|
||||
struct comedi_cmd *cmd = &s->async->cmd;
|
||||
unsigned int num_samples;
|
||||
unsigned int bits_per_sample;
|
||||
|
||||
|
@ -427,6 +429,29 @@ unsigned int comedi_bytes_per_scan(struct comedi_subdevice *s)
|
|||
}
|
||||
return comedi_samples_to_bytes(s, num_samples);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(comedi_bytes_per_scan_cmd);
|
||||
|
||||
/**
|
||||
* comedi_bytes_per_scan() - Get length of asynchronous command "scan" in bytes
|
||||
* @s: COMEDI subdevice.
|
||||
*
|
||||
* Determines the overall scan length according to the subdevice type and the
|
||||
* number of channels in the scan for the current command.
|
||||
*
|
||||
* For digital input, output or input/output subdevices, samples for
|
||||
* multiple channels are assumed to be packed into one or more unsigned
|
||||
* short or unsigned int values according to the subdevice's %SDF_LSAMPL
|
||||
* flag. For other types of subdevice, samples are assumed to occupy a
|
||||
* whole unsigned short or unsigned int according to the %SDF_LSAMPL flag.
|
||||
*
|
||||
* Returns the overall scan length in bytes.
|
||||
*/
|
||||
unsigned int comedi_bytes_per_scan(struct comedi_subdevice *s)
|
||||
{
|
||||
struct comedi_cmd *cmd = &s->async->cmd;
|
||||
|
||||
return comedi_bytes_per_scan_cmd(s, cmd);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(comedi_bytes_per_scan);
|
||||
|
||||
static unsigned int __comedi_nscans_left(struct comedi_subdevice *s,
|
||||
|
|
|
@ -3545,6 +3545,7 @@ static int ni_cdio_cmdtest(struct comedi_device *dev,
|
|||
struct comedi_subdevice *s, struct comedi_cmd *cmd)
|
||||
{
|
||||
struct ni_private *devpriv = dev->private;
|
||||
unsigned int bytes_per_scan;
|
||||
int err = 0;
|
||||
|
||||
/* Step 1 : check if triggers are trivially valid */
|
||||
|
@ -3579,9 +3580,12 @@ static int ni_cdio_cmdtest(struct comedi_device *dev,
|
|||
err |= comedi_check_trigger_arg_is(&cmd->convert_arg, 0);
|
||||
err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg,
|
||||
cmd->chanlist_len);
|
||||
err |= comedi_check_trigger_arg_max(&cmd->stop_arg,
|
||||
s->async->prealloc_bufsz /
|
||||
comedi_bytes_per_scan(s));
|
||||
bytes_per_scan = comedi_bytes_per_scan_cmd(s, cmd);
|
||||
if (bytes_per_scan) {
|
||||
err |= comedi_check_trigger_arg_max(&cmd->stop_arg,
|
||||
s->async->prealloc_bufsz /
|
||||
bytes_per_scan);
|
||||
}
|
||||
|
||||
if (err)
|
||||
return 3;
|
||||
|
|
|
@ -23,6 +23,21 @@ static const unsigned char erofs_filetype_table[EROFS_FT_MAX] = {
|
|||
[EROFS_FT_SYMLINK] = DT_LNK,
|
||||
};
|
||||
|
||||
static void debug_one_dentry(unsigned char d_type, const char *de_name,
|
||||
unsigned int de_namelen)
|
||||
{
|
||||
#ifdef CONFIG_EROFS_FS_DEBUG
|
||||
/* since the on-disk name could not have the trailing '\0' */
|
||||
unsigned char dbg_namebuf[EROFS_NAME_LEN + 1];
|
||||
|
||||
memcpy(dbg_namebuf, de_name, de_namelen);
|
||||
dbg_namebuf[de_namelen] = '\0';
|
||||
|
||||
debugln("found dirent %s de_len %u d_type %d", dbg_namebuf,
|
||||
de_namelen, d_type);
|
||||
#endif
|
||||
}
|
||||
|
||||
static int erofs_fill_dentries(struct dir_context *ctx,
|
||||
void *dentry_blk, unsigned int *ofs,
|
||||
unsigned int nameoff, unsigned int maxsize)
|
||||
|
@ -33,14 +48,10 @@ static int erofs_fill_dentries(struct dir_context *ctx,
|
|||
de = dentry_blk + *ofs;
|
||||
while (de < end) {
|
||||
const char *de_name;
|
||||
int de_namelen;
|
||||
unsigned int de_namelen;
|
||||
unsigned char d_type;
|
||||
#ifdef CONFIG_EROFS_FS_DEBUG
|
||||
unsigned int dbg_namelen;
|
||||
unsigned char dbg_namebuf[EROFS_NAME_LEN];
|
||||
#endif
|
||||
|
||||
if (unlikely(de->file_type < EROFS_FT_MAX))
|
||||
if (de->file_type < EROFS_FT_MAX)
|
||||
d_type = erofs_filetype_table[de->file_type];
|
||||
else
|
||||
d_type = DT_UNKNOWN;
|
||||
|
@ -48,26 +59,20 @@ static int erofs_fill_dentries(struct dir_context *ctx,
|
|||
nameoff = le16_to_cpu(de->nameoff);
|
||||
de_name = (char *)dentry_blk + nameoff;
|
||||
|
||||
de_namelen = unlikely(de + 1 >= end) ?
|
||||
/* last directory entry */
|
||||
strnlen(de_name, maxsize - nameoff) :
|
||||
le16_to_cpu(de[1].nameoff) - nameoff;
|
||||
/* the last dirent in the block? */
|
||||
if (de + 1 >= end)
|
||||
de_namelen = strnlen(de_name, maxsize - nameoff);
|
||||
else
|
||||
de_namelen = le16_to_cpu(de[1].nameoff) - nameoff;
|
||||
|
||||
/* a corrupted entry is found */
|
||||
if (unlikely(de_namelen < 0)) {
|
||||
if (unlikely(nameoff + de_namelen > maxsize ||
|
||||
de_namelen > EROFS_NAME_LEN)) {
|
||||
DBG_BUGON(1);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_EROFS_FS_DEBUG
|
||||
dbg_namelen = min(EROFS_NAME_LEN - 1, de_namelen);
|
||||
memcpy(dbg_namebuf, de_name, dbg_namelen);
|
||||
dbg_namebuf[dbg_namelen] = '\0';
|
||||
|
||||
debugln("%s, found de_name %s de_len %d d_type %d", __func__,
|
||||
dbg_namebuf, de_namelen, d_type);
|
||||
#endif
|
||||
|
||||
debug_one_dentry(d_type, de_name, de_namelen);
|
||||
if (!dir_emit(ctx, de_name, de_namelen,
|
||||
le64_to_cpu(de->nid), d_type))
|
||||
/* stopped by some reason */
|
||||
|
|
|
@ -972,6 +972,7 @@ repeat:
|
|||
overlapped = false;
|
||||
compressed_pages = grp->compressed_pages;
|
||||
|
||||
err = 0;
|
||||
for (i = 0; i < clusterpages; ++i) {
|
||||
unsigned int pagenr;
|
||||
|
||||
|
@ -981,26 +982,39 @@ repeat:
|
|||
DBG_BUGON(!page);
|
||||
DBG_BUGON(!page->mapping);
|
||||
|
||||
if (z_erofs_is_stagingpage(page))
|
||||
continue;
|
||||
if (!z_erofs_is_stagingpage(page)) {
|
||||
#ifdef EROFS_FS_HAS_MANAGED_CACHE
|
||||
if (page->mapping == MNGD_MAPPING(sbi)) {
|
||||
DBG_BUGON(!PageUptodate(page));
|
||||
continue;
|
||||
}
|
||||
if (page->mapping == MNGD_MAPPING(sbi)) {
|
||||
if (unlikely(!PageUptodate(page)))
|
||||
err = -EIO;
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* only non-head page could be reused as a compressed page */
|
||||
pagenr = z_erofs_onlinepage_index(page);
|
||||
/*
|
||||
* only if non-head page can be selected
|
||||
* for inplace decompression
|
||||
*/
|
||||
pagenr = z_erofs_onlinepage_index(page);
|
||||
|
||||
DBG_BUGON(pagenr >= nr_pages);
|
||||
DBG_BUGON(pages[pagenr]);
|
||||
++sparsemem_pages;
|
||||
pages[pagenr] = page;
|
||||
DBG_BUGON(pagenr >= nr_pages);
|
||||
DBG_BUGON(pages[pagenr]);
|
||||
++sparsemem_pages;
|
||||
pages[pagenr] = page;
|
||||
|
||||
overlapped = true;
|
||||
overlapped = true;
|
||||
}
|
||||
|
||||
/* PG_error needs checking for inplaced and staging pages */
|
||||
if (unlikely(PageError(page))) {
|
||||
DBG_BUGON(PageUptodate(page));
|
||||
err = -EIO;
|
||||
}
|
||||
}
|
||||
|
||||
if (unlikely(err))
|
||||
goto out;
|
||||
|
||||
llen = (nr_pages << PAGE_SHIFT) - work->pageofs;
|
||||
|
||||
if (z_erofs_vle_workgrp_fmt(grp) == Z_EROFS_VLE_WORKGRP_FMT_PLAIN) {
|
||||
|
@ -1029,6 +1043,10 @@ repeat:
|
|||
|
||||
skip_allocpage:
|
||||
vout = erofs_vmap(pages, nr_pages);
|
||||
if (!vout) {
|
||||
err = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
err = z_erofs_vle_unzip_vmap(compressed_pages,
|
||||
clusterpages, vout, llen, work->pageofs, overlapped);
|
||||
|
@ -1194,6 +1212,7 @@ repeat:
|
|||
if (page->mapping == mc) {
|
||||
WRITE_ONCE(grp->compressed_pages[nr], page);
|
||||
|
||||
ClearPageError(page);
|
||||
if (!PagePrivate(page)) {
|
||||
/*
|
||||
* impossible to be !PagePrivate(page) for
|
||||
|
|
|
@ -136,10 +136,13 @@ int z_erofs_vle_unzip_fast_percpu(struct page **compressed_pages,
|
|||
|
||||
nr_pages = DIV_ROUND_UP(outlen + pageofs, PAGE_SIZE);
|
||||
|
||||
if (clusterpages == 1)
|
||||
if (clusterpages == 1) {
|
||||
vin = kmap_atomic(compressed_pages[0]);
|
||||
else
|
||||
} else {
|
||||
vin = erofs_vmap(compressed_pages, clusterpages);
|
||||
if (!vin)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
preempt_disable();
|
||||
vout = erofs_pcpubuf[smp_processor_id()].data;
|
||||
|
|
|
@ -117,22 +117,6 @@
|
|||
status = "okay";
|
||||
};
|
||||
|
||||
ðernet {
|
||||
//mtd-mac-address = <&factory 0xe000>;
|
||||
gmac1: mac@0 {
|
||||
compatible = "mediatek,eth-mac";
|
||||
reg = <0>;
|
||||
phy-handle = <&phy1>;
|
||||
};
|
||||
|
||||
mdio-bus {
|
||||
phy1: ethernet-phy@1 {
|
||||
reg = <1>;
|
||||
phy-mode = "rgmii";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&pinctrl {
|
||||
state_default: pinctrl0 {
|
||||
gpio {
|
||||
|
@ -141,3 +125,16 @@
|
|||
};
|
||||
};
|
||||
};
|
||||
|
||||
&switch0 {
|
||||
ports {
|
||||
port@0 {
|
||||
label = "ethblack";
|
||||
status = "ok";
|
||||
};
|
||||
port@4 {
|
||||
label = "ethblue";
|
||||
status = "ok";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
|
@ -372,16 +372,83 @@
|
|||
|
||||
mediatek,ethsys = <ðsys>;
|
||||
|
||||
mediatek,switch = <&gsw>;
|
||||
|
||||
gmac0: mac@0 {
|
||||
compatible = "mediatek,eth-mac";
|
||||
reg = <0>;
|
||||
phy-mode = "rgmii";
|
||||
fixed-link {
|
||||
speed = <1000>;
|
||||
full-duplex;
|
||||
pause;
|
||||
};
|
||||
};
|
||||
gmac1: mac@1 {
|
||||
compatible = "mediatek,eth-mac";
|
||||
reg = <1>;
|
||||
status = "off";
|
||||
phy-mode = "rgmii";
|
||||
phy-handle = <&phy5>;
|
||||
};
|
||||
mdio-bus {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
phy1f: ethernet-phy@1f {
|
||||
reg = <0x1f>;
|
||||
phy5: ethernet-phy@5 {
|
||||
reg = <5>;
|
||||
phy-mode = "rgmii";
|
||||
};
|
||||
|
||||
switch0: switch0@0 {
|
||||
compatible = "mediatek,mt7621";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
reg = <0>;
|
||||
mediatek,mcm;
|
||||
resets = <&rstctrl 2>;
|
||||
reset-names = "mcm";
|
||||
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
reg = <0>;
|
||||
port@0 {
|
||||
status = "off";
|
||||
reg = <0>;
|
||||
label = "lan0";
|
||||
};
|
||||
port@1 {
|
||||
status = "off";
|
||||
reg = <1>;
|
||||
label = "lan1";
|
||||
};
|
||||
port@2 {
|
||||
status = "off";
|
||||
reg = <2>;
|
||||
label = "lan2";
|
||||
};
|
||||
port@3 {
|
||||
status = "off";
|
||||
reg = <3>;
|
||||
label = "lan3";
|
||||
};
|
||||
port@4 {
|
||||
status = "off";
|
||||
reg = <4>;
|
||||
label = "lan4";
|
||||
};
|
||||
port@6 {
|
||||
reg = <6>;
|
||||
label = "cpu";
|
||||
ethernet = <&gmac0>;
|
||||
phy-mode = "trgmii";
|
||||
fixed-link {
|
||||
speed = <1000>;
|
||||
full-duplex;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -1,48 +0,0 @@
|
|||
Mediatek Gigabit Switch
|
||||
=======================
|
||||
|
||||
The mediatek gigabit switch can be found on Mediatek SoCs.
|
||||
|
||||
Required properties:
|
||||
- compatible: Should be "mediatek,mt7620-gsw", "mediatek,mt7621-gsw",
|
||||
"mediatek,mt7623-gsw"
|
||||
- reg: Address and length of the register set for the device
|
||||
- interrupts: Should contain the gigabit switches interrupt
|
||||
|
||||
|
||||
Additional required properties for ARM based SoCs:
|
||||
- mediatek,reset-pin: phandle describing the reset GPIO
|
||||
- clocks: the clocks used by the switch
|
||||
- clock-names: the names of the clocks listed in the clocks property
|
||||
these should be "trgpll", "esw", "gp2", "gp1"
|
||||
- mt7530-supply: the phandle of the regulator used to power the switch
|
||||
- mediatek,pctl-regmap: phandle to the port control regmap. this is used to
|
||||
setup the drive current
|
||||
|
||||
|
||||
Optional properties:
|
||||
- interrupt-parent: Should be the phandle for the interrupt controller
|
||||
that services interrupts for this device
|
||||
|
||||
Example:
|
||||
|
||||
gsw: switch@1b100000 {
|
||||
compatible = "mediatek,mt7623-gsw";
|
||||
reg = <0 0x1b110000 0 0x300000>;
|
||||
|
||||
interrupt-parent = <&pio>;
|
||||
interrupts = <168 IRQ_TYPE_EDGE_RISING>;
|
||||
|
||||
clocks = <&apmixedsys CLK_APMIXED_TRGPLL>,
|
||||
<ðsys CLK_ETHSYS_ESW>,
|
||||
<ðsys CLK_ETHSYS_GP2>,
|
||||
<ðsys CLK_ETHSYS_GP1>;
|
||||
clock-names = "trgpll", "esw", "gp2", "gp1";
|
||||
|
||||
mt7530-supply = <&mt6323_vpa_reg>;
|
||||
|
||||
mediatek,pctl-regmap = <&syscfg_pctl_a>;
|
||||
mediatek,reset-pin = <&pio 15 0>;
|
||||
|
||||
status = "okay";
|
||||
};
|
|
@ -1,39 +0,0 @@
|
|||
config NET_VENDOR_MEDIATEK_STAGING
|
||||
bool "MediaTek ethernet driver - staging version"
|
||||
depends on RALINK
|
||||
---help---
|
||||
If you have an MT7621 Mediatek SoC with ethernet, say Y.
|
||||
|
||||
if NET_VENDOR_MEDIATEK_STAGING
|
||||
choice
|
||||
prompt "MAC type"
|
||||
|
||||
config NET_MEDIATEK_MT7621
|
||||
bool "MT7621"
|
||||
depends on MIPS && SOC_MT7621
|
||||
|
||||
endchoice
|
||||
|
||||
config NET_MEDIATEK_SOC_STAGING
|
||||
tristate "MediaTek SoC Gigabit Ethernet support"
|
||||
depends on NET_VENDOR_MEDIATEK_STAGING
|
||||
select PHYLIB
|
||||
---help---
|
||||
This driver supports the gigabit ethernet MACs in the
|
||||
MediaTek SoC family.
|
||||
|
||||
config NET_MEDIATEK_MDIO
|
||||
def_bool NET_MEDIATEK_SOC_STAGING
|
||||
depends on NET_MEDIATEK_MT7621
|
||||
select PHYLIB
|
||||
|
||||
config NET_MEDIATEK_MDIO_MT7620
|
||||
def_bool NET_MEDIATEK_SOC_STAGING
|
||||
depends on NET_MEDIATEK_MT7621
|
||||
select NET_MEDIATEK_MDIO
|
||||
|
||||
config NET_MEDIATEK_GSW_MT7621
|
||||
def_tristate NET_MEDIATEK_SOC_STAGING
|
||||
depends on NET_MEDIATEK_MT7621
|
||||
|
||||
endif #NET_VENDOR_MEDIATEK_STAGING
|
|
@ -1,14 +0,0 @@
|
|||
#
|
||||
# Makefile for the Ralink SoCs built-in ethernet macs
|
||||
#
|
||||
|
||||
mtk-eth-soc-y += mtk_eth_soc.o ethtool.o
|
||||
|
||||
mtk-eth-soc-$(CONFIG_NET_MEDIATEK_MDIO) += mdio.o
|
||||
mtk-eth-soc-$(CONFIG_NET_MEDIATEK_MDIO_MT7620) += mdio_mt7620.o
|
||||
|
||||
mtk-eth-soc-$(CONFIG_NET_MEDIATEK_MT7621) += soc_mt7621.o
|
||||
|
||||
obj-$(CONFIG_NET_MEDIATEK_GSW_MT7621) += gsw_mt7621.o
|
||||
|
||||
obj-$(CONFIG_NET_MEDIATEK_SOC_STAGING) += mtk-eth-soc.o
|
|
@ -1,13 +0,0 @@
|
|||
|
||||
- verify devicetree documentation is consistent with code
|
||||
- fix ethtool - currently doesn't return valid data.
|
||||
- general code review and clean up
|
||||
- add support for second MAC on mt7621
|
||||
- convert gsw code to use switchdev interfaces
|
||||
- md7620_mmi_write etc should probably be wrapped
|
||||
in a regmap abstraction.
|
||||
- Get soc_mt7621 to work with QDMA TX if possible.
|
||||
- Ensure phys are correctly configured when a cable
|
||||
is plugged in.
|
||||
|
||||
Cc: NeilBrown <neil@brown.name>
|
|
@ -1,250 +0,0 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/* 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; version 2 of the License
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Copyright (C) 2009-2016 John Crispin <blogic@openwrt.org>
|
||||
* Copyright (C) 2009-2016 Felix Fietkau <nbd@openwrt.org>
|
||||
* Copyright (C) 2013-2016 Michael Lee <igvtee@gmail.com>
|
||||
*/
|
||||
|
||||
#include "mtk_eth_soc.h"
|
||||
#include "ethtool.h"
|
||||
|
||||
struct mtk_stat {
|
||||
char name[ETH_GSTRING_LEN];
|
||||
unsigned int idx;
|
||||
};
|
||||
|
||||
#define MTK_HW_STAT(stat) { \
|
||||
.name = #stat, \
|
||||
.idx = offsetof(struct mtk_hw_stats, stat) / sizeof(u64) \
|
||||
}
|
||||
|
||||
static const struct mtk_stat mtk_ethtool_hw_stats[] = {
|
||||
MTK_HW_STAT(tx_bytes),
|
||||
MTK_HW_STAT(tx_packets),
|
||||
MTK_HW_STAT(tx_skip),
|
||||
MTK_HW_STAT(tx_collisions),
|
||||
MTK_HW_STAT(rx_bytes),
|
||||
MTK_HW_STAT(rx_packets),
|
||||
MTK_HW_STAT(rx_overflow),
|
||||
MTK_HW_STAT(rx_fcs_errors),
|
||||
MTK_HW_STAT(rx_short_errors),
|
||||
MTK_HW_STAT(rx_long_errors),
|
||||
MTK_HW_STAT(rx_checksum_errors),
|
||||
MTK_HW_STAT(rx_flow_control_packets),
|
||||
};
|
||||
|
||||
#define MTK_HW_STATS_LEN ARRAY_SIZE(mtk_ethtool_hw_stats)
|
||||
|
||||
static int mtk_get_link_ksettings(struct net_device *dev,
|
||||
struct ethtool_link_ksettings *cmd)
|
||||
{
|
||||
struct mtk_mac *mac = netdev_priv(dev);
|
||||
int err;
|
||||
|
||||
if (!mac->phy_dev)
|
||||
return -ENODEV;
|
||||
|
||||
if (mac->phy_flags == MTK_PHY_FLAG_ATTACH) {
|
||||
err = phy_read_status(mac->phy_dev);
|
||||
if (err)
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
phy_ethtool_ksettings_get(mac->phy_dev, cmd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mtk_set_link_ksettings(struct net_device *dev,
|
||||
const struct ethtool_link_ksettings *cmd)
|
||||
{
|
||||
struct mtk_mac *mac = netdev_priv(dev);
|
||||
|
||||
if (!mac->phy_dev)
|
||||
return -ENODEV;
|
||||
|
||||
if (cmd->base.phy_address != mac->phy_dev->mdio.addr) {
|
||||
if (mac->hw->phy->phy_node[cmd->base.phy_address]) {
|
||||
mac->phy_dev = mac->hw->phy->phy[cmd->base.phy_address];
|
||||
mac->phy_flags = MTK_PHY_FLAG_PORT;
|
||||
} else if (mac->hw->mii_bus) {
|
||||
mac->phy_dev = mdiobus_get_phy(mac->hw->mii_bus,
|
||||
cmd->base.phy_address);
|
||||
if (!mac->phy_dev)
|
||||
return -ENODEV;
|
||||
mac->phy_flags = MTK_PHY_FLAG_ATTACH;
|
||||
} else {
|
||||
return -ENODEV;
|
||||
}
|
||||
}
|
||||
|
||||
return phy_ethtool_ksettings_set(mac->phy_dev, cmd);
|
||||
}
|
||||
|
||||
static void mtk_get_drvinfo(struct net_device *dev,
|
||||
struct ethtool_drvinfo *info)
|
||||
{
|
||||
struct mtk_mac *mac = netdev_priv(dev);
|
||||
struct mtk_soc_data *soc = mac->hw->soc;
|
||||
|
||||
strlcpy(info->driver, mac->hw->dev->driver->name, sizeof(info->driver));
|
||||
strlcpy(info->bus_info, dev_name(mac->hw->dev), sizeof(info->bus_info));
|
||||
|
||||
if (soc->reg_table[MTK_REG_MTK_COUNTER_BASE])
|
||||
info->n_stats = MTK_HW_STATS_LEN;
|
||||
}
|
||||
|
||||
static u32 mtk_get_msglevel(struct net_device *dev)
|
||||
{
|
||||
struct mtk_mac *mac = netdev_priv(dev);
|
||||
|
||||
return mac->hw->msg_enable;
|
||||
}
|
||||
|
||||
static void mtk_set_msglevel(struct net_device *dev, u32 value)
|
||||
{
|
||||
struct mtk_mac *mac = netdev_priv(dev);
|
||||
|
||||
mac->hw->msg_enable = value;
|
||||
}
|
||||
|
||||
static int mtk_nway_reset(struct net_device *dev)
|
||||
{
|
||||
struct mtk_mac *mac = netdev_priv(dev);
|
||||
|
||||
if (!mac->phy_dev)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
return genphy_restart_aneg(mac->phy_dev);
|
||||
}
|
||||
|
||||
static u32 mtk_get_link(struct net_device *dev)
|
||||
{
|
||||
struct mtk_mac *mac = netdev_priv(dev);
|
||||
int err;
|
||||
|
||||
if (!mac->phy_dev)
|
||||
goto out_get_link;
|
||||
|
||||
if (mac->phy_flags == MTK_PHY_FLAG_ATTACH) {
|
||||
err = genphy_update_link(mac->phy_dev);
|
||||
if (err)
|
||||
goto out_get_link;
|
||||
}
|
||||
|
||||
return mac->phy_dev->link;
|
||||
|
||||
out_get_link:
|
||||
return ethtool_op_get_link(dev);
|
||||
}
|
||||
|
||||
static int mtk_set_ringparam(struct net_device *dev,
|
||||
struct ethtool_ringparam *ring)
|
||||
{
|
||||
struct mtk_mac *mac = netdev_priv(dev);
|
||||
|
||||
if ((ring->tx_pending < 2) ||
|
||||
(ring->rx_pending < 2) ||
|
||||
(ring->rx_pending > mac->hw->soc->dma_ring_size) ||
|
||||
(ring->tx_pending > mac->hw->soc->dma_ring_size))
|
||||
return -EINVAL;
|
||||
|
||||
dev->netdev_ops->ndo_stop(dev);
|
||||
|
||||
mac->hw->tx_ring.tx_ring_size = BIT(fls(ring->tx_pending) - 1);
|
||||
mac->hw->rx_ring[0].rx_ring_size = BIT(fls(ring->rx_pending) - 1);
|
||||
|
||||
return dev->netdev_ops->ndo_open(dev);
|
||||
}
|
||||
|
||||
static void mtk_get_ringparam(struct net_device *dev,
|
||||
struct ethtool_ringparam *ring)
|
||||
{
|
||||
struct mtk_mac *mac = netdev_priv(dev);
|
||||
|
||||
ring->rx_max_pending = mac->hw->soc->dma_ring_size;
|
||||
ring->tx_max_pending = mac->hw->soc->dma_ring_size;
|
||||
ring->rx_pending = mac->hw->rx_ring[0].rx_ring_size;
|
||||
ring->tx_pending = mac->hw->tx_ring.tx_ring_size;
|
||||
}
|
||||
|
||||
static void mtk_get_strings(struct net_device *dev, u32 stringset, u8 *data)
|
||||
{
|
||||
int i;
|
||||
|
||||
switch (stringset) {
|
||||
case ETH_SS_STATS:
|
||||
for (i = 0; i < MTK_HW_STATS_LEN; i++) {
|
||||
memcpy(data, mtk_ethtool_hw_stats[i].name,
|
||||
ETH_GSTRING_LEN);
|
||||
data += ETH_GSTRING_LEN;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int mtk_get_sset_count(struct net_device *dev, int sset)
|
||||
{
|
||||
switch (sset) {
|
||||
case ETH_SS_STATS:
|
||||
return MTK_HW_STATS_LEN;
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
}
|
||||
|
||||
static void mtk_get_ethtool_stats(struct net_device *dev,
|
||||
struct ethtool_stats *stats, u64 *data)
|
||||
{
|
||||
struct mtk_mac *mac = netdev_priv(dev);
|
||||
struct mtk_hw_stats *hwstats = mac->hw_stats;
|
||||
unsigned int start;
|
||||
int i;
|
||||
|
||||
if (netif_running(dev) && netif_device_present(dev)) {
|
||||
if (spin_trylock(&hwstats->stats_lock)) {
|
||||
mtk_stats_update_mac(mac);
|
||||
spin_unlock(&hwstats->stats_lock);
|
||||
}
|
||||
}
|
||||
|
||||
do {
|
||||
start = u64_stats_fetch_begin_irq(&hwstats->syncp);
|
||||
for (i = 0; i < MTK_HW_STATS_LEN; i++)
|
||||
data[i] = ((u64 *)hwstats)[mtk_ethtool_hw_stats[i].idx];
|
||||
|
||||
} while (u64_stats_fetch_retry_irq(&hwstats->syncp, start));
|
||||
}
|
||||
|
||||
static struct ethtool_ops mtk_ethtool_ops = {
|
||||
.get_link_ksettings = mtk_get_link_ksettings,
|
||||
.set_link_ksettings = mtk_set_link_ksettings,
|
||||
.get_drvinfo = mtk_get_drvinfo,
|
||||
.get_msglevel = mtk_get_msglevel,
|
||||
.set_msglevel = mtk_set_msglevel,
|
||||
.nway_reset = mtk_nway_reset,
|
||||
.get_link = mtk_get_link,
|
||||
.set_ringparam = mtk_set_ringparam,
|
||||
.get_ringparam = mtk_get_ringparam,
|
||||
};
|
||||
|
||||
void mtk_set_ethtool_ops(struct net_device *netdev)
|
||||
{
|
||||
struct mtk_mac *mac = netdev_priv(netdev);
|
||||
struct mtk_soc_data *soc = mac->hw->soc;
|
||||
|
||||
if (soc->reg_table[MTK_REG_MTK_COUNTER_BASE]) {
|
||||
mtk_ethtool_ops.get_strings = mtk_get_strings;
|
||||
mtk_ethtool_ops.get_sset_count = mtk_get_sset_count;
|
||||
mtk_ethtool_ops.get_ethtool_stats = mtk_get_ethtool_stats;
|
||||
}
|
||||
|
||||
netdev->ethtool_ops = &mtk_ethtool_ops;
|
||||
}
|
|
@ -1,15 +0,0 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (C) 2009-2016 John Crispin <blogic@openwrt.org>
|
||||
* Copyright (C) 2009-2016 Felix Fietkau <nbd@openwrt.org>
|
||||
* Copyright (C) 2013-2016 Michael Lee <igvtee@gmail.com>
|
||||
*/
|
||||
|
||||
#ifndef MTK_ETHTOOL_H
|
||||
#define MTK_ETHTOOL_H
|
||||
|
||||
#include <linux/ethtool.h>
|
||||
|
||||
void mtk_set_ethtool_ops(struct net_device *netdev);
|
||||
|
||||
#endif /* MTK_ETHTOOL_H */
|
|
@ -1,277 +0,0 @@
|
|||
/* 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; version 2 of the License
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Copyright (C) 2009-2016 John Crispin <blogic@openwrt.org>
|
||||
* Copyright (C) 2009-2016 Felix Fietkau <nbd@openwrt.org>
|
||||
* Copyright (C) 2013-2016 Michael Lee <igvtee@gmail.com>
|
||||
*/
|
||||
|
||||
#ifndef _RALINK_GSW_MT7620_H__
|
||||
#define _RALINK_GSW_MT7620_H__
|
||||
|
||||
#define GSW_REG_PHY_TIMEOUT (5 * HZ)
|
||||
|
||||
#define MT7620_GSW_REG_PIAC 0x0004
|
||||
|
||||
#define GSW_NUM_VLANS 16
|
||||
#define GSW_NUM_VIDS 4096
|
||||
#define GSW_NUM_PORTS 7
|
||||
#define GSW_PORT6 6
|
||||
|
||||
#define GSW_MDIO_ACCESS BIT(31)
|
||||
#define GSW_MDIO_READ BIT(19)
|
||||
#define GSW_MDIO_WRITE BIT(18)
|
||||
#define GSW_MDIO_START BIT(16)
|
||||
#define GSW_MDIO_ADDR_SHIFT 20
|
||||
#define GSW_MDIO_REG_SHIFT 25
|
||||
|
||||
#define GSW_REG_PORT_PMCR(x) (0x3000 + (x * 0x100))
|
||||
#define GSW_REG_PORT_STATUS(x) (0x3008 + (x * 0x100))
|
||||
#define GSW_REG_SMACCR0 0x3fE4
|
||||
#define GSW_REG_SMACCR1 0x3fE8
|
||||
#define GSW_REG_CKGCR 0x3ff0
|
||||
|
||||
#define GSW_REG_IMR 0x7008
|
||||
#define GSW_REG_ISR 0x700c
|
||||
#define GSW_REG_GPC1 0x7014
|
||||
|
||||
#define SYSC_REG_CHIP_REV_ID 0x0c
|
||||
#define SYSC_REG_CFG 0x10
|
||||
#define SYSC_REG_CFG1 0x14
|
||||
#define RST_CTRL_MCM BIT(2)
|
||||
#define SYSC_PAD_RGMII2_MDIO 0x58
|
||||
#define SYSC_GPIO_MODE 0x60
|
||||
|
||||
#define PORT_IRQ_ST_CHG 0x7f
|
||||
|
||||
#define MT7621_ESW_PHY_POLLING 0x0000
|
||||
#define MT7620_ESW_PHY_POLLING 0x7000
|
||||
|
||||
#define PMCR_IPG BIT(18)
|
||||
#define PMCR_MAC_MODE BIT(16)
|
||||
#define PMCR_FORCE BIT(15)
|
||||
#define PMCR_TX_EN BIT(14)
|
||||
#define PMCR_RX_EN BIT(13)
|
||||
#define PMCR_BACKOFF BIT(9)
|
||||
#define PMCR_BACKPRES BIT(8)
|
||||
#define PMCR_RX_FC BIT(5)
|
||||
#define PMCR_TX_FC BIT(4)
|
||||
#define PMCR_SPEED(_x) (_x << 2)
|
||||
#define PMCR_DUPLEX BIT(1)
|
||||
#define PMCR_LINK BIT(0)
|
||||
|
||||
#define PHY_AN_EN BIT(31)
|
||||
#define PHY_PRE_EN BIT(30)
|
||||
#define PMY_MDC_CONF(_x) ((_x & 0x3f) << 24)
|
||||
|
||||
/* ethernet subsystem config register */
|
||||
#define ETHSYS_SYSCFG0 0x14
|
||||
/* ethernet subsystem clock register */
|
||||
#define ETHSYS_CLKCFG0 0x2c
|
||||
#define ETHSYS_TRGMII_CLK_SEL362_5 BIT(11)
|
||||
|
||||
/* p5 RGMII wrapper TX clock control register */
|
||||
#define MT7530_P5RGMIITXCR 0x7b04
|
||||
/* p5 RGMII wrapper RX clock control register */
|
||||
#define MT7530_P5RGMIIRXCR 0x7b00
|
||||
/* TRGMII TDX ODT registers */
|
||||
#define MT7530_TRGMII_TD0_ODT 0x7a54
|
||||
#define MT7530_TRGMII_TD1_ODT 0x7a5c
|
||||
#define MT7530_TRGMII_TD2_ODT 0x7a64
|
||||
#define MT7530_TRGMII_TD3_ODT 0x7a6c
|
||||
#define MT7530_TRGMII_TD4_ODT 0x7a74
|
||||
#define MT7530_TRGMII_TD5_ODT 0x7a7c
|
||||
/* TRGMII TCK ctrl register */
|
||||
#define MT7530_TRGMII_TCK_CTRL 0x7a78
|
||||
/* TRGMII Tx ctrl register */
|
||||
#define MT7530_TRGMII_TXCTRL 0x7a40
|
||||
/* port 6 extended control register */
|
||||
#define MT7530_P6ECR 0x7830
|
||||
/* IO driver control register */
|
||||
#define MT7530_IO_DRV_CR 0x7810
|
||||
/* top signal control register */
|
||||
#define MT7530_TOP_SIG_CTRL 0x7808
|
||||
/* modified hwtrap register */
|
||||
#define MT7530_MHWTRAP 0x7804
|
||||
/* hwtrap status register */
|
||||
#define MT7530_HWTRAP 0x7800
|
||||
/* status interrupt register */
|
||||
#define MT7530_SYS_INT_STS 0x700c
|
||||
/* system nterrupt register */
|
||||
#define MT7530_SYS_INT_EN 0x7008
|
||||
/* system control register */
|
||||
#define MT7530_SYS_CTRL 0x7000
|
||||
/* port MAC status register */
|
||||
#define MT7530_PMSR_P(x) (0x3008 + (x * 0x100))
|
||||
/* port MAC control register */
|
||||
#define MT7530_PMCR_P(x) (0x3000 + (x * 0x100))
|
||||
|
||||
#define MT7621_XTAL_SHIFT 6
|
||||
#define MT7621_XTAL_MASK 0x7
|
||||
#define MT7621_XTAL_25 6
|
||||
#define MT7621_XTAL_40 3
|
||||
#define MT7621_MDIO_DRV_MASK (3 << 4)
|
||||
#define MT7621_GE1_MODE_MASK (3 << 12)
|
||||
|
||||
#define TRGMII_TXCTRL_TXC_INV BIT(30)
|
||||
#define P6ECR_INTF_MODE_RGMII BIT(1)
|
||||
#define P5RGMIIRXCR_C_ALIGN BIT(8)
|
||||
#define P5RGMIIRXCR_DELAY_2 BIT(1)
|
||||
#define P5RGMIITXCR_DELAY_2 (BIT(8) | BIT(2))
|
||||
|
||||
/* TOP_SIG_CTRL bits */
|
||||
#define TOP_SIG_CTRL_NORMAL (BIT(17) | BIT(16))
|
||||
|
||||
/* MHWTRAP bits */
|
||||
#define MHWTRAP_MANUAL BIT(16)
|
||||
#define MHWTRAP_P5_MAC_SEL BIT(13)
|
||||
#define MHWTRAP_P6_DIS BIT(8)
|
||||
#define MHWTRAP_P5_RGMII_MODE BIT(7)
|
||||
#define MHWTRAP_P5_DIS BIT(6)
|
||||
#define MHWTRAP_PHY_ACCESS BIT(5)
|
||||
|
||||
/* HWTRAP bits */
|
||||
#define HWTRAP_XTAL_SHIFT 9
|
||||
#define HWTRAP_XTAL_MASK 0x3
|
||||
|
||||
/* SYS_CTRL bits */
|
||||
#define SYS_CTRL_SW_RST BIT(1)
|
||||
#define SYS_CTRL_REG_RST BIT(0)
|
||||
|
||||
/* PMCR bits */
|
||||
#define PMCR_IFG_XMIT_96 BIT(18)
|
||||
#define PMCR_MAC_MODE BIT(16)
|
||||
#define PMCR_FORCE_MODE BIT(15)
|
||||
#define PMCR_TX_EN BIT(14)
|
||||
#define PMCR_RX_EN BIT(13)
|
||||
#define PMCR_BACK_PRES_EN BIT(9)
|
||||
#define PMCR_BACKOFF_EN BIT(8)
|
||||
#define PMCR_TX_FC_EN BIT(5)
|
||||
#define PMCR_RX_FC_EN BIT(4)
|
||||
#define PMCR_FORCE_SPEED_1000 BIT(3)
|
||||
#define PMCR_FORCE_FDX BIT(1)
|
||||
#define PMCR_FORCE_LNK BIT(0)
|
||||
#define PMCR_FIXED_LINK (PMCR_IFG_XMIT_96 | PMCR_MAC_MODE | \
|
||||
PMCR_FORCE_MODE | PMCR_TX_EN | PMCR_RX_EN | \
|
||||
PMCR_BACK_PRES_EN | PMCR_BACKOFF_EN | \
|
||||
PMCR_FORCE_SPEED_1000 | PMCR_FORCE_FDX | \
|
||||
PMCR_FORCE_LNK)
|
||||
|
||||
#define PMCR_FIXED_LINK_FC (PMCR_FIXED_LINK | \
|
||||
PMCR_TX_FC_EN | PMCR_RX_FC_EN)
|
||||
|
||||
/* TRGMII control registers */
|
||||
#define GSW_INTF_MODE 0x390
|
||||
#define GSW_TRGMII_TD0_ODT 0x354
|
||||
#define GSW_TRGMII_TD1_ODT 0x35c
|
||||
#define GSW_TRGMII_TD2_ODT 0x364
|
||||
#define GSW_TRGMII_TD3_ODT 0x36c
|
||||
#define GSW_TRGMII_TXCTL_ODT 0x374
|
||||
#define GSW_TRGMII_TCK_ODT 0x37c
|
||||
#define GSW_TRGMII_RCK_CTRL 0x300
|
||||
|
||||
#define INTF_MODE_TRGMII BIT(1)
|
||||
#define TRGMII_RCK_CTRL_RX_RST BIT(31)
|
||||
|
||||
/* Mac control registers */
|
||||
#define MTK_MAC_P2_MCR 0x200
|
||||
#define MTK_MAC_P1_MCR 0x100
|
||||
|
||||
#define MAC_MCR_MAX_RX_2K BIT(29)
|
||||
#define MAC_MCR_IPG_CFG (BIT(18) | BIT(16))
|
||||
#define MAC_MCR_FORCE_MODE BIT(15)
|
||||
#define MAC_MCR_TX_EN BIT(14)
|
||||
#define MAC_MCR_RX_EN BIT(13)
|
||||
#define MAC_MCR_BACKOFF_EN BIT(9)
|
||||
#define MAC_MCR_BACKPR_EN BIT(8)
|
||||
#define MAC_MCR_FORCE_RX_FC BIT(5)
|
||||
#define MAC_MCR_FORCE_TX_FC BIT(4)
|
||||
#define MAC_MCR_SPEED_1000 BIT(3)
|
||||
#define MAC_MCR_FORCE_DPX BIT(1)
|
||||
#define MAC_MCR_FORCE_LINK BIT(0)
|
||||
#define MAC_MCR_FIXED_LINK (MAC_MCR_MAX_RX_2K | MAC_MCR_IPG_CFG | \
|
||||
MAC_MCR_FORCE_MODE | MAC_MCR_TX_EN | \
|
||||
MAC_MCR_RX_EN | MAC_MCR_BACKOFF_EN | \
|
||||
MAC_MCR_BACKPR_EN | MAC_MCR_FORCE_RX_FC | \
|
||||
MAC_MCR_FORCE_TX_FC | MAC_MCR_SPEED_1000 | \
|
||||
MAC_MCR_FORCE_DPX | MAC_MCR_FORCE_LINK)
|
||||
#define MAC_MCR_FIXED_LINK_FC (MAC_MCR_MAX_RX_2K | MAC_MCR_IPG_CFG | \
|
||||
MAC_MCR_FIXED_LINK)
|
||||
|
||||
/* possible XTAL speed */
|
||||
#define MT7623_XTAL_40 0
|
||||
#define MT7623_XTAL_20 1
|
||||
#define MT7623_XTAL_25 3
|
||||
|
||||
/* GPIO port control registers */
|
||||
#define GPIO_OD33_CTRL8 0x4c0
|
||||
#define GPIO_BIAS_CTRL 0xed0
|
||||
#define GPIO_DRV_SEL10 0xf00
|
||||
|
||||
/* on MT7620 the functio of port 4 can be software configured */
|
||||
enum {
|
||||
PORT4_EPHY = 0,
|
||||
PORT4_EXT,
|
||||
};
|
||||
|
||||
/* struct mt7620_gsw - the structure that holds the SoC specific data
|
||||
* @dev: The Device struct
|
||||
* @base: The base address
|
||||
* @piac_offset: The PIAC base may change depending on SoC
|
||||
* @irq: The IRQ we are using
|
||||
* @port4: The port4 mode on MT7620
|
||||
* @autopoll: Is MDIO autopolling enabled
|
||||
* @ethsys: The ethsys register map
|
||||
* @pctl: The pin control register map
|
||||
* @clk_gsw: The switch clock
|
||||
* @clk_gp1: The gmac1 clock
|
||||
* @clk_gp2: The gmac2 clock
|
||||
* @clk_trgpll: The trgmii pll clock
|
||||
*/
|
||||
struct mt7620_gsw {
|
||||
struct device *dev;
|
||||
void __iomem *base;
|
||||
u32 piac_offset;
|
||||
int irq;
|
||||
int port4;
|
||||
unsigned long int autopoll;
|
||||
|
||||
struct regmap *ethsys;
|
||||
struct regmap *pctl;
|
||||
|
||||
struct clk *clk_gsw;
|
||||
struct clk *clk_gp1;
|
||||
struct clk *clk_gp2;
|
||||
struct clk *clk_trgpll;
|
||||
};
|
||||
|
||||
/* switch register I/O wrappers */
|
||||
void mtk_switch_w32(struct mt7620_gsw *gsw, u32 val, unsigned int reg);
|
||||
u32 mtk_switch_r32(struct mt7620_gsw *gsw, unsigned int reg);
|
||||
|
||||
/* the callback used by the driver core to bringup the switch */
|
||||
int mtk_gsw_init(struct mtk_eth *eth);
|
||||
|
||||
/* MDIO access wrappers */
|
||||
int mt7620_mdio_write(struct mii_bus *bus, int phy_addr, int phy_reg, u16 val);
|
||||
int mt7620_mdio_read(struct mii_bus *bus, int phy_addr, int phy_reg);
|
||||
void mt7620_mdio_link_adjust(struct mtk_eth *eth, int port);
|
||||
int mt7620_has_carrier(struct mtk_eth *eth);
|
||||
void mt7620_print_link_state(struct mtk_eth *eth, int port, int link,
|
||||
int speed, int duplex);
|
||||
void mt7530_mdio_w32(struct mt7620_gsw *gsw, u32 reg, u32 val);
|
||||
u32 mt7530_mdio_r32(struct mt7620_gsw *gsw, u32 reg);
|
||||
void mt7530_mdio_m32(struct mt7620_gsw *gsw, u32 mask, u32 set, u32 reg);
|
||||
|
||||
u32 _mt7620_mii_write(struct mt7620_gsw *gsw, u32 phy_addr,
|
||||
u32 phy_register, u32 write_data);
|
||||
u32 _mt7620_mii_read(struct mt7620_gsw *gsw, int phy_addr, int phy_reg);
|
||||
void mt7620_handle_carrier(struct mtk_eth *eth);
|
||||
|
||||
#endif
|
|
@ -1,297 +0,0 @@
|
|||
/* 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; version 2 of the License
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Copyright (C) 2009-2016 John Crispin <blogic@openwrt.org>
|
||||
* Copyright (C) 2009-2016 Felix Fietkau <nbd@openwrt.org>
|
||||
* Copyright (C) 2013-2016 Michael Lee <igvtee@gmail.com>
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of_irq.h>
|
||||
|
||||
#include <ralink_regs.h>
|
||||
|
||||
#include "mtk_eth_soc.h"
|
||||
#include "gsw_mt7620.h"
|
||||
|
||||
void mtk_switch_w32(struct mt7620_gsw *gsw, u32 val, unsigned int reg)
|
||||
{
|
||||
iowrite32(val, gsw->base + reg);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mtk_switch_w32);
|
||||
|
||||
u32 mtk_switch_r32(struct mt7620_gsw *gsw, unsigned int reg)
|
||||
{
|
||||
return ioread32(gsw->base + reg);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mtk_switch_r32);
|
||||
|
||||
static irqreturn_t gsw_interrupt_mt7621(int irq, void *_eth)
|
||||
{
|
||||
struct mtk_eth *eth = (struct mtk_eth *)_eth;
|
||||
struct mt7620_gsw *gsw = (struct mt7620_gsw *)eth->sw_priv;
|
||||
u32 reg, i;
|
||||
|
||||
reg = mt7530_mdio_r32(gsw, MT7530_SYS_INT_STS);
|
||||
|
||||
for (i = 0; i < 5; i++) {
|
||||
unsigned int link;
|
||||
|
||||
if ((reg & BIT(i)) == 0)
|
||||
continue;
|
||||
|
||||
link = mt7530_mdio_r32(gsw, MT7530_PMSR_P(i)) & 0x1;
|
||||
|
||||
if (link == eth->link[i])
|
||||
continue;
|
||||
|
||||
eth->link[i] = link;
|
||||
if (link)
|
||||
netdev_info(*eth->netdev,
|
||||
"port %d link up\n", i);
|
||||
else
|
||||
netdev_info(*eth->netdev,
|
||||
"port %d link down\n", i);
|
||||
}
|
||||
|
||||
mt7530_mdio_w32(gsw, MT7530_SYS_INT_STS, 0x1f);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static void mt7621_hw_init(struct mtk_eth *eth, struct mt7620_gsw *gsw,
|
||||
struct device_node *np)
|
||||
{
|
||||
u32 i;
|
||||
u32 val;
|
||||
|
||||
/* hardware reset the switch */
|
||||
mtk_reset(eth, RST_CTRL_MCM);
|
||||
mdelay(10);
|
||||
|
||||
/* reduce RGMII2 PAD driving strength */
|
||||
rt_sysc_m32(MT7621_MDIO_DRV_MASK, 0, SYSC_PAD_RGMII2_MDIO);
|
||||
|
||||
/* gpio mux - RGMII1=Normal mode */
|
||||
rt_sysc_m32(BIT(14), 0, SYSC_GPIO_MODE);
|
||||
|
||||
/* set GMAC1 RGMII mode */
|
||||
rt_sysc_m32(MT7621_GE1_MODE_MASK, 0, SYSC_REG_CFG1);
|
||||
|
||||
/* enable MDIO to control MT7530 */
|
||||
rt_sysc_m32(3 << 12, 0, SYSC_GPIO_MODE);
|
||||
|
||||
/* turn off all PHYs */
|
||||
for (i = 0; i <= 4; i++) {
|
||||
val = _mt7620_mii_read(gsw, i, 0x0);
|
||||
val |= BIT(11);
|
||||
_mt7620_mii_write(gsw, i, 0x0, val);
|
||||
}
|
||||
|
||||
/* reset the switch */
|
||||
mt7530_mdio_w32(gsw, MT7530_SYS_CTRL,
|
||||
SYS_CTRL_SW_RST | SYS_CTRL_REG_RST);
|
||||
usleep_range(10, 20);
|
||||
|
||||
if ((rt_sysc_r32(SYSC_REG_CHIP_REV_ID) & 0xFFFF) == 0x0101) {
|
||||
/* GE1, Force 1000M/FD, FC ON, MAX_RX_LENGTH 1536 */
|
||||
mtk_switch_w32(gsw, MAC_MCR_FIXED_LINK, MTK_MAC_P2_MCR);
|
||||
mt7530_mdio_w32(gsw, MT7530_PMCR_P(6), PMCR_FIXED_LINK);
|
||||
} else {
|
||||
/* GE1, Force 1000M/FD, FC ON, MAX_RX_LENGTH 1536 */
|
||||
mtk_switch_w32(gsw, MAC_MCR_FIXED_LINK_FC, MTK_MAC_P1_MCR);
|
||||
mt7530_mdio_w32(gsw, MT7530_PMCR_P(6), PMCR_FIXED_LINK_FC);
|
||||
}
|
||||
|
||||
/* GE2, Link down */
|
||||
mtk_switch_w32(gsw, MAC_MCR_FORCE_MODE, MTK_MAC_P2_MCR);
|
||||
|
||||
/* Enable Port 6, P5 as GMAC5, P5 disable */
|
||||
val = mt7530_mdio_r32(gsw, MT7530_MHWTRAP);
|
||||
/* Enable Port 6 */
|
||||
val &= ~MHWTRAP_P6_DIS;
|
||||
/* Disable Port 5 */
|
||||
val |= MHWTRAP_P5_DIS;
|
||||
/* manual override of HW-Trap */
|
||||
val |= MHWTRAP_MANUAL;
|
||||
mt7530_mdio_w32(gsw, MT7530_MHWTRAP, val);
|
||||
|
||||
val = rt_sysc_r32(SYSC_REG_CFG);
|
||||
val = (val >> MT7621_XTAL_SHIFT) & MT7621_XTAL_MASK;
|
||||
if (val < MT7621_XTAL_25 && val >= MT7621_XTAL_40) {
|
||||
/* 40Mhz */
|
||||
|
||||
/* disable MT7530 core clock */
|
||||
_mt7620_mii_write(gsw, 0, 13, 0x1f);
|
||||
_mt7620_mii_write(gsw, 0, 14, 0x410);
|
||||
_mt7620_mii_write(gsw, 0, 13, 0x401f);
|
||||
_mt7620_mii_write(gsw, 0, 14, 0x0);
|
||||
|
||||
/* disable MT7530 PLL */
|
||||
_mt7620_mii_write(gsw, 0, 13, 0x1f);
|
||||
_mt7620_mii_write(gsw, 0, 14, 0x40d);
|
||||
_mt7620_mii_write(gsw, 0, 13, 0x401f);
|
||||
_mt7620_mii_write(gsw, 0, 14, 0x2020);
|
||||
|
||||
/* for MT7530 core clock = 500Mhz */
|
||||
_mt7620_mii_write(gsw, 0, 13, 0x1f);
|
||||
_mt7620_mii_write(gsw, 0, 14, 0x40e);
|
||||
_mt7620_mii_write(gsw, 0, 13, 0x401f);
|
||||
_mt7620_mii_write(gsw, 0, 14, 0x119);
|
||||
|
||||
/* enable MT7530 PLL */
|
||||
_mt7620_mii_write(gsw, 0, 13, 0x1f);
|
||||
_mt7620_mii_write(gsw, 0, 14, 0x40d);
|
||||
_mt7620_mii_write(gsw, 0, 13, 0x401f);
|
||||
_mt7620_mii_write(gsw, 0, 14, 0x2820);
|
||||
|
||||
usleep_range(20, 40);
|
||||
|
||||
/* enable MT7530 core clock */
|
||||
_mt7620_mii_write(gsw, 0, 13, 0x1f);
|
||||
_mt7620_mii_write(gsw, 0, 14, 0x410);
|
||||
_mt7620_mii_write(gsw, 0, 13, 0x401f);
|
||||
}
|
||||
|
||||
/* RGMII */
|
||||
_mt7620_mii_write(gsw, 0, 14, 0x1);
|
||||
|
||||
/* set MT7530 central align */
|
||||
mt7530_mdio_m32(gsw, BIT(0), P6ECR_INTF_MODE_RGMII, MT7530_P6ECR);
|
||||
mt7530_mdio_m32(gsw, TRGMII_TXCTRL_TXC_INV, 0,
|
||||
MT7530_TRGMII_TXCTRL);
|
||||
mt7530_mdio_w32(gsw, MT7530_TRGMII_TCK_CTRL, 0x855);
|
||||
|
||||
/* delay setting for 10/1000M */
|
||||
mt7530_mdio_w32(gsw, MT7530_P5RGMIIRXCR,
|
||||
P5RGMIIRXCR_C_ALIGN | P5RGMIIRXCR_DELAY_2);
|
||||
mt7530_mdio_w32(gsw, MT7530_P5RGMIITXCR, 0x14);
|
||||
|
||||
/* lower Tx Driving*/
|
||||
mt7530_mdio_w32(gsw, MT7530_TRGMII_TD0_ODT, 0x44);
|
||||
mt7530_mdio_w32(gsw, MT7530_TRGMII_TD1_ODT, 0x44);
|
||||
mt7530_mdio_w32(gsw, MT7530_TRGMII_TD2_ODT, 0x44);
|
||||
mt7530_mdio_w32(gsw, MT7530_TRGMII_TD3_ODT, 0x44);
|
||||
mt7530_mdio_w32(gsw, MT7530_TRGMII_TD4_ODT, 0x44);
|
||||
mt7530_mdio_w32(gsw, MT7530_TRGMII_TD5_ODT, 0x44);
|
||||
|
||||
/* turn on all PHYs */
|
||||
for (i = 0; i <= 4; i++) {
|
||||
val = _mt7620_mii_read(gsw, i, 0);
|
||||
val &= ~BIT(11);
|
||||
_mt7620_mii_write(gsw, i, 0, val);
|
||||
}
|
||||
|
||||
#define MT7530_NUM_PORTS 8
|
||||
#define REG_ESW_PORT_PCR(x) (0x2004 | ((x) << 8))
|
||||
#define REG_ESW_PORT_PVC(x) (0x2010 | ((x) << 8))
|
||||
#define REG_ESW_PORT_PPBV1(x) (0x2014 | ((x) << 8))
|
||||
#define MT7530_CPU_PORT 6
|
||||
|
||||
/* This is copied from mt7530_apply_config in libreCMC driver */
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MT7530_NUM_PORTS; i++)
|
||||
mt7530_mdio_w32(gsw, REG_ESW_PORT_PCR(i), 0x00400000);
|
||||
|
||||
mt7530_mdio_w32(gsw, REG_ESW_PORT_PCR(MT7530_CPU_PORT),
|
||||
0x00ff0000);
|
||||
|
||||
for (i = 0; i < MT7530_NUM_PORTS; i++)
|
||||
mt7530_mdio_w32(gsw, REG_ESW_PORT_PVC(i), 0x810000c0);
|
||||
}
|
||||
|
||||
/* enable irq */
|
||||
mt7530_mdio_m32(gsw, 0, 3 << 16, MT7530_TOP_SIG_CTRL);
|
||||
mt7530_mdio_w32(gsw, MT7530_SYS_INT_EN, 0x1f);
|
||||
}
|
||||
|
||||
static const struct of_device_id mediatek_gsw_match[] = {
|
||||
{ .compatible = "mediatek,mt7621-gsw" },
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, mediatek_gsw_match);
|
||||
|
||||
int mtk_gsw_init(struct mtk_eth *eth)
|
||||
{
|
||||
struct device_node *np = eth->switch_np;
|
||||
struct platform_device *pdev = of_find_device_by_node(np);
|
||||
struct mt7620_gsw *gsw;
|
||||
|
||||
if (!pdev)
|
||||
return -ENODEV;
|
||||
|
||||
if (!of_device_is_compatible(np, mediatek_gsw_match->compatible))
|
||||
return -EINVAL;
|
||||
|
||||
gsw = platform_get_drvdata(pdev);
|
||||
eth->sw_priv = gsw;
|
||||
|
||||
if (!gsw->irq)
|
||||
return -EINVAL;
|
||||
|
||||
request_irq(gsw->irq, gsw_interrupt_mt7621, 0,
|
||||
"gsw", eth);
|
||||
disable_irq(gsw->irq);
|
||||
|
||||
mt7621_hw_init(eth, gsw, np);
|
||||
|
||||
enable_irq(gsw->irq);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mtk_gsw_init);
|
||||
|
||||
static int mt7621_gsw_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
struct mt7620_gsw *gsw;
|
||||
|
||||
gsw = devm_kzalloc(&pdev->dev, sizeof(struct mt7620_gsw), GFP_KERNEL);
|
||||
if (!gsw)
|
||||
return -ENOMEM;
|
||||
|
||||
gsw->base = devm_ioremap_resource(&pdev->dev, res);
|
||||
if (IS_ERR(gsw->base))
|
||||
return PTR_ERR(gsw->base);
|
||||
|
||||
gsw->dev = &pdev->dev;
|
||||
gsw->irq = irq_of_parse_and_map(pdev->dev.of_node, 0);
|
||||
|
||||
platform_set_drvdata(pdev, gsw);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mt7621_gsw_remove(struct platform_device *pdev)
|
||||
{
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver gsw_driver = {
|
||||
.probe = mt7621_gsw_probe,
|
||||
.remove = mt7621_gsw_remove,
|
||||
.driver = {
|
||||
.name = "mt7621-gsw",
|
||||
.of_match_table = mediatek_gsw_match,
|
||||
},
|
||||
};
|
||||
|
||||
module_platform_driver(gsw_driver);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("John Crispin <blogic@openwrt.org>");
|
||||
MODULE_DESCRIPTION("GBit switch driver for Mediatek MT7621 SoC");
|
|
@ -1,275 +0,0 @@
|
|||
/* 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; version 2 of the License
|
||||
*
|
||||
* Copyright (C) 2009-2016 John Crispin <blogic@openwrt.org>
|
||||
* Copyright (C) 2009-2016 Felix Fietkau <nbd@openwrt.org>
|
||||
* Copyright (C) 2013-2016 Michael Lee <igvtee@gmail.com>
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/phy.h>
|
||||
#include <linux/of_net.h>
|
||||
#include <linux/of_mdio.h>
|
||||
|
||||
#include "mtk_eth_soc.h"
|
||||
#include "mdio.h"
|
||||
|
||||
static int mtk_mdio_reset(struct mii_bus *bus)
|
||||
{
|
||||
/* TODO */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mtk_phy_link_adjust(struct net_device *dev)
|
||||
{
|
||||
struct mtk_eth *eth = netdev_priv(dev);
|
||||
unsigned long flags;
|
||||
int i;
|
||||
|
||||
spin_lock_irqsave(ð->phy->lock, flags);
|
||||
for (i = 0; i < 8; i++) {
|
||||
if (eth->phy->phy_node[i]) {
|
||||
struct phy_device *phydev = eth->phy->phy[i];
|
||||
int status_change = 0;
|
||||
|
||||
if (phydev->link)
|
||||
if (eth->phy->duplex[i] != phydev->duplex ||
|
||||
eth->phy->speed[i] != phydev->speed)
|
||||
status_change = 1;
|
||||
|
||||
if (phydev->link != eth->link[i])
|
||||
status_change = 1;
|
||||
|
||||
switch (phydev->speed) {
|
||||
case SPEED_1000:
|
||||
case SPEED_100:
|
||||
case SPEED_10:
|
||||
eth->link[i] = phydev->link;
|
||||
eth->phy->duplex[i] = phydev->duplex;
|
||||
eth->phy->speed[i] = phydev->speed;
|
||||
|
||||
if (status_change &&
|
||||
eth->soc->mdio_adjust_link)
|
||||
eth->soc->mdio_adjust_link(eth, i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
spin_unlock_irqrestore(ð->phy->lock, flags);
|
||||
}
|
||||
|
||||
int mtk_connect_phy_node(struct mtk_eth *eth, struct mtk_mac *mac,
|
||||
struct device_node *phy_node)
|
||||
{
|
||||
const __be32 *_port = NULL;
|
||||
struct phy_device *phydev;
|
||||
int phy_mode, port;
|
||||
|
||||
_port = of_get_property(phy_node, "reg", NULL);
|
||||
|
||||
if (!_port || (be32_to_cpu(*_port) >= 0x20)) {
|
||||
pr_err("%pOFn: invalid port id\n", phy_node);
|
||||
return -EINVAL;
|
||||
}
|
||||
port = be32_to_cpu(*_port);
|
||||
phy_mode = of_get_phy_mode(phy_node);
|
||||
if (phy_mode < 0) {
|
||||
dev_err(eth->dev, "incorrect phy-mode %d\n", phy_mode);
|
||||
eth->phy->phy_node[port] = NULL;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
phydev = of_phy_connect(eth->netdev[mac->id], phy_node,
|
||||
mtk_phy_link_adjust, 0, phy_mode);
|
||||
if (!phydev) {
|
||||
dev_err(eth->dev, "could not connect to PHY\n");
|
||||
eth->phy->phy_node[port] = NULL;
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
phydev->supported &= PHY_1000BT_FEATURES;
|
||||
phydev->advertising = phydev->supported;
|
||||
|
||||
dev_info(eth->dev,
|
||||
"connected port %d to PHY at %s [uid=%08x, driver=%s]\n",
|
||||
port, phydev_name(phydev), phydev->phy_id,
|
||||
phydev->drv->name);
|
||||
|
||||
eth->phy->phy[port] = phydev;
|
||||
eth->link[port] = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void phy_init(struct mtk_eth *eth, struct mtk_mac *mac,
|
||||
struct phy_device *phy)
|
||||
{
|
||||
phy_attach(eth->netdev[mac->id], phydev_name(phy),
|
||||
PHY_INTERFACE_MODE_MII);
|
||||
|
||||
phy->autoneg = AUTONEG_ENABLE;
|
||||
phy->speed = 0;
|
||||
phy->duplex = 0;
|
||||
phy_set_max_speed(phy, SPEED_100);
|
||||
phy->advertising = phy->supported | ADVERTISED_Autoneg;
|
||||
|
||||
phy_start_aneg(phy);
|
||||
}
|
||||
|
||||
static int mtk_phy_connect(struct mtk_mac *mac)
|
||||
{
|
||||
struct mtk_eth *eth = mac->hw;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
if (eth->phy->phy_node[i]) {
|
||||
if (!mac->phy_dev) {
|
||||
mac->phy_dev = eth->phy->phy[i];
|
||||
mac->phy_flags = MTK_PHY_FLAG_PORT;
|
||||
}
|
||||
} else if (eth->mii_bus) {
|
||||
struct phy_device *phy;
|
||||
|
||||
phy = mdiobus_get_phy(eth->mii_bus, i);
|
||||
if (phy) {
|
||||
phy_init(eth, mac, phy);
|
||||
if (!mac->phy_dev) {
|
||||
mac->phy_dev = phy;
|
||||
mac->phy_flags = MTK_PHY_FLAG_ATTACH;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mtk_phy_disconnect(struct mtk_mac *mac)
|
||||
{
|
||||
struct mtk_eth *eth = mac->hw;
|
||||
unsigned long flags;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 8; i++)
|
||||
if (eth->phy->phy_fixed[i]) {
|
||||
spin_lock_irqsave(ð->phy->lock, flags);
|
||||
eth->link[i] = 0;
|
||||
if (eth->soc->mdio_adjust_link)
|
||||
eth->soc->mdio_adjust_link(eth, i);
|
||||
spin_unlock_irqrestore(ð->phy->lock, flags);
|
||||
} else if (eth->phy->phy[i]) {
|
||||
phy_disconnect(eth->phy->phy[i]);
|
||||
} else if (eth->mii_bus) {
|
||||
struct phy_device *phy =
|
||||
mdiobus_get_phy(eth->mii_bus, i);
|
||||
|
||||
if (phy)
|
||||
phy_detach(phy);
|
||||
}
|
||||
}
|
||||
|
||||
static void mtk_phy_start(struct mtk_mac *mac)
|
||||
{
|
||||
struct mtk_eth *eth = mac->hw;
|
||||
unsigned long flags;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
if (eth->phy->phy_fixed[i]) {
|
||||
spin_lock_irqsave(ð->phy->lock, flags);
|
||||
eth->link[i] = 1;
|
||||
if (eth->soc->mdio_adjust_link)
|
||||
eth->soc->mdio_adjust_link(eth, i);
|
||||
spin_unlock_irqrestore(ð->phy->lock, flags);
|
||||
} else if (eth->phy->phy[i]) {
|
||||
phy_start(eth->phy->phy[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void mtk_phy_stop(struct mtk_mac *mac)
|
||||
{
|
||||
struct mtk_eth *eth = mac->hw;
|
||||
unsigned long flags;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 8; i++)
|
||||
if (eth->phy->phy_fixed[i]) {
|
||||
spin_lock_irqsave(ð->phy->lock, flags);
|
||||
eth->link[i] = 0;
|
||||
if (eth->soc->mdio_adjust_link)
|
||||
eth->soc->mdio_adjust_link(eth, i);
|
||||
spin_unlock_irqrestore(ð->phy->lock, flags);
|
||||
} else if (eth->phy->phy[i]) {
|
||||
phy_stop(eth->phy->phy[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static struct mtk_phy phy_ralink = {
|
||||
.connect = mtk_phy_connect,
|
||||
.disconnect = mtk_phy_disconnect,
|
||||
.start = mtk_phy_start,
|
||||
.stop = mtk_phy_stop,
|
||||
};
|
||||
|
||||
int mtk_mdio_init(struct mtk_eth *eth)
|
||||
{
|
||||
struct device_node *mii_np;
|
||||
int err;
|
||||
|
||||
if (!eth->soc->mdio_read || !eth->soc->mdio_write)
|
||||
return 0;
|
||||
|
||||
spin_lock_init(&phy_ralink.lock);
|
||||
eth->phy = &phy_ralink;
|
||||
|
||||
mii_np = of_get_child_by_name(eth->dev->of_node, "mdio-bus");
|
||||
if (!mii_np) {
|
||||
dev_err(eth->dev, "no %s child node found", "mdio-bus");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (!of_device_is_available(mii_np)) {
|
||||
err = 0;
|
||||
goto err_put_node;
|
||||
}
|
||||
|
||||
eth->mii_bus = mdiobus_alloc();
|
||||
if (!eth->mii_bus) {
|
||||
err = -ENOMEM;
|
||||
goto err_put_node;
|
||||
}
|
||||
|
||||
eth->mii_bus->name = "mdio";
|
||||
eth->mii_bus->read = eth->soc->mdio_read;
|
||||
eth->mii_bus->write = eth->soc->mdio_write;
|
||||
eth->mii_bus->reset = mtk_mdio_reset;
|
||||
eth->mii_bus->priv = eth;
|
||||
eth->mii_bus->parent = eth->dev;
|
||||
|
||||
snprintf(eth->mii_bus->id, MII_BUS_ID_SIZE, "%pOFn", mii_np);
|
||||
err = of_mdiobus_register(eth->mii_bus, mii_np);
|
||||
if (err)
|
||||
goto err_free_bus;
|
||||
|
||||
return 0;
|
||||
|
||||
err_free_bus:
|
||||
kfree(eth->mii_bus);
|
||||
err_put_node:
|
||||
of_node_put(mii_np);
|
||||
eth->mii_bus = NULL;
|
||||
return err;
|
||||
}
|
||||
|
||||
void mtk_mdio_cleanup(struct mtk_eth *eth)
|
||||
{
|
||||
if (!eth->mii_bus)
|
||||
return;
|
||||
|
||||
mdiobus_unregister(eth->mii_bus);
|
||||
of_node_put(eth->mii_bus->dev.of_node);
|
||||
kfree(eth->mii_bus);
|
||||
}
|
|
@ -1,27 +0,0 @@
|
|||
/* 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; version 2 of the License
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Copyright (C) 2009-2016 John Crispin <blogic@openwrt.org>
|
||||
* Copyright (C) 2009-2016 Felix Fietkau <nbd@openwrt.org>
|
||||
* Copyright (C) 2013-2016 Michael Lee <igvtee@gmail.com>
|
||||
*/
|
||||
|
||||
#ifndef _RALINK_MDIO_H__
|
||||
#define _RALINK_MDIO_H__
|
||||
|
||||
#ifdef CONFIG_NET_MEDIATEK_MDIO
|
||||
int mtk_mdio_init(struct mtk_eth *eth);
|
||||
void mtk_mdio_cleanup(struct mtk_eth *eth);
|
||||
int mtk_connect_phy_node(struct mtk_eth *eth, struct mtk_mac *mac,
|
||||
struct device_node *phy_node);
|
||||
#else
|
||||
static inline int mtk_mdio_init(struct mtk_eth *eth) { return 0; }
|
||||
static inline void mtk_mdio_cleanup(struct mtk_eth *eth) {}
|
||||
#endif
|
||||
#endif
|
|
@ -1,173 +0,0 @@
|
|||
/* 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; version 2 of the License
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Copyright (C) 2009-2016 John Crispin <blogic@openwrt.org>
|
||||
* Copyright (C) 2009-2016 Felix Fietkau <nbd@openwrt.org>
|
||||
* Copyright (C) 2013-2016 Michael Lee <igvtee@gmail.com>
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
#include "mtk_eth_soc.h"
|
||||
#include "gsw_mt7620.h"
|
||||
#include "mdio.h"
|
||||
|
||||
static int mt7620_mii_busy_wait(struct mt7620_gsw *gsw)
|
||||
{
|
||||
unsigned long t_start = jiffies;
|
||||
|
||||
while (1) {
|
||||
if (!(mtk_switch_r32(gsw,
|
||||
gsw->piac_offset + MT7620_GSW_REG_PIAC) &
|
||||
GSW_MDIO_ACCESS))
|
||||
return 0;
|
||||
if (time_after(jiffies, t_start + GSW_REG_PHY_TIMEOUT))
|
||||
break;
|
||||
}
|
||||
|
||||
dev_err(gsw->dev, "mdio: MDIO timeout\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
u32 _mt7620_mii_write(struct mt7620_gsw *gsw, u32 phy_addr,
|
||||
u32 phy_register, u32 write_data)
|
||||
{
|
||||
if (mt7620_mii_busy_wait(gsw))
|
||||
return -1;
|
||||
|
||||
write_data &= 0xffff;
|
||||
|
||||
mtk_switch_w32(gsw, GSW_MDIO_ACCESS | GSW_MDIO_START | GSW_MDIO_WRITE |
|
||||
(phy_register << GSW_MDIO_REG_SHIFT) |
|
||||
(phy_addr << GSW_MDIO_ADDR_SHIFT) | write_data,
|
||||
MT7620_GSW_REG_PIAC);
|
||||
|
||||
if (mt7620_mii_busy_wait(gsw))
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(_mt7620_mii_write);
|
||||
|
||||
u32 _mt7620_mii_read(struct mt7620_gsw *gsw, int phy_addr, int phy_reg)
|
||||
{
|
||||
u32 d;
|
||||
|
||||
if (mt7620_mii_busy_wait(gsw))
|
||||
return 0xffff;
|
||||
|
||||
mtk_switch_w32(gsw, GSW_MDIO_ACCESS | GSW_MDIO_START | GSW_MDIO_READ |
|
||||
(phy_reg << GSW_MDIO_REG_SHIFT) |
|
||||
(phy_addr << GSW_MDIO_ADDR_SHIFT),
|
||||
MT7620_GSW_REG_PIAC);
|
||||
|
||||
if (mt7620_mii_busy_wait(gsw))
|
||||
return 0xffff;
|
||||
|
||||
d = mtk_switch_r32(gsw, MT7620_GSW_REG_PIAC) & 0xffff;
|
||||
|
||||
return d;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(_mt7620_mii_read);
|
||||
|
||||
int mt7620_mdio_write(struct mii_bus *bus, int phy_addr, int phy_reg, u16 val)
|
||||
{
|
||||
struct mtk_eth *eth = bus->priv;
|
||||
struct mt7620_gsw *gsw = (struct mt7620_gsw *)eth->sw_priv;
|
||||
|
||||
return _mt7620_mii_write(gsw, phy_addr, phy_reg, val);
|
||||
}
|
||||
|
||||
int mt7620_mdio_read(struct mii_bus *bus, int phy_addr, int phy_reg)
|
||||
{
|
||||
struct mtk_eth *eth = bus->priv;
|
||||
struct mt7620_gsw *gsw = (struct mt7620_gsw *)eth->sw_priv;
|
||||
|
||||
return _mt7620_mii_read(gsw, phy_addr, phy_reg);
|
||||
}
|
||||
|
||||
void mt7530_mdio_w32(struct mt7620_gsw *gsw, u32 reg, u32 val)
|
||||
{
|
||||
_mt7620_mii_write(gsw, 0x1f, 0x1f, (reg >> 6) & 0x3ff);
|
||||
_mt7620_mii_write(gsw, 0x1f, (reg >> 2) & 0xf, val & 0xffff);
|
||||
_mt7620_mii_write(gsw, 0x1f, 0x10, val >> 16);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt7530_mdio_w32);
|
||||
|
||||
u32 mt7530_mdio_r32(struct mt7620_gsw *gsw, u32 reg)
|
||||
{
|
||||
u16 high, low;
|
||||
|
||||
_mt7620_mii_write(gsw, 0x1f, 0x1f, (reg >> 6) & 0x3ff);
|
||||
low = _mt7620_mii_read(gsw, 0x1f, (reg >> 2) & 0xf);
|
||||
high = _mt7620_mii_read(gsw, 0x1f, 0x10);
|
||||
|
||||
return (high << 16) | (low & 0xffff);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt7530_mdio_r32);
|
||||
|
||||
void mt7530_mdio_m32(struct mt7620_gsw *gsw, u32 mask, u32 set, u32 reg)
|
||||
{
|
||||
u32 val = mt7530_mdio_r32(gsw, reg);
|
||||
|
||||
val &= ~mask;
|
||||
val |= set;
|
||||
mt7530_mdio_w32(gsw, reg, val);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt7530_mdio_m32);
|
||||
|
||||
static unsigned char *mtk_speed_str(int speed)
|
||||
{
|
||||
switch (speed) {
|
||||
case 2:
|
||||
case SPEED_1000:
|
||||
return "1000";
|
||||
case 1:
|
||||
case SPEED_100:
|
||||
return "100";
|
||||
case 0:
|
||||
case SPEED_10:
|
||||
return "10";
|
||||
}
|
||||
|
||||
return "? ";
|
||||
}
|
||||
|
||||
int mt7620_has_carrier(struct mtk_eth *eth)
|
||||
{
|
||||
struct mt7620_gsw *gsw = (struct mt7620_gsw *)eth->sw_priv;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < GSW_PORT6; i++)
|
||||
if (mt7530_mdio_r32(gsw, GSW_REG_PORT_STATUS(i)) & 0x1)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void mt7620_print_link_state(struct mtk_eth *eth, int port, int link,
|
||||
int speed, int duplex)
|
||||
{
|
||||
struct mt7620_gsw *gsw = eth->sw_priv;
|
||||
|
||||
if (link)
|
||||
dev_info(gsw->dev, "port %d link up (%sMbps/%s duplex)\n",
|
||||
port, mtk_speed_str(speed),
|
||||
(duplex) ? "Full" : "Half");
|
||||
else
|
||||
dev_info(gsw->dev, "port %d link down\n", port);
|
||||
}
|
||||
|
||||
void mt7620_mdio_link_adjust(struct mtk_eth *eth, int port)
|
||||
{
|
||||
mt7620_print_link_state(eth, port, eth->link[port],
|
||||
eth->phy->speed[port],
|
||||
(eth->phy->duplex[port] == DUPLEX_FULL));
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -1,716 +0,0 @@
|
|||
/* 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; version 2 of the License
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Copyright (C) 2009-2016 John Crispin <blogic@openwrt.org>
|
||||
* Copyright (C) 2009-2016 Felix Fietkau <nbd@openwrt.org>
|
||||
* Copyright (C) 2013-2016 Michael Lee <igvtee@gmail.com>
|
||||
*/
|
||||
|
||||
#ifndef MTK_ETH_H
|
||||
#define MTK_ETH_H
|
||||
|
||||
#include <linux/mii.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/phy.h>
|
||||
#include <linux/ethtool.h>
|
||||
#include <linux/version.h>
|
||||
#include <linux/atomic.h>
|
||||
|
||||
/* these registers have different offsets depending on the SoC. we use a lookup
|
||||
* table for these
|
||||
*/
|
||||
enum mtk_reg {
|
||||
MTK_REG_PDMA_GLO_CFG = 0,
|
||||
MTK_REG_PDMA_RST_CFG,
|
||||
MTK_REG_DLY_INT_CFG,
|
||||
MTK_REG_TX_BASE_PTR0,
|
||||
MTK_REG_TX_MAX_CNT0,
|
||||
MTK_REG_TX_CTX_IDX0,
|
||||
MTK_REG_TX_DTX_IDX0,
|
||||
MTK_REG_RX_BASE_PTR0,
|
||||
MTK_REG_RX_MAX_CNT0,
|
||||
MTK_REG_RX_CALC_IDX0,
|
||||
MTK_REG_RX_DRX_IDX0,
|
||||
MTK_REG_MTK_INT_ENABLE,
|
||||
MTK_REG_MTK_INT_STATUS,
|
||||
MTK_REG_MTK_DMA_VID_BASE,
|
||||
MTK_REG_MTK_COUNTER_BASE,
|
||||
MTK_REG_MTK_RST_GL,
|
||||
MTK_REG_MTK_INT_STATUS2,
|
||||
MTK_REG_COUNT
|
||||
};
|
||||
|
||||
/* delayed interrupt bits */
|
||||
#define MTK_DELAY_EN_INT 0x80
|
||||
#define MTK_DELAY_MAX_INT 0x04
|
||||
#define MTK_DELAY_MAX_TOUT 0x04
|
||||
#define MTK_DELAY_TIME 20
|
||||
#define MTK_DELAY_CHAN (((MTK_DELAY_EN_INT | MTK_DELAY_MAX_INT) << 8) \
|
||||
| MTK_DELAY_MAX_TOUT)
|
||||
#define MTK_DELAY_INIT ((MTK_DELAY_CHAN << 16) | MTK_DELAY_CHAN)
|
||||
#define MTK_PSE_FQFC_CFG_INIT 0x80504000
|
||||
#define MTK_PSE_FQFC_CFG_256Q 0xff908000
|
||||
|
||||
/* interrupt bits */
|
||||
#define MTK_CNT_PPE_AF BIT(31)
|
||||
#define MTK_CNT_GDM_AF BIT(29)
|
||||
#define MTK_PSE_P2_FC BIT(26)
|
||||
#define MTK_PSE_BUF_DROP BIT(24)
|
||||
#define MTK_GDM_OTHER_DROP BIT(23)
|
||||
#define MTK_PSE_P1_FC BIT(22)
|
||||
#define MTK_PSE_P0_FC BIT(21)
|
||||
#define MTK_PSE_FQ_EMPTY BIT(20)
|
||||
#define MTK_GE1_STA_CHG BIT(18)
|
||||
#define MTK_TX_COHERENT BIT(17)
|
||||
#define MTK_RX_COHERENT BIT(16)
|
||||
#define MTK_TX_DONE_INT3 BIT(11)
|
||||
#define MTK_TX_DONE_INT2 BIT(10)
|
||||
#define MTK_TX_DONE_INT1 BIT(9)
|
||||
#define MTK_TX_DONE_INT0 BIT(8)
|
||||
#define MTK_RX_DONE_INT0 BIT(2)
|
||||
#define MTK_TX_DLY_INT BIT(1)
|
||||
#define MTK_RX_DLY_INT BIT(0)
|
||||
|
||||
#define MTK_RX_DONE_INT MTK_RX_DONE_INT0
|
||||
#define MTK_TX_DONE_INT (MTK_TX_DONE_INT0 | MTK_TX_DONE_INT1 | \
|
||||
MTK_TX_DONE_INT2 | MTK_TX_DONE_INT3)
|
||||
|
||||
#define RT5350_RX_DLY_INT BIT(30)
|
||||
#define RT5350_TX_DLY_INT BIT(28)
|
||||
#define RT5350_RX_DONE_INT1 BIT(17)
|
||||
#define RT5350_RX_DONE_INT0 BIT(16)
|
||||
#define RT5350_TX_DONE_INT3 BIT(3)
|
||||
#define RT5350_TX_DONE_INT2 BIT(2)
|
||||
#define RT5350_TX_DONE_INT1 BIT(1)
|
||||
#define RT5350_TX_DONE_INT0 BIT(0)
|
||||
|
||||
#define RT5350_RX_DONE_INT (RT5350_RX_DONE_INT0 | RT5350_RX_DONE_INT1)
|
||||
#define RT5350_TX_DONE_INT (RT5350_TX_DONE_INT0 | RT5350_TX_DONE_INT1 | \
|
||||
RT5350_TX_DONE_INT2 | RT5350_TX_DONE_INT3)
|
||||
|
||||
/* registers */
|
||||
#define MTK_GDMA_OFFSET 0x0020
|
||||
#define MTK_PSE_OFFSET 0x0040
|
||||
#define MTK_GDMA2_OFFSET 0x0060
|
||||
#define MTK_CDMA_OFFSET 0x0080
|
||||
#define MTK_DMA_VID0 0x00a8
|
||||
#define MTK_PDMA_OFFSET 0x0100
|
||||
#define MTK_PPE_OFFSET 0x0200
|
||||
#define MTK_CMTABLE_OFFSET 0x0400
|
||||
#define MTK_POLICYTABLE_OFFSET 0x1000
|
||||
|
||||
#define MT7621_GDMA_OFFSET 0x0500
|
||||
#define MT7620_GDMA_OFFSET 0x0600
|
||||
|
||||
#define RT5350_PDMA_OFFSET 0x0800
|
||||
#define RT5350_SDM_OFFSET 0x0c00
|
||||
|
||||
#define MTK_MDIO_ACCESS 0x00
|
||||
#define MTK_MDIO_CFG 0x04
|
||||
#define MTK_GLO_CFG 0x08
|
||||
#define MTK_RST_GL 0x0C
|
||||
#define MTK_INT_STATUS 0x10
|
||||
#define MTK_INT_ENABLE 0x14
|
||||
#define MTK_MDIO_CFG2 0x18
|
||||
#define MTK_FOC_TS_T 0x1C
|
||||
|
||||
#define MTK_GDMA1_FWD_CFG (MTK_GDMA_OFFSET + 0x00)
|
||||
#define MTK_GDMA1_SCH_CFG (MTK_GDMA_OFFSET + 0x04)
|
||||
#define MTK_GDMA1_SHPR_CFG (MTK_GDMA_OFFSET + 0x08)
|
||||
#define MTK_GDMA1_MAC_ADRL (MTK_GDMA_OFFSET + 0x0C)
|
||||
#define MTK_GDMA1_MAC_ADRH (MTK_GDMA_OFFSET + 0x10)
|
||||
|
||||
#define MTK_GDMA2_FWD_CFG (MTK_GDMA2_OFFSET + 0x00)
|
||||
#define MTK_GDMA2_SCH_CFG (MTK_GDMA2_OFFSET + 0x04)
|
||||
#define MTK_GDMA2_SHPR_CFG (MTK_GDMA2_OFFSET + 0x08)
|
||||
#define MTK_GDMA2_MAC_ADRL (MTK_GDMA2_OFFSET + 0x0C)
|
||||
#define MTK_GDMA2_MAC_ADRH (MTK_GDMA2_OFFSET + 0x10)
|
||||
|
||||
#define MTK_PSE_FQ_CFG (MTK_PSE_OFFSET + 0x00)
|
||||
#define MTK_CDMA_FC_CFG (MTK_PSE_OFFSET + 0x04)
|
||||
#define MTK_GDMA1_FC_CFG (MTK_PSE_OFFSET + 0x08)
|
||||
#define MTK_GDMA2_FC_CFG (MTK_PSE_OFFSET + 0x0C)
|
||||
|
||||
#define MTK_CDMA_CSG_CFG (MTK_CDMA_OFFSET + 0x00)
|
||||
#define MTK_CDMA_SCH_CFG (MTK_CDMA_OFFSET + 0x04)
|
||||
|
||||
#define MT7621_GDMA_FWD_CFG(x) (MT7621_GDMA_OFFSET + (x * 0x1000))
|
||||
|
||||
/* FIXME this might be different for different SOCs */
|
||||
#define MT7620_GDMA1_FWD_CFG (MT7621_GDMA_OFFSET + 0x00)
|
||||
|
||||
#define RT5350_TX_BASE_PTR0 (RT5350_PDMA_OFFSET + 0x00)
|
||||
#define RT5350_TX_MAX_CNT0 (RT5350_PDMA_OFFSET + 0x04)
|
||||
#define RT5350_TX_CTX_IDX0 (RT5350_PDMA_OFFSET + 0x08)
|
||||
#define RT5350_TX_DTX_IDX0 (RT5350_PDMA_OFFSET + 0x0C)
|
||||
#define RT5350_TX_BASE_PTR1 (RT5350_PDMA_OFFSET + 0x10)
|
||||
#define RT5350_TX_MAX_CNT1 (RT5350_PDMA_OFFSET + 0x14)
|
||||
#define RT5350_TX_CTX_IDX1 (RT5350_PDMA_OFFSET + 0x18)
|
||||
#define RT5350_TX_DTX_IDX1 (RT5350_PDMA_OFFSET + 0x1C)
|
||||
#define RT5350_TX_BASE_PTR2 (RT5350_PDMA_OFFSET + 0x20)
|
||||
#define RT5350_TX_MAX_CNT2 (RT5350_PDMA_OFFSET + 0x24)
|
||||
#define RT5350_TX_CTX_IDX2 (RT5350_PDMA_OFFSET + 0x28)
|
||||
#define RT5350_TX_DTX_IDX2 (RT5350_PDMA_OFFSET + 0x2C)
|
||||
#define RT5350_TX_BASE_PTR3 (RT5350_PDMA_OFFSET + 0x30)
|
||||
#define RT5350_TX_MAX_CNT3 (RT5350_PDMA_OFFSET + 0x34)
|
||||
#define RT5350_TX_CTX_IDX3 (RT5350_PDMA_OFFSET + 0x38)
|
||||
#define RT5350_TX_DTX_IDX3 (RT5350_PDMA_OFFSET + 0x3C)
|
||||
#define RT5350_RX_BASE_PTR0 (RT5350_PDMA_OFFSET + 0x100)
|
||||
#define RT5350_RX_MAX_CNT0 (RT5350_PDMA_OFFSET + 0x104)
|
||||
#define RT5350_RX_CALC_IDX0 (RT5350_PDMA_OFFSET + 0x108)
|
||||
#define RT5350_RX_DRX_IDX0 (RT5350_PDMA_OFFSET + 0x10C)
|
||||
#define RT5350_RX_BASE_PTR1 (RT5350_PDMA_OFFSET + 0x110)
|
||||
#define RT5350_RX_MAX_CNT1 (RT5350_PDMA_OFFSET + 0x114)
|
||||
#define RT5350_RX_CALC_IDX1 (RT5350_PDMA_OFFSET + 0x118)
|
||||
#define RT5350_RX_DRX_IDX1 (RT5350_PDMA_OFFSET + 0x11C)
|
||||
#define RT5350_PDMA_GLO_CFG (RT5350_PDMA_OFFSET + 0x204)
|
||||
#define RT5350_PDMA_RST_CFG (RT5350_PDMA_OFFSET + 0x208)
|
||||
#define RT5350_DLY_INT_CFG (RT5350_PDMA_OFFSET + 0x20c)
|
||||
#define RT5350_MTK_INT_STATUS (RT5350_PDMA_OFFSET + 0x220)
|
||||
#define RT5350_MTK_INT_ENABLE (RT5350_PDMA_OFFSET + 0x228)
|
||||
#define RT5350_PDMA_SCH_CFG (RT5350_PDMA_OFFSET + 0x280)
|
||||
|
||||
#define MTK_PDMA_GLO_CFG (MTK_PDMA_OFFSET + 0x00)
|
||||
#define MTK_PDMA_RST_CFG (MTK_PDMA_OFFSET + 0x04)
|
||||
#define MTK_PDMA_SCH_CFG (MTK_PDMA_OFFSET + 0x08)
|
||||
#define MTK_DLY_INT_CFG (MTK_PDMA_OFFSET + 0x0C)
|
||||
#define MTK_TX_BASE_PTR0 (MTK_PDMA_OFFSET + 0x10)
|
||||
#define MTK_TX_MAX_CNT0 (MTK_PDMA_OFFSET + 0x14)
|
||||
#define MTK_TX_CTX_IDX0 (MTK_PDMA_OFFSET + 0x18)
|
||||
#define MTK_TX_DTX_IDX0 (MTK_PDMA_OFFSET + 0x1C)
|
||||
#define MTK_TX_BASE_PTR1 (MTK_PDMA_OFFSET + 0x20)
|
||||
#define MTK_TX_MAX_CNT1 (MTK_PDMA_OFFSET + 0x24)
|
||||
#define MTK_TX_CTX_IDX1 (MTK_PDMA_OFFSET + 0x28)
|
||||
#define MTK_TX_DTX_IDX1 (MTK_PDMA_OFFSET + 0x2C)
|
||||
#define MTK_RX_BASE_PTR0 (MTK_PDMA_OFFSET + 0x30)
|
||||
#define MTK_RX_MAX_CNT0 (MTK_PDMA_OFFSET + 0x34)
|
||||
#define MTK_RX_CALC_IDX0 (MTK_PDMA_OFFSET + 0x38)
|
||||
#define MTK_RX_DRX_IDX0 (MTK_PDMA_OFFSET + 0x3C)
|
||||
#define MTK_TX_BASE_PTR2 (MTK_PDMA_OFFSET + 0x40)
|
||||
#define MTK_TX_MAX_CNT2 (MTK_PDMA_OFFSET + 0x44)
|
||||
#define MTK_TX_CTX_IDX2 (MTK_PDMA_OFFSET + 0x48)
|
||||
#define MTK_TX_DTX_IDX2 (MTK_PDMA_OFFSET + 0x4C)
|
||||
#define MTK_TX_BASE_PTR3 (MTK_PDMA_OFFSET + 0x50)
|
||||
#define MTK_TX_MAX_CNT3 (MTK_PDMA_OFFSET + 0x54)
|
||||
#define MTK_TX_CTX_IDX3 (MTK_PDMA_OFFSET + 0x58)
|
||||
#define MTK_TX_DTX_IDX3 (MTK_PDMA_OFFSET + 0x5C)
|
||||
#define MTK_RX_BASE_PTR1 (MTK_PDMA_OFFSET + 0x60)
|
||||
#define MTK_RX_MAX_CNT1 (MTK_PDMA_OFFSET + 0x64)
|
||||
#define MTK_RX_CALC_IDX1 (MTK_PDMA_OFFSET + 0x68)
|
||||
#define MTK_RX_DRX_IDX1 (MTK_PDMA_OFFSET + 0x6C)
|
||||
|
||||
/* Switch DMA configuration */
|
||||
#define RT5350_SDM_CFG (RT5350_SDM_OFFSET + 0x00)
|
||||
#define RT5350_SDM_RRING (RT5350_SDM_OFFSET + 0x04)
|
||||
#define RT5350_SDM_TRING (RT5350_SDM_OFFSET + 0x08)
|
||||
#define RT5350_SDM_MAC_ADRL (RT5350_SDM_OFFSET + 0x0C)
|
||||
#define RT5350_SDM_MAC_ADRH (RT5350_SDM_OFFSET + 0x10)
|
||||
#define RT5350_SDM_TPCNT (RT5350_SDM_OFFSET + 0x100)
|
||||
#define RT5350_SDM_TBCNT (RT5350_SDM_OFFSET + 0x104)
|
||||
#define RT5350_SDM_RPCNT (RT5350_SDM_OFFSET + 0x108)
|
||||
#define RT5350_SDM_RBCNT (RT5350_SDM_OFFSET + 0x10C)
|
||||
#define RT5350_SDM_CS_ERR (RT5350_SDM_OFFSET + 0x110)
|
||||
|
||||
#define RT5350_SDM_ICS_EN BIT(16)
|
||||
#define RT5350_SDM_TCS_EN BIT(17)
|
||||
#define RT5350_SDM_UCS_EN BIT(18)
|
||||
|
||||
/* QDMA registers */
|
||||
#define MTK_QTX_CFG(x) (0x1800 + (x * 0x10))
|
||||
#define MTK_QTX_SCH(x) (0x1804 + (x * 0x10))
|
||||
#define MTK_QRX_BASE_PTR0 0x1900
|
||||
#define MTK_QRX_MAX_CNT0 0x1904
|
||||
#define MTK_QRX_CRX_IDX0 0x1908
|
||||
#define MTK_QRX_DRX_IDX0 0x190C
|
||||
#define MTK_QDMA_GLO_CFG 0x1A04
|
||||
#define MTK_QDMA_RST_IDX 0x1A08
|
||||
#define MTK_QDMA_DELAY_INT 0x1A0C
|
||||
#define MTK_QDMA_FC_THRES 0x1A10
|
||||
#define MTK_QMTK_INT_STATUS 0x1A18
|
||||
#define MTK_QMTK_INT_ENABLE 0x1A1C
|
||||
#define MTK_QDMA_HRED2 0x1A44
|
||||
|
||||
#define MTK_QTX_CTX_PTR 0x1B00
|
||||
#define MTK_QTX_DTX_PTR 0x1B04
|
||||
|
||||
#define MTK_QTX_CRX_PTR 0x1B10
|
||||
#define MTK_QTX_DRX_PTR 0x1B14
|
||||
|
||||
#define MTK_QDMA_FQ_HEAD 0x1B20
|
||||
#define MTK_QDMA_FQ_TAIL 0x1B24
|
||||
#define MTK_QDMA_FQ_CNT 0x1B28
|
||||
#define MTK_QDMA_FQ_BLEN 0x1B2C
|
||||
|
||||
#define QDMA_PAGE_SIZE 2048
|
||||
#define QDMA_TX_OWNER_CPU BIT(31)
|
||||
#define QDMA_TX_SWC BIT(14)
|
||||
#define TX_QDMA_SDL(_x) (((_x) & 0x3fff) << 16)
|
||||
#define QDMA_RES_THRES 4
|
||||
|
||||
/* MDIO_CFG register bits */
|
||||
#define MTK_MDIO_CFG_AUTO_POLL_EN BIT(29)
|
||||
#define MTK_MDIO_CFG_GP1_BP_EN BIT(16)
|
||||
#define MTK_MDIO_CFG_GP1_FRC_EN BIT(15)
|
||||
#define MTK_MDIO_CFG_GP1_SPEED_10 (0 << 13)
|
||||
#define MTK_MDIO_CFG_GP1_SPEED_100 (1 << 13)
|
||||
#define MTK_MDIO_CFG_GP1_SPEED_1000 (2 << 13)
|
||||
#define MTK_MDIO_CFG_GP1_DUPLEX BIT(12)
|
||||
#define MTK_MDIO_CFG_GP1_FC_TX BIT(11)
|
||||
#define MTK_MDIO_CFG_GP1_FC_RX BIT(10)
|
||||
#define MTK_MDIO_CFG_GP1_LNK_DWN BIT(9)
|
||||
#define MTK_MDIO_CFG_GP1_AN_FAIL BIT(8)
|
||||
#define MTK_MDIO_CFG_MDC_CLK_DIV_1 (0 << 6)
|
||||
#define MTK_MDIO_CFG_MDC_CLK_DIV_2 (1 << 6)
|
||||
#define MTK_MDIO_CFG_MDC_CLK_DIV_4 (2 << 6)
|
||||
#define MTK_MDIO_CFG_MDC_CLK_DIV_8 (3 << 6)
|
||||
#define MTK_MDIO_CFG_TURBO_MII_FREQ BIT(5)
|
||||
#define MTK_MDIO_CFG_TURBO_MII_MODE BIT(4)
|
||||
#define MTK_MDIO_CFG_RX_CLK_SKEW_0 (0 << 2)
|
||||
#define MTK_MDIO_CFG_RX_CLK_SKEW_200 (1 << 2)
|
||||
#define MTK_MDIO_CFG_RX_CLK_SKEW_400 (2 << 2)
|
||||
#define MTK_MDIO_CFG_RX_CLK_SKEW_INV (3 << 2)
|
||||
#define MTK_MDIO_CFG_TX_CLK_SKEW_0 0
|
||||
#define MTK_MDIO_CFG_TX_CLK_SKEW_200 1
|
||||
#define MTK_MDIO_CFG_TX_CLK_SKEW_400 2
|
||||
#define MTK_MDIO_CFG_TX_CLK_SKEW_INV 3
|
||||
|
||||
/* uni-cast port */
|
||||
#define MTK_GDM1_JMB_LEN_MASK 0xf
|
||||
#define MTK_GDM1_JMB_LEN_SHIFT 28
|
||||
#define MTK_GDM1_ICS_EN BIT(22)
|
||||
#define MTK_GDM1_TCS_EN BIT(21)
|
||||
#define MTK_GDM1_UCS_EN BIT(20)
|
||||
#define MTK_GDM1_JMB_EN BIT(19)
|
||||
#define MTK_GDM1_STRPCRC BIT(16)
|
||||
#define MTK_GDM1_UFRC_P_CPU (0 << 12)
|
||||
#define MTK_GDM1_UFRC_P_GDMA1 (1 << 12)
|
||||
#define MTK_GDM1_UFRC_P_PPE (6 << 12)
|
||||
|
||||
/* checksums */
|
||||
#define MTK_ICS_GEN_EN BIT(2)
|
||||
#define MTK_UCS_GEN_EN BIT(1)
|
||||
#define MTK_TCS_GEN_EN BIT(0)
|
||||
|
||||
/* dma mode */
|
||||
#define MTK_PDMA BIT(0)
|
||||
#define MTK_QDMA BIT(1)
|
||||
#define MTK_PDMA_RX_QDMA_TX (MTK_PDMA | MTK_QDMA)
|
||||
|
||||
/* dma ring */
|
||||
#define MTK_PST_DRX_IDX0 BIT(16)
|
||||
#define MTK_PST_DTX_IDX3 BIT(3)
|
||||
#define MTK_PST_DTX_IDX2 BIT(2)
|
||||
#define MTK_PST_DTX_IDX1 BIT(1)
|
||||
#define MTK_PST_DTX_IDX0 BIT(0)
|
||||
|
||||
#define MTK_RX_2B_OFFSET BIT(31)
|
||||
#define MTK_TX_WB_DDONE BIT(6)
|
||||
#define MTK_RX_DMA_BUSY BIT(3)
|
||||
#define MTK_TX_DMA_BUSY BIT(1)
|
||||
#define MTK_RX_DMA_EN BIT(2)
|
||||
#define MTK_TX_DMA_EN BIT(0)
|
||||
|
||||
#define MTK_PDMA_SIZE_4DWORDS (0 << 4)
|
||||
#define MTK_PDMA_SIZE_8DWORDS (1 << 4)
|
||||
#define MTK_PDMA_SIZE_16DWORDS (2 << 4)
|
||||
|
||||
#define MTK_US_CYC_CNT_MASK 0xff
|
||||
#define MTK_US_CYC_CNT_SHIFT 0x8
|
||||
#define MTK_US_CYC_CNT_DIVISOR 1000000
|
||||
|
||||
/* PDMA descriptor rxd2 */
|
||||
#define RX_DMA_DONE BIT(31)
|
||||
#define RX_DMA_LSO BIT(30)
|
||||
#define RX_DMA_PLEN0(_x) (((_x) & 0x3fff) << 16)
|
||||
#define RX_DMA_GET_PLEN0(_x) (((_x) >> 16) & 0x3fff)
|
||||
#define RX_DMA_TAG BIT(15)
|
||||
|
||||
/* PDMA descriptor rxd3 */
|
||||
#define RX_DMA_TPID(_x) (((_x) >> 16) & 0xffff)
|
||||
#define RX_DMA_VID(_x) ((_x) & 0xfff)
|
||||
|
||||
/* PDMA descriptor rxd4 */
|
||||
#define RX_DMA_L4VALID BIT(30)
|
||||
#define RX_DMA_FPORT_SHIFT 19
|
||||
#define RX_DMA_FPORT_MASK 0x7
|
||||
|
||||
struct mtk_rx_dma {
|
||||
unsigned int rxd1;
|
||||
unsigned int rxd2;
|
||||
unsigned int rxd3;
|
||||
unsigned int rxd4;
|
||||
} __packed __aligned(4);
|
||||
|
||||
/* PDMA tx descriptor bits */
|
||||
#define TX_DMA_BUF_LEN 0x3fff
|
||||
#define TX_DMA_PLEN0_MASK (TX_DMA_BUF_LEN << 16)
|
||||
#define TX_DMA_PLEN0(_x) (((_x) & TX_DMA_BUF_LEN) << 16)
|
||||
#define TX_DMA_PLEN1(_x) ((_x) & TX_DMA_BUF_LEN)
|
||||
#define TX_DMA_GET_PLEN0(_x) (((_x) >> 16) & TX_DMA_BUF_LEN)
|
||||
#define TX_DMA_GET_PLEN1(_x) ((_x) & TX_DMA_BUF_LEN)
|
||||
#define TX_DMA_LS1 BIT(14)
|
||||
#define TX_DMA_LS0 BIT(30)
|
||||
#define TX_DMA_DONE BIT(31)
|
||||
#define TX_DMA_FPORT_SHIFT 25
|
||||
#define TX_DMA_FPORT_MASK 0x7
|
||||
#define TX_DMA_INS_VLAN_MT7621 BIT(16)
|
||||
#define TX_DMA_INS_VLAN BIT(7)
|
||||
#define TX_DMA_INS_PPPOE BIT(12)
|
||||
#define TX_DMA_TAG BIT(15)
|
||||
#define TX_DMA_TAG_MASK BIT(15)
|
||||
#define TX_DMA_QN(_x) ((_x) << 16)
|
||||
#define TX_DMA_PN(_x) ((_x) << 24)
|
||||
#define TX_DMA_QN_MASK TX_DMA_QN(0x7)
|
||||
#define TX_DMA_PN_MASK TX_DMA_PN(0x7)
|
||||
#define TX_DMA_UDF BIT(20)
|
||||
#define TX_DMA_CHKSUM (0x7 << 29)
|
||||
#define TX_DMA_TSO BIT(28)
|
||||
#define TX_DMA_DESP4_DEF (TX_DMA_QN(3) | TX_DMA_PN(1))
|
||||
|
||||
/* frame engine counters */
|
||||
#define MTK_PPE_AC_BCNT0 (MTK_CMTABLE_OFFSET + 0x00)
|
||||
#define MTK_GDMA1_TX_GBCNT (MTK_CMTABLE_OFFSET + 0x300)
|
||||
#define MTK_GDMA2_TX_GBCNT (MTK_GDMA1_TX_GBCNT + 0x40)
|
||||
|
||||
/* phy device flags */
|
||||
#define MTK_PHY_FLAG_PORT BIT(0)
|
||||
#define MTK_PHY_FLAG_ATTACH BIT(1)
|
||||
|
||||
struct mtk_tx_dma {
|
||||
unsigned int txd1;
|
||||
unsigned int txd2;
|
||||
unsigned int txd3;
|
||||
unsigned int txd4;
|
||||
} __packed __aligned(4);
|
||||
|
||||
struct mtk_eth;
|
||||
struct mtk_mac;
|
||||
|
||||
/* manage the attached phys */
|
||||
struct mtk_phy {
|
||||
spinlock_t lock;
|
||||
|
||||
struct phy_device *phy[8];
|
||||
struct device_node *phy_node[8];
|
||||
const __be32 *phy_fixed[8];
|
||||
int duplex[8];
|
||||
int speed[8];
|
||||
int tx_fc[8];
|
||||
int rx_fc[8];
|
||||
int (*connect)(struct mtk_mac *mac);
|
||||
void (*disconnect)(struct mtk_mac *mac);
|
||||
void (*start)(struct mtk_mac *mac);
|
||||
void (*stop)(struct mtk_mac *mac);
|
||||
};
|
||||
|
||||
/* struct mtk_soc_data - the structure that holds the SoC specific data
|
||||
* @reg_table: Some of the legacy registers changed their location
|
||||
* over time. Their offsets are stored in this table
|
||||
*
|
||||
* @init_data: Some features depend on the silicon revision. This
|
||||
* callback allows runtime modification of the content of
|
||||
* this struct
|
||||
* @reset_fe: This callback is used to trigger the reset of the frame
|
||||
* engine
|
||||
* @set_mac: This callback is used to set the unicast mac address
|
||||
* filter
|
||||
* @fwd_config: This callback is used to setup the forward config
|
||||
* register of the MAC
|
||||
* @switch_init: This callback is used to bring up the switch core
|
||||
* @port_init: Some SoCs have ports that can be router to a switch port
|
||||
* or an external PHY. This callback is used to setup these
|
||||
* ports.
|
||||
* @has_carrier: This callback allows driver to check if there is a cable
|
||||
* attached.
|
||||
* @mdio_init: This callbck is used to setup the MDIO bus if one is
|
||||
* present
|
||||
* @mdio_cleanup: This callback is used to cleanup the MDIO state.
|
||||
* @mdio_write: This callback is used to write data to the MDIO bus.
|
||||
* @mdio_read: This callback is used to write data to the MDIO bus.
|
||||
* @mdio_adjust_link: This callback is used to apply the PHY settings.
|
||||
* @piac_offset: the PIAC register has a different different base offset
|
||||
* @hw_features: feature set depends on the SoC type
|
||||
* @dma_ring_size: allow GBit SoCs to set bigger rings than FE SoCs
|
||||
* @napi_weight: allow GBit SoCs to set bigger napi weight than FE SoCs
|
||||
* @dma_type: SoCs is PDMA, QDMA or a mix of the 2
|
||||
* @pdma_glo_cfg: the default DMA configuration
|
||||
* @rx_int: the TX interrupt bits used by the SoC
|
||||
* @tx_int: the TX interrupt bits used by the SoC
|
||||
* @status_int: the Status interrupt bits used by the SoC
|
||||
* @checksum_bit: the bits used to turn on HW checksumming
|
||||
* @txd4: default value of the TXD4 descriptor
|
||||
* @mac_count: the number of MACs that the SoC has
|
||||
* @new_stats: there is a old and new way to read hardware stats
|
||||
* registers
|
||||
* @jumbo_frame: does the SoC support jumbo frames ?
|
||||
* @rx_2b_offset: tell the rx dma to offset the data by 2 bytes
|
||||
* @rx_sg_dma: scatter gather support
|
||||
* @padding_64b enable 64 bit padding
|
||||
* @padding_bug: rt2880 has a padding bug
|
||||
* @has_switch: does the SoC have a built-in switch
|
||||
*
|
||||
* Although all of the supported SoCs share the same basic functionality, there
|
||||
* are several SoC specific functions and features that we need to support. This
|
||||
* struct holds the SoC specific data so that the common core can figure out
|
||||
* how to setup and use these differences.
|
||||
*/
|
||||
struct mtk_soc_data {
|
||||
const u16 *reg_table;
|
||||
|
||||
void (*init_data)(struct mtk_soc_data *data, struct net_device *netdev);
|
||||
void (*reset_fe)(struct mtk_eth *eth);
|
||||
void (*set_mac)(struct mtk_mac *mac, unsigned char *macaddr);
|
||||
int (*fwd_config)(struct mtk_eth *eth);
|
||||
int (*switch_init)(struct mtk_eth *eth);
|
||||
void (*port_init)(struct mtk_eth *eth, struct mtk_mac *mac,
|
||||
struct device_node *port);
|
||||
int (*has_carrier)(struct mtk_eth *eth);
|
||||
int (*mdio_init)(struct mtk_eth *eth);
|
||||
void (*mdio_cleanup)(struct mtk_eth *eth);
|
||||
int (*mdio_write)(struct mii_bus *bus, int phy_addr, int phy_reg,
|
||||
u16 val);
|
||||
int (*mdio_read)(struct mii_bus *bus, int phy_addr, int phy_reg);
|
||||
void (*mdio_adjust_link)(struct mtk_eth *eth, int port);
|
||||
u32 piac_offset;
|
||||
netdev_features_t hw_features;
|
||||
u32 dma_ring_size;
|
||||
u32 napi_weight;
|
||||
u32 dma_type;
|
||||
u32 pdma_glo_cfg;
|
||||
u32 rx_int;
|
||||
u32 tx_int;
|
||||
u32 status_int;
|
||||
u32 checksum_bit;
|
||||
u32 txd4;
|
||||
u32 mac_count;
|
||||
|
||||
u32 new_stats:1;
|
||||
u32 jumbo_frame:1;
|
||||
u32 rx_2b_offset:1;
|
||||
u32 rx_sg_dma:1;
|
||||
u32 padding_64b:1;
|
||||
u32 padding_bug:1;
|
||||
u32 has_switch:1;
|
||||
};
|
||||
|
||||
#define MTK_STAT_OFFSET 0x40
|
||||
|
||||
/* struct mtk_hw_stats - the structure that holds the traffic statistics.
|
||||
* @stats_lock: make sure that stats operations are atomic
|
||||
* @reg_offset: the status register offset of the SoC
|
||||
* @syncp: the refcount
|
||||
*
|
||||
* All of the supported SoCs have hardware counters for traffic statstics.
|
||||
* Whenever the status IRQ triggers we can read the latest stats from these
|
||||
* counters and store them in this struct.
|
||||
*/
|
||||
struct mtk_hw_stats {
|
||||
spinlock_t stats_lock;
|
||||
u32 reg_offset;
|
||||
struct u64_stats_sync syncp;
|
||||
|
||||
u64 tx_bytes;
|
||||
u64 tx_packets;
|
||||
u64 tx_skip;
|
||||
u64 tx_collisions;
|
||||
u64 rx_bytes;
|
||||
u64 rx_packets;
|
||||
u64 rx_overflow;
|
||||
u64 rx_fcs_errors;
|
||||
u64 rx_short_errors;
|
||||
u64 rx_long_errors;
|
||||
u64 rx_checksum_errors;
|
||||
u64 rx_flow_control_packets;
|
||||
};
|
||||
|
||||
/* PDMA descriptor can point at 1-2 segments. This enum allows us to track how
|
||||
* memory was allocated so that it can be freed properly
|
||||
*/
|
||||
enum mtk_tx_flags {
|
||||
MTK_TX_FLAGS_SINGLE0 = 0x01,
|
||||
MTK_TX_FLAGS_PAGE0 = 0x02,
|
||||
MTK_TX_FLAGS_PAGE1 = 0x04,
|
||||
};
|
||||
|
||||
/* struct mtk_tx_buf - This struct holds the pointers to the memory pointed at
|
||||
* by the TX descriptor s
|
||||
* @skb: The SKB pointer of the packet being sent
|
||||
* @dma_addr0: The base addr of the first segment
|
||||
* @dma_len0: The length of the first segment
|
||||
* @dma_addr1: The base addr of the second segment
|
||||
* @dma_len1: The length of the second segment
|
||||
*/
|
||||
struct mtk_tx_buf {
|
||||
struct sk_buff *skb;
|
||||
u32 flags;
|
||||
DEFINE_DMA_UNMAP_ADDR(dma_addr0);
|
||||
DEFINE_DMA_UNMAP_LEN(dma_len0);
|
||||
DEFINE_DMA_UNMAP_ADDR(dma_addr1);
|
||||
DEFINE_DMA_UNMAP_LEN(dma_len1);
|
||||
};
|
||||
|
||||
/* struct mtk_tx_ring - This struct holds info describing a TX ring
|
||||
* @tx_dma: The descriptor ring
|
||||
* @tx_buf: The memory pointed at by the ring
|
||||
* @tx_phys: The physical addr of tx_buf
|
||||
* @tx_next_free: Pointer to the next free descriptor
|
||||
* @tx_last_free: Pointer to the last free descriptor
|
||||
* @tx_thresh: The threshold of minimum amount of free descriptors
|
||||
* @tx_map: Callback to map a new packet into the ring
|
||||
* @tx_poll: Callback for the housekeeping function
|
||||
* @tx_clean: Callback for the cleanup function
|
||||
* @tx_ring_size: How many descriptors are in the ring
|
||||
* @tx_free_idx: The index of th next free descriptor
|
||||
* @tx_next_idx: QDMA uses a linked list. This element points to the next
|
||||
* free descriptor in the list
|
||||
* @tx_free_count: QDMA uses a linked list. Track how many free descriptors
|
||||
* are present
|
||||
*/
|
||||
struct mtk_tx_ring {
|
||||
struct mtk_tx_dma *tx_dma;
|
||||
struct mtk_tx_buf *tx_buf;
|
||||
dma_addr_t tx_phys;
|
||||
struct mtk_tx_dma *tx_next_free;
|
||||
struct mtk_tx_dma *tx_last_free;
|
||||
u16 tx_thresh;
|
||||
int (*tx_map)(struct sk_buff *skb, struct net_device *dev, int tx_num,
|
||||
struct mtk_tx_ring *ring, bool gso);
|
||||
int (*tx_poll)(struct mtk_eth *eth, int budget, bool *tx_again);
|
||||
void (*tx_clean)(struct mtk_eth *eth);
|
||||
|
||||
/* PDMA only */
|
||||
u16 tx_ring_size;
|
||||
u16 tx_free_idx;
|
||||
|
||||
/* QDMA only */
|
||||
u16 tx_next_idx;
|
||||
atomic_t tx_free_count;
|
||||
};
|
||||
|
||||
/* struct mtk_rx_ring - This struct holds info describing a RX ring
|
||||
* @rx_dma: The descriptor ring
|
||||
* @rx_data: The memory pointed at by the ring
|
||||
* @trx_phys: The physical addr of rx_buf
|
||||
* @rx_ring_size: How many descriptors are in the ring
|
||||
* @rx_buf_size: The size of each packet buffer
|
||||
* @rx_calc_idx: The current head of ring
|
||||
*/
|
||||
struct mtk_rx_ring {
|
||||
struct mtk_rx_dma *rx_dma;
|
||||
u8 **rx_data;
|
||||
dma_addr_t rx_phys;
|
||||
u16 rx_ring_size;
|
||||
u16 frag_size;
|
||||
u16 rx_buf_size;
|
||||
u16 rx_calc_idx;
|
||||
};
|
||||
|
||||
/* currently no SoC has more than 2 macs */
|
||||
#define MTK_MAX_DEVS 2
|
||||
|
||||
/* struct mtk_eth - This is the main datasructure for holding the state
|
||||
* of the driver
|
||||
* @dev: The device pointer
|
||||
* @base: The mapped register i/o base
|
||||
* @page_lock: Make sure that register operations are atomic
|
||||
* @soc: pointer to our SoC specific data
|
||||
* @dummy_dev: we run 2 netdevs on 1 physical DMA ring and need a
|
||||
* dummy for NAPI to work
|
||||
* @netdev: The netdev instances
|
||||
* @mac: Each netdev is linked to a physical MAC
|
||||
* @switch_np: The phandle for the switch
|
||||
* @irq: The IRQ that we are using
|
||||
* @msg_enable: Ethtool msg level
|
||||
* @ysclk: The sysclk rate - neeed for calibration
|
||||
* @ethsys: The register map pointing at the range used to setup
|
||||
* MII modes
|
||||
* @dma_refcnt: track how many netdevs are using the DMA engine
|
||||
* @tx_ring: Pointer to the memore holding info about the TX ring
|
||||
* @rx_ring: Pointer to the memore holding info about the RX ring
|
||||
* @rx_napi: The NAPI struct
|
||||
* @scratch_ring: Newer SoCs need memory for a second HW managed TX ring
|
||||
* @scratch_head: The scratch memory that scratch_ring points to.
|
||||
* @phy: Info about the attached PHYs
|
||||
* @mii_bus: If there is a bus we need to create an instance for it
|
||||
* @link: Track if the ports have a physical link
|
||||
* @sw_priv: Pointer to the switches private data
|
||||
* @vlan_map: RX VID tracking
|
||||
*/
|
||||
|
||||
struct mtk_eth {
|
||||
struct device *dev;
|
||||
void __iomem *base;
|
||||
spinlock_t page_lock;
|
||||
struct mtk_soc_data *soc;
|
||||
struct net_device dummy_dev;
|
||||
struct net_device *netdev[MTK_MAX_DEVS];
|
||||
struct mtk_mac *mac[MTK_MAX_DEVS];
|
||||
struct device_node *switch_np;
|
||||
int irq;
|
||||
u32 msg_enable;
|
||||
unsigned long sysclk;
|
||||
struct regmap *ethsys;
|
||||
atomic_t dma_refcnt;
|
||||
struct mtk_tx_ring tx_ring;
|
||||
struct mtk_rx_ring rx_ring[2];
|
||||
struct napi_struct rx_napi;
|
||||
struct mtk_tx_dma *scratch_ring;
|
||||
void *scratch_head;
|
||||
struct mtk_phy *phy;
|
||||
struct mii_bus *mii_bus;
|
||||
int link[8];
|
||||
void *sw_priv;
|
||||
unsigned long vlan_map;
|
||||
};
|
||||
|
||||
/* struct mtk_mac - the structure that holds the info about the MACs of the
|
||||
* SoC
|
||||
* @id: The number of the MAC
|
||||
* @of_node: Our devicetree node
|
||||
* @hw: Backpointer to our main datastruture
|
||||
* @hw_stats: Packet statistics counter
|
||||
* @phy_dev: The attached PHY if available
|
||||
* @phy_flags: The PHYs flags
|
||||
* @pending_work: The workqueue used to reset the dma ring
|
||||
*/
|
||||
struct mtk_mac {
|
||||
int id;
|
||||
struct device_node *of_node;
|
||||
struct mtk_eth *hw;
|
||||
struct mtk_hw_stats *hw_stats;
|
||||
struct phy_device *phy_dev;
|
||||
u32 phy_flags;
|
||||
struct work_struct pending_work;
|
||||
};
|
||||
|
||||
/* the struct describing the SoC. these are declared in the soc_xyz.c files */
|
||||
extern const struct of_device_id of_mtk_match[];
|
||||
|
||||
/* read the hardware status register */
|
||||
void mtk_stats_update_mac(struct mtk_mac *mac);
|
||||
|
||||
/* default checksum setup handler */
|
||||
void mtk_reset(struct mtk_eth *eth, u32 reset_bits);
|
||||
|
||||
/* register i/o wrappers */
|
||||
void mtk_w32(struct mtk_eth *eth, u32 val, unsigned int reg);
|
||||
u32 mtk_r32(struct mtk_eth *eth, unsigned int reg);
|
||||
|
||||
/* default clock calibration handler */
|
||||
int mtk_set_clock_cycle(struct mtk_eth *eth);
|
||||
|
||||
/* default checksum setup handler */
|
||||
void mtk_csum_config(struct mtk_eth *eth);
|
||||
|
||||
/* default forward config handler */
|
||||
void mtk_fwd_config(struct mtk_eth *eth);
|
||||
|
||||
#endif /* MTK_ETH_H */
|
|
@ -1,161 +0,0 @@
|
|||
/* 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; version 2 of the License
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Copyright (C) 2009-2016 John Crispin <blogic@openwrt.org>
|
||||
* Copyright (C) 2009-2016 Felix Fietkau <nbd@openwrt.org>
|
||||
* Copyright (C) 2013-2016 Michael Lee <igvtee@gmail.com>
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/if_vlan.h>
|
||||
#include <linux/of_net.h>
|
||||
|
||||
#include <asm/mach-ralink/ralink_regs.h>
|
||||
|
||||
#include "mtk_eth_soc.h"
|
||||
#include "gsw_mt7620.h"
|
||||
#include "mdio.h"
|
||||
|
||||
#define MT7620_CDMA_CSG_CFG 0x400
|
||||
#define MT7621_CDMP_IG_CTRL (MT7620_CDMA_CSG_CFG + 0x00)
|
||||
#define MT7621_CDMP_EG_CTRL (MT7620_CDMA_CSG_CFG + 0x04)
|
||||
#define MT7621_RESET_FE BIT(6)
|
||||
#define MT7621_L4_VALID BIT(24)
|
||||
|
||||
#define MT7621_TX_DMA_UDF BIT(19)
|
||||
|
||||
#define CDMA_ICS_EN BIT(2)
|
||||
#define CDMA_UCS_EN BIT(1)
|
||||
#define CDMA_TCS_EN BIT(0)
|
||||
|
||||
#define GDMA_ICS_EN BIT(22)
|
||||
#define GDMA_TCS_EN BIT(21)
|
||||
#define GDMA_UCS_EN BIT(20)
|
||||
|
||||
/* frame engine counters */
|
||||
#define MT7621_REG_MIB_OFFSET 0x2000
|
||||
#define MT7621_PPE_AC_BCNT0 (MT7621_REG_MIB_OFFSET + 0x00)
|
||||
#define MT7621_GDM1_TX_GBCNT (MT7621_REG_MIB_OFFSET + 0x400)
|
||||
#define MT7621_GDM2_TX_GBCNT (MT7621_GDM1_TX_GBCNT + 0x40)
|
||||
|
||||
#define GSW_REG_GDMA1_MAC_ADRL 0x508
|
||||
#define GSW_REG_GDMA1_MAC_ADRH 0x50C
|
||||
#define GSW_REG_GDMA2_MAC_ADRL 0x1508
|
||||
#define GSW_REG_GDMA2_MAC_ADRH 0x150C
|
||||
|
||||
#define MT7621_MTK_RST_GL 0x04
|
||||
#define MT7620_MTK_INT_STATUS2 0x08
|
||||
|
||||
/* MTK_INT_STATUS reg on mt7620 define CNT_GDM1_AF at BIT(29)
|
||||
* but after test it should be BIT(13).
|
||||
*/
|
||||
#define MT7621_MTK_GDM1_AF BIT(28)
|
||||
#define MT7621_MTK_GDM2_AF BIT(29)
|
||||
|
||||
static const u16 mt7621_reg_table[MTK_REG_COUNT] = {
|
||||
[MTK_REG_PDMA_GLO_CFG] = RT5350_PDMA_GLO_CFG,
|
||||
[MTK_REG_PDMA_RST_CFG] = RT5350_PDMA_RST_CFG,
|
||||
[MTK_REG_DLY_INT_CFG] = RT5350_DLY_INT_CFG,
|
||||
[MTK_REG_TX_BASE_PTR0] = RT5350_TX_BASE_PTR0,
|
||||
[MTK_REG_TX_MAX_CNT0] = RT5350_TX_MAX_CNT0,
|
||||
[MTK_REG_TX_CTX_IDX0] = RT5350_TX_CTX_IDX0,
|
||||
[MTK_REG_TX_DTX_IDX0] = RT5350_TX_DTX_IDX0,
|
||||
[MTK_REG_RX_BASE_PTR0] = RT5350_RX_BASE_PTR0,
|
||||
[MTK_REG_RX_MAX_CNT0] = RT5350_RX_MAX_CNT0,
|
||||
[MTK_REG_RX_CALC_IDX0] = RT5350_RX_CALC_IDX0,
|
||||
[MTK_REG_RX_DRX_IDX0] = RT5350_RX_DRX_IDX0,
|
||||
[MTK_REG_MTK_INT_ENABLE] = RT5350_MTK_INT_ENABLE,
|
||||
[MTK_REG_MTK_INT_STATUS] = RT5350_MTK_INT_STATUS,
|
||||
[MTK_REG_MTK_DMA_VID_BASE] = 0,
|
||||
[MTK_REG_MTK_COUNTER_BASE] = MT7621_GDM1_TX_GBCNT,
|
||||
[MTK_REG_MTK_RST_GL] = MT7621_MTK_RST_GL,
|
||||
[MTK_REG_MTK_INT_STATUS2] = MT7620_MTK_INT_STATUS2,
|
||||
};
|
||||
|
||||
static void mt7621_mtk_reset(struct mtk_eth *eth)
|
||||
{
|
||||
mtk_reset(eth, MT7621_RESET_FE);
|
||||
}
|
||||
|
||||
static int mt7621_fwd_config(struct mtk_eth *eth)
|
||||
{
|
||||
/* Setup GMAC1 only, there is no support for GMAC2 yet */
|
||||
mtk_w32(eth, mtk_r32(eth, MT7620_GDMA1_FWD_CFG) & ~0xffff,
|
||||
MT7620_GDMA1_FWD_CFG);
|
||||
|
||||
/* Enable RX checksum */
|
||||
mtk_w32(eth, mtk_r32(eth, MT7620_GDMA1_FWD_CFG) | (GDMA_ICS_EN |
|
||||
GDMA_TCS_EN | GDMA_UCS_EN),
|
||||
MT7620_GDMA1_FWD_CFG);
|
||||
|
||||
/* Enable RX VLan Offloading */
|
||||
mtk_w32(eth, 0, MT7621_CDMP_EG_CTRL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mt7621_set_mac(struct mtk_mac *mac, unsigned char *hwaddr)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&mac->hw->page_lock, flags);
|
||||
if (mac->id == 0) {
|
||||
mtk_w32(mac->hw, (hwaddr[0] << 8) | hwaddr[1],
|
||||
GSW_REG_GDMA1_MAC_ADRH);
|
||||
mtk_w32(mac->hw, (hwaddr[2] << 24) | (hwaddr[3] << 16) |
|
||||
(hwaddr[4] << 8) | hwaddr[5],
|
||||
GSW_REG_GDMA1_MAC_ADRL);
|
||||
}
|
||||
if (mac->id == 1) {
|
||||
mtk_w32(mac->hw, (hwaddr[0] << 8) | hwaddr[1],
|
||||
GSW_REG_GDMA2_MAC_ADRH);
|
||||
mtk_w32(mac->hw, (hwaddr[2] << 24) | (hwaddr[3] << 16) |
|
||||
(hwaddr[4] << 8) | hwaddr[5],
|
||||
GSW_REG_GDMA2_MAC_ADRL);
|
||||
}
|
||||
spin_unlock_irqrestore(&mac->hw->page_lock, flags);
|
||||
}
|
||||
|
||||
static struct mtk_soc_data mt7621_data = {
|
||||
.hw_features = NETIF_F_IP_CSUM | NETIF_F_RXCSUM |
|
||||
NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX |
|
||||
NETIF_F_SG | NETIF_F_TSO | NETIF_F_TSO6 |
|
||||
NETIF_F_IPV6_CSUM,
|
||||
.dma_type = MTK_PDMA,
|
||||
.dma_ring_size = 256,
|
||||
.napi_weight = 64,
|
||||
.new_stats = 1,
|
||||
.padding_64b = 1,
|
||||
.rx_2b_offset = 1,
|
||||
.rx_sg_dma = 1,
|
||||
.has_switch = 1,
|
||||
.mac_count = 2,
|
||||
.reset_fe = mt7621_mtk_reset,
|
||||
.set_mac = mt7621_set_mac,
|
||||
.fwd_config = mt7621_fwd_config,
|
||||
.switch_init = mtk_gsw_init,
|
||||
.reg_table = mt7621_reg_table,
|
||||
.pdma_glo_cfg = MTK_PDMA_SIZE_16DWORDS,
|
||||
.rx_int = RT5350_RX_DONE_INT,
|
||||
.tx_int = RT5350_TX_DONE_INT,
|
||||
.status_int = MT7621_MTK_GDM1_AF | MT7621_MTK_GDM2_AF,
|
||||
.checksum_bit = MT7621_L4_VALID,
|
||||
.has_carrier = mt7620_has_carrier,
|
||||
.mdio_read = mt7620_mdio_read,
|
||||
.mdio_write = mt7620_mdio_write,
|
||||
.mdio_adjust_link = mt7620_mdio_link_adjust,
|
||||
};
|
||||
|
||||
const struct of_device_id of_mtk_match[] = {
|
||||
{ .compatible = "mediatek,mt7621-eth", .data = &mt7621_data },
|
||||
{},
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(of, of_mtk_match);
|
|
@ -1,6 +1,7 @@
|
|||
config PCI_MT7621
|
||||
tristate "MediaTek MT7621 PCI Controller"
|
||||
depends on RALINK
|
||||
depends on PCI
|
||||
select PCI_DRIVERS_GENERIC
|
||||
help
|
||||
This selects a driver for the MediaTek MT7621 PCI Controller.
|
||||
|
|
|
@ -163,7 +163,7 @@ int cvm_oct_phy_setup_device(struct net_device *dev)
|
|||
goto no_phy;
|
||||
|
||||
phydev = of_phy_connect(dev, phy_node, cvm_oct_adjust_link, 0,
|
||||
PHY_INTERFACE_MODE_GMII);
|
||||
priv->phy_mode);
|
||||
of_node_put(phy_node);
|
||||
|
||||
if (!phydev)
|
||||
|
|
|
@ -653,14 +653,37 @@ static struct device_node *cvm_oct_node_for_port(struct device_node *pip,
|
|||
return np;
|
||||
}
|
||||
|
||||
static void cvm_set_rgmii_delay(struct device_node *np, int iface, int port)
|
||||
static void cvm_set_rgmii_delay(struct octeon_ethernet *priv, int iface,
|
||||
int port)
|
||||
{
|
||||
struct device_node *np = priv->of_node;
|
||||
u32 delay_value;
|
||||
bool rx_delay;
|
||||
bool tx_delay;
|
||||
|
||||
if (!of_property_read_u32(np, "rx-delay", &delay_value))
|
||||
/* By default, both RX/TX delay is enabled in
|
||||
* __cvmx_helper_rgmii_enable().
|
||||
*/
|
||||
rx_delay = true;
|
||||
tx_delay = true;
|
||||
|
||||
if (!of_property_read_u32(np, "rx-delay", &delay_value)) {
|
||||
cvmx_write_csr(CVMX_ASXX_RX_CLK_SETX(port, iface), delay_value);
|
||||
if (!of_property_read_u32(np, "tx-delay", &delay_value))
|
||||
rx_delay = delay_value > 0;
|
||||
}
|
||||
if (!of_property_read_u32(np, "tx-delay", &delay_value)) {
|
||||
cvmx_write_csr(CVMX_ASXX_TX_CLK_SETX(port, iface), delay_value);
|
||||
tx_delay = delay_value > 0;
|
||||
}
|
||||
|
||||
if (!rx_delay && !tx_delay)
|
||||
priv->phy_mode = PHY_INTERFACE_MODE_RGMII_ID;
|
||||
else if (!rx_delay)
|
||||
priv->phy_mode = PHY_INTERFACE_MODE_RGMII_RXID;
|
||||
else if (!tx_delay)
|
||||
priv->phy_mode = PHY_INTERFACE_MODE_RGMII_TXID;
|
||||
else
|
||||
priv->phy_mode = PHY_INTERFACE_MODE_RGMII;
|
||||
}
|
||||
|
||||
static int cvm_oct_probe(struct platform_device *pdev)
|
||||
|
@ -825,6 +848,7 @@ static int cvm_oct_probe(struct platform_device *pdev)
|
|||
priv->port = port;
|
||||
priv->queue = cvmx_pko_get_base_queue(priv->port);
|
||||
priv->fau = fau - cvmx_pko_get_num_queues(port) * 4;
|
||||
priv->phy_mode = PHY_INTERFACE_MODE_NA;
|
||||
for (qos = 0; qos < 16; qos++)
|
||||
skb_queue_head_init(&priv->tx_free_list[qos]);
|
||||
for (qos = 0; qos < cvmx_pko_get_num_queues(port);
|
||||
|
@ -856,6 +880,7 @@ static int cvm_oct_probe(struct platform_device *pdev)
|
|||
break;
|
||||
|
||||
case CVMX_HELPER_INTERFACE_MODE_SGMII:
|
||||
priv->phy_mode = PHY_INTERFACE_MODE_SGMII;
|
||||
dev->netdev_ops = &cvm_oct_sgmii_netdev_ops;
|
||||
strcpy(dev->name, "eth%d");
|
||||
break;
|
||||
|
@ -865,11 +890,16 @@ static int cvm_oct_probe(struct platform_device *pdev)
|
|||
strcpy(dev->name, "spi%d");
|
||||
break;
|
||||
|
||||
case CVMX_HELPER_INTERFACE_MODE_RGMII:
|
||||
case CVMX_HELPER_INTERFACE_MODE_GMII:
|
||||
priv->phy_mode = PHY_INTERFACE_MODE_GMII;
|
||||
dev->netdev_ops = &cvm_oct_rgmii_netdev_ops;
|
||||
strcpy(dev->name, "eth%d");
|
||||
cvm_set_rgmii_delay(priv->of_node, interface,
|
||||
break;
|
||||
|
||||
case CVMX_HELPER_INTERFACE_MODE_RGMII:
|
||||
dev->netdev_ops = &cvm_oct_rgmii_netdev_ops;
|
||||
strcpy(dev->name, "eth%d");
|
||||
cvm_set_rgmii_delay(priv, interface,
|
||||
port_index);
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
#define OCTEON_ETHERNET_H
|
||||
|
||||
#include <linux/of.h>
|
||||
|
||||
#include <linux/phy.h>
|
||||
#include <asm/octeon/cvmx-helper-board.h>
|
||||
|
||||
/**
|
||||
|
@ -33,6 +33,8 @@ struct octeon_ethernet {
|
|||
* cvmx_helper_interface_mode_t
|
||||
*/
|
||||
int imode;
|
||||
/* PHY mode */
|
||||
phy_interface_t phy_mode;
|
||||
/* List of outstanding tx buffers per queue */
|
||||
struct sk_buff_head tx_free_list[16];
|
||||
unsigned int last_speed;
|
||||
|
|
|
@ -45,7 +45,7 @@ static int dcon_init_xo_1(struct dcon_priv *dcon)
|
|||
{
|
||||
unsigned char lob;
|
||||
int ret, i;
|
||||
struct dcon_gpio *pin = &gpios_asis[0];
|
||||
const struct dcon_gpio *pin = &gpios_asis[0];
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(gpios_asis); i++) {
|
||||
gpios[i] = devm_gpiod_get(&dcon->client->dev, pin[i].name,
|
||||
|
|
|
@ -174,7 +174,9 @@ s32 _rtw_init_xmit_priv(struct xmit_priv *pxmitpriv, struct adapter *padapter)
|
|||
|
||||
pxmitpriv->free_xmit_extbuf_cnt = num_xmit_extbuf;
|
||||
|
||||
rtw_alloc_hwxmits(padapter);
|
||||
res = rtw_alloc_hwxmits(padapter);
|
||||
if (res == _FAIL)
|
||||
goto exit;
|
||||
rtw_init_hwxmits(pxmitpriv->hwxmits, pxmitpriv->hwxmit_entry);
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
|
@ -1503,7 +1505,7 @@ exit:
|
|||
return res;
|
||||
}
|
||||
|
||||
void rtw_alloc_hwxmits(struct adapter *padapter)
|
||||
s32 rtw_alloc_hwxmits(struct adapter *padapter)
|
||||
{
|
||||
struct hw_xmit *hwxmits;
|
||||
struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
|
||||
|
@ -1512,6 +1514,8 @@ void rtw_alloc_hwxmits(struct adapter *padapter)
|
|||
|
||||
pxmitpriv->hwxmits = kcalloc(pxmitpriv->hwxmit_entry,
|
||||
sizeof(struct hw_xmit), GFP_KERNEL);
|
||||
if (!pxmitpriv->hwxmits)
|
||||
return _FAIL;
|
||||
|
||||
hwxmits = pxmitpriv->hwxmits;
|
||||
|
||||
|
@ -1519,6 +1523,7 @@ void rtw_alloc_hwxmits(struct adapter *padapter)
|
|||
hwxmits[1] .sta_queue = &pxmitpriv->vi_pending;
|
||||
hwxmits[2] .sta_queue = &pxmitpriv->be_pending;
|
||||
hwxmits[3] .sta_queue = &pxmitpriv->bk_pending;
|
||||
return _SUCCESS;
|
||||
}
|
||||
|
||||
void rtw_free_hwxmits(struct adapter *padapter)
|
||||
|
|
|
@ -336,7 +336,7 @@ s32 rtw_txframes_sta_ac_pending(struct adapter *padapter,
|
|||
void rtw_init_hwxmits(struct hw_xmit *phwxmit, int entry);
|
||||
s32 _rtw_init_xmit_priv(struct xmit_priv *pxmitpriv, struct adapter *padapter);
|
||||
void _rtw_free_xmit_priv(struct xmit_priv *pxmitpriv);
|
||||
void rtw_alloc_hwxmits(struct adapter *padapter);
|
||||
s32 rtw_alloc_hwxmits(struct adapter *padapter);
|
||||
void rtw_free_hwxmits(struct adapter *padapter);
|
||||
s32 rtw_xmit(struct adapter *padapter, struct sk_buff **pkt);
|
||||
|
||||
|
|
|
@ -147,17 +147,9 @@ static u8 write_macreg_hdl(struct _adapter *padapter, u8 *pbuf)
|
|||
|
||||
static u8 read_bbreg_hdl(struct _adapter *padapter, u8 *pbuf)
|
||||
{
|
||||
u32 val;
|
||||
void (*pcmd_callback)(struct _adapter *dev, struct cmd_obj *pcmd);
|
||||
struct cmd_obj *pcmd = (struct cmd_obj *)pbuf;
|
||||
|
||||
if (pcmd->rsp && pcmd->rspsz > 0)
|
||||
memcpy(pcmd->rsp, (u8 *)&val, pcmd->rspsz);
|
||||
pcmd_callback = cmd_callback[pcmd->cmdcode].callback;
|
||||
if (!pcmd_callback)
|
||||
r8712_free_cmd_obj(pcmd);
|
||||
else
|
||||
pcmd_callback(padapter, pcmd);
|
||||
r8712_free_cmd_obj(pcmd);
|
||||
return H2C_SUCCESS;
|
||||
}
|
||||
|
||||
|
|
|
@ -140,7 +140,7 @@ enum rtl8712_h2c_cmd {
|
|||
static struct _cmd_callback cmd_callback[] = {
|
||||
{GEN_CMD_CODE(_Read_MACREG), NULL}, /*0*/
|
||||
{GEN_CMD_CODE(_Write_MACREG), NULL},
|
||||
{GEN_CMD_CODE(_Read_BBREG), &r8712_getbbrfreg_cmdrsp_callback},
|
||||
{GEN_CMD_CODE(_Read_BBREG), NULL},
|
||||
{GEN_CMD_CODE(_Write_BBREG), NULL},
|
||||
{GEN_CMD_CODE(_Read_RFREG), &r8712_getbbrfreg_cmdrsp_callback},
|
||||
{GEN_CMD_CODE(_Write_RFREG), NULL}, /*5*/
|
||||
|
|
|
@ -260,7 +260,9 @@ s32 _rtw_init_xmit_priv(struct xmit_priv *pxmitpriv, struct adapter *padapter)
|
|||
}
|
||||
}
|
||||
|
||||
rtw_alloc_hwxmits(padapter);
|
||||
res = rtw_alloc_hwxmits(padapter);
|
||||
if (res == _FAIL)
|
||||
goto exit;
|
||||
rtw_init_hwxmits(pxmitpriv->hwxmits, pxmitpriv->hwxmit_entry);
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
|
@ -2144,7 +2146,7 @@ exit:
|
|||
return res;
|
||||
}
|
||||
|
||||
void rtw_alloc_hwxmits(struct adapter *padapter)
|
||||
s32 rtw_alloc_hwxmits(struct adapter *padapter)
|
||||
{
|
||||
struct hw_xmit *hwxmits;
|
||||
struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
|
||||
|
@ -2155,10 +2157,8 @@ void rtw_alloc_hwxmits(struct adapter *padapter)
|
|||
|
||||
pxmitpriv->hwxmits = rtw_zmalloc(sizeof(struct hw_xmit) * pxmitpriv->hwxmit_entry);
|
||||
|
||||
if (pxmitpriv->hwxmits == NULL) {
|
||||
DBG_871X("alloc hwxmits fail!...\n");
|
||||
return;
|
||||
}
|
||||
if (!pxmitpriv->hwxmits)
|
||||
return _FAIL;
|
||||
|
||||
hwxmits = pxmitpriv->hwxmits;
|
||||
|
||||
|
@ -2204,7 +2204,7 @@ void rtw_alloc_hwxmits(struct adapter *padapter)
|
|||
|
||||
}
|
||||
|
||||
|
||||
return _SUCCESS;
|
||||
}
|
||||
|
||||
void rtw_free_hwxmits(struct adapter *padapter)
|
||||
|
|
|
@ -487,7 +487,7 @@ s32 _rtw_init_xmit_priv(struct xmit_priv *pxmitpriv, struct adapter *padapter);
|
|||
void _rtw_free_xmit_priv (struct xmit_priv *pxmitpriv);
|
||||
|
||||
|
||||
void rtw_alloc_hwxmits(struct adapter *padapter);
|
||||
s32 rtw_alloc_hwxmits(struct adapter *padapter);
|
||||
void rtw_free_hwxmits(struct adapter *padapter);
|
||||
|
||||
|
||||
|
|
|
@ -180,6 +180,8 @@ static int rtl_phydm_init_priv(struct rtl_priv *rtlpriv,
|
|||
|
||||
rtlpriv->phydm.internal =
|
||||
kzalloc(sizeof(struct phy_dm_struct), GFP_KERNEL);
|
||||
if (!rtlpriv->phydm.internal)
|
||||
return 0;
|
||||
|
||||
_rtl_phydm_init_com_info(rtlpriv, ic, params);
|
||||
|
||||
|
|
|
@ -743,6 +743,8 @@ void rtl8822be_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished)
|
|||
u1_rsvd_page_loc, 3);
|
||||
|
||||
skb = dev_alloc_skb(totalpacketlen);
|
||||
if (!skb)
|
||||
return;
|
||||
memcpy((u8 *)skb_put(skb, totalpacketlen), &reserved_page_packet,
|
||||
totalpacketlen);
|
||||
|
||||
|
|
|
@ -210,12 +210,15 @@ static ssize_t softsynthx_read(struct file *fp, char __user *buf, size_t count,
|
|||
return -EINVAL;
|
||||
|
||||
spin_lock_irqsave(&speakup_info.spinlock, flags);
|
||||
synth_soft.alive = 1;
|
||||
while (1) {
|
||||
prepare_to_wait(&speakup_event, &wait, TASK_INTERRUPTIBLE);
|
||||
if (!unicode)
|
||||
synth_buffer_skip_nonlatin1();
|
||||
if (!synth_buffer_empty() || speakup_info.flushing)
|
||||
break;
|
||||
if (synth_current() == &synth_soft) {
|
||||
if (!unicode)
|
||||
synth_buffer_skip_nonlatin1();
|
||||
if (!synth_buffer_empty() || speakup_info.flushing)
|
||||
break;
|
||||
}
|
||||
spin_unlock_irqrestore(&speakup_info.spinlock, flags);
|
||||
if (fp->f_flags & O_NONBLOCK) {
|
||||
finish_wait(&speakup_event, &wait);
|
||||
|
@ -235,6 +238,8 @@ static ssize_t softsynthx_read(struct file *fp, char __user *buf, size_t count,
|
|||
|
||||
/* Keep 3 bytes available for a 16bit UTF-8-encoded character */
|
||||
while (chars_sent <= count - bytes_per_ch) {
|
||||
if (synth_current() != &synth_soft)
|
||||
break;
|
||||
if (speakup_info.flushing) {
|
||||
speakup_info.flushing = 0;
|
||||
ch = '\x18';
|
||||
|
@ -331,7 +336,8 @@ static __poll_t softsynth_poll(struct file *fp, struct poll_table_struct *wait)
|
|||
poll_wait(fp, &speakup_event, wait);
|
||||
|
||||
spin_lock_irqsave(&speakup_info.spinlock, flags);
|
||||
if (!synth_buffer_empty() || speakup_info.flushing)
|
||||
if (synth_current() == &synth_soft &&
|
||||
(!synth_buffer_empty() || speakup_info.flushing))
|
||||
ret = EPOLLIN | EPOLLRDNORM;
|
||||
spin_unlock_irqrestore(&speakup_info.spinlock, flags);
|
||||
return ret;
|
||||
|
|
|
@ -74,6 +74,7 @@ int synth_request_region(unsigned long start, unsigned long n);
|
|||
int synth_release_region(unsigned long start, unsigned long n);
|
||||
int synth_add(struct spk_synth *in_synth);
|
||||
void synth_remove(struct spk_synth *in_synth);
|
||||
struct spk_synth *synth_current(void);
|
||||
|
||||
extern struct speakup_info_t speakup_info;
|
||||
|
||||
|
|
|
@ -481,4 +481,10 @@ void synth_remove(struct spk_synth *in_synth)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(synth_remove);
|
||||
|
||||
struct spk_synth *synth_current(void)
|
||||
{
|
||||
return synth;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(synth_current);
|
||||
|
||||
short spk_punc_masks[] = { 0, SOME, MOST, PUNC, PUNC | B_SYM };
|
||||
|
|
|
@ -3513,6 +3513,7 @@ static int vchiq_probe(struct platform_device *pdev)
|
|||
struct device_node *fw_node;
|
||||
const struct of_device_id *of_id;
|
||||
struct vchiq_drvdata *drvdata;
|
||||
struct device *vchiq_dev;
|
||||
int err;
|
||||
|
||||
of_id = of_match_node(vchiq_of_match, pdev->dev.of_node);
|
||||
|
@ -3547,9 +3548,12 @@ static int vchiq_probe(struct platform_device *pdev)
|
|||
goto failed_platform_init;
|
||||
}
|
||||
|
||||
if (IS_ERR(device_create(vchiq_class, &pdev->dev, vchiq_devid,
|
||||
NULL, "vchiq")))
|
||||
vchiq_dev = device_create(vchiq_class, &pdev->dev, vchiq_devid, NULL,
|
||||
"vchiq");
|
||||
if (IS_ERR(vchiq_dev)) {
|
||||
err = PTR_ERR(vchiq_dev);
|
||||
goto failed_device_create;
|
||||
}
|
||||
|
||||
vchiq_debugfs_init();
|
||||
|
||||
|
|
|
@ -1033,8 +1033,6 @@ static void vnt_interrupt_process(struct vnt_private *priv)
|
|||
return;
|
||||
}
|
||||
|
||||
MACvIntDisable(priv->PortOffset);
|
||||
|
||||
spin_lock_irqsave(&priv->lock, flags);
|
||||
|
||||
/* Read low level stats */
|
||||
|
@ -1122,8 +1120,6 @@ static void vnt_interrupt_process(struct vnt_private *priv)
|
|||
}
|
||||
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
|
||||
MACvIntEnable(priv->PortOffset, IMR_MASK_VALUE);
|
||||
}
|
||||
|
||||
static void vnt_interrupt_work(struct work_struct *work)
|
||||
|
@ -1133,14 +1129,17 @@ static void vnt_interrupt_work(struct work_struct *work)
|
|||
|
||||
if (priv->vif)
|
||||
vnt_interrupt_process(priv);
|
||||
|
||||
MACvIntEnable(priv->PortOffset, IMR_MASK_VALUE);
|
||||
}
|
||||
|
||||
static irqreturn_t vnt_interrupt(int irq, void *arg)
|
||||
{
|
||||
struct vnt_private *priv = arg;
|
||||
|
||||
if (priv->vif)
|
||||
schedule_work(&priv->interrupt_work);
|
||||
schedule_work(&priv->interrupt_work);
|
||||
|
||||
MACvIntDisable(priv->PortOffset);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue