diff --git a/include/kernel-6.12 b/include/kernel-6.12 index 3649471866b2b5..6e26f829ab2961 100644 --- a/include/kernel-6.12 +++ b/include/kernel-6.12 @@ -1,2 +1,2 @@ -LINUX_VERSION-6.12 = .9 -LINUX_KERNEL_HASH-6.12.9 = 87be0360df0931b340d2bac35161a548070fbc3a8c352c49e21e96666c26aeb4 +LINUX_VERSION-6.12 = .10 +LINUX_KERNEL_HASH-6.12.10 = 4a516e5ed748537a73cb42ec47fbbeb6df8b1298e8892c29c0e91de79095b297 diff --git a/target/linux/generic/files-6.12/Documentation/devicetree/bindings/mtd/partitions/openwrt,uimage.yaml b/target/linux/generic/files-6.12/Documentation/devicetree/bindings/mtd/partitions/openwrt,uimage.yaml deleted file mode 100644 index d052ab1fc981bb..00000000000000 --- a/target/linux/generic/files-6.12/Documentation/devicetree/bindings/mtd/partitions/openwrt,uimage.yaml +++ /dev/null @@ -1,91 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause -%YAML 1.2 ---- -$id: http://devicetree.org/schemas/mtd/partitions/openwrt,uimage.yaml# -$schema: http://devicetree.org/meta-schemas/core.yaml# - -title: OpenWrt variations of U-Boot Image partitions - -maintainers: - - Bjørn Mork - -description: | - The image format defined by the boot loader "Das U-Boot" is often - modified or extended by device vendors. This defines a few optional - properties which can be used to describe such modifications. - -# partition.txt defines common properties, but has not yet been -# converted to YAML -#allOf: -# - $ref: ../partition.yaml# - -properties: - compatible: - items: - - enum: - - openwrt,uimage - - const: denx,uimage - - openwrt,padding: - description: Number of padding bytes between header and data - $ref: /schemas/types.yaml#/definitions/uint32 - default: 0 - - openwrt,ih-magic: - description: U-Boot Image Header magic number. - $ref: /schemas/types.yaml#/definitions/uint32 - default: 0x27051956 # IH_MAGIC - - openwrt,ih-type: - description: U-Boot Image type - $ref: /schemas/types.yaml#/definitions/uint32 - default: 2 # IH_TYPE_KERNEL - - openwrt,offset: - description: - Offset between partition start and U-Boot Image in bytes - $ref: /schemas/types.yaml#/definitions/uint32 - default: 0 - - openwrt,partition-magic: - description: - Magic number found at the start of the partition. Will only be - validated if both this property and openwrt,offset is non-zero - $ref: /schemas/types.yaml#/definitions/uint32 - default: 0 - -required: - - compatible - - reg - -#unevaluatedProperties: false -additionalProperties: false - -examples: - - | - // device with non-default magic - partition@300000 { - compatible = "openwrt,uimage", "denx,uimage"; - reg = <0x00300000 0xe80000>; - label = "firmware"; - openwrt,ih-magic = <0x4e474520>; - }; - - | - // device with U-Boot Image at an offset, with a partition magic value - partition@70000 { - compatible = "openwrt,uimage", "denx,uimage"; - reg = <0x00070000 0x00790000>; - label = "firmware"; - openwrt,offset = <20>; - openwrt,partition-magic = <0x43535953>; - }; - - | - // device using a non-default image type - #include "dt-bindings/mtd/partitions/uimage.h" - partition@6c0000 { - compatible = "openwrt,uimage", "denx,uimage"; - reg = <0x6c0000 0x1900000>; - label = "firmware"; - openwrt,ih-magic = <0x33373033>; - openwrt,ih-type = ; - }; diff --git a/target/linux/generic/files-6.12/Documentation/networking/adm6996.txt b/target/linux/generic/files-6.12/Documentation/networking/adm6996.txt deleted file mode 100644 index ab59f1df033713..00000000000000 --- a/target/linux/generic/files-6.12/Documentation/networking/adm6996.txt +++ /dev/null @@ -1,110 +0,0 @@ -------- - -ADM6996FC / ADM6996M switch chip driver - - -1. General information - - This driver supports the FC and M models only. The ADM6996F and L are - completely different chips. - - Support for the FC model is extremely limited at the moment. There is no VLAN - support as of yet. The driver will not offer an swconfig interface for the FC - chip. - -1.1 VLAN IDs - - It is possible to define 16 different VLANs. Every VLAN has an identifier, its - VLAN ID. It is easiest if you use at most VLAN IDs 0-15. In that case, the - swconfig based configuration is very straightforward. To define two VLANs with - IDs 4 and 5, you can invoke, for example: - - # swconfig dev ethX vlan 4 set ports '0 1t 2 5t' - # swconfig dev ethX vlan 5 set ports '0t 1t 5t' - - The swconfig framework will automatically invoke 'port Y set pvid Z' for every - port that is an untagged member of VLAN Y, setting its Primary VLAN ID. In - this example, ports 0 and 2 would get "pvid 4". The Primary VLAN ID of a port - is the VLAN ID associated with untagged packets coming in on that port. - - But if you wish to use VLAN IDs outside the range 0-15, this automatic - behaviour of the swconfig framework becomes a problem. The 16 VLANs that - swconfig can configure on the ADM6996 also have a "vid" setting. By default, - this is the same as the number of the VLAN entry, to make the simple behaviour - above possible. To still support a VLAN with a VLAN ID higher than 15 - (presumably because you are in a network where such VLAN IDs are already in - use), you can change the "vid" setting of the VLAN to anything in the range - 0-1023. But suppose you did the following: - - # swconfig dev ethX vlan 0 set vid 998 - # swconfig dev ethX vlan 0 set ports '0 2 5t' - - Now the swconfig framework will issue 'port 0 set pvid 0' and 'port 2 set pvid - 0'. But the "pvid" should be set to 998, so you are responsible for manually - fixing this! - -1.2 VLAN filtering - - The switch is configured to apply source port filtering. This means that - packets are only accepted when the port the packets came in on is a member of - the VLAN the packet should go to. - - Only membership of a VLAN is tested, it does not matter whether it is a tagged - or untagged membership. - - For untagged packets, the destination VLAN is the Primary VLAN ID of the - incoming port. So if the PVID of a port is 0, but that port is not a member of - the VLAN with ID 0, this means that untagged packets on that port are dropped. - This can be used as a roundabout way of dropping untagged packets from a port, - a mode often referred to as "Admit only tagged packets". - -1.3 Reset - - The two supported chip models do not have a sofware-initiated reset. When the - driver is initialised, as well as when the 'reset' swconfig option is invoked, - the driver will set those registers it knows about and supports to the correct - default value. But there are a lot of registers in the chip that the driver - does not support. If something changed those registers, invoking 'reset' or - performing a warm reboot might still leave the chip in a "broken" state. Only - a hardware reset will bring it back in the default state. - -2. Technical details on PHYs and the ADM6996 - - From the viewpoint of the Linux kernel, it is common that an Ethernet adapter - can be seen as a separate MAC entity and a separate PHY entity. The PHY entity - can be queried and set through registers accessible via an MDIO bus. A PHY - normally has a single address on that bus, in the range 0 through 31. - - The ADM6996 has special-purpose registers in the range of PHYs 0 through 10. - Even though all these registers control a single ADM6996 chip, the Linux - kernel treats this as 11 separate PHYs. The driver will bind to these - addresses to prevent a different PHY driver from binding and corrupting these - registers. - - What Linux sees as the PHY on address 0 is meant for the Ethernet MAC - connected to the CPU port of the ADM6996 switch chip (port 5). This is the - Ethernet MAC you will use to send and receive data through the switch. - - The PHYs at addresses 16 through 20 map to the PHYs on ports 0 through 4 of - the switch chip. These can be accessed with the Generic PHY driver, as the - registers have the common layout. - - If a second Ethernet MAC on your board is wired to the port 4 PHY, that MAC - needs to bind to PHY address 20 for the port to work correctly. - - The ADM6996 switch driver will reset the ports 0 through 3 on startup and when - 'reset' is invoked. This could clash with a different PHY driver if the kernel - binds a PHY driver to address 16 through 19. - - If Linux binds a PHY on addresses 1 through 10 to an Ethernet MAC, the ADM6996 - driver will simply always report a connected 100 Mbit/s full-duplex link for - that PHY, and provide no other functionality. This is most likely not what you - want. So if you see a message in your log - - ethX: PHY overlaps ADM6996, providing fixed PHY yy. - - This is most likely an indication that ethX will not work properly, and your - kernel needs to be configured to attach a different PHY to that Ethernet MAC. - - Controlling the mapping between MACs and PHYs is usually done in platform- or - board-specific fixup code. The ADM6996 driver has no influence over this. diff --git a/target/linux/generic/files-6.12/arch/mips/fw/myloader/Makefile b/target/linux/generic/files-6.12/arch/mips/fw/myloader/Makefile deleted file mode 100644 index 34acfd01cc0aba..00000000000000 --- a/target/linux/generic/files-6.12/arch/mips/fw/myloader/Makefile +++ /dev/null @@ -1,5 +0,0 @@ -# -# Makefile for the Compex's MyLoader support on MIPS architecture -# - -lib-y += myloader.o diff --git a/target/linux/generic/files-6.12/arch/mips/fw/myloader/myloader.c b/target/linux/generic/files-6.12/arch/mips/fw/myloader/myloader.c deleted file mode 100644 index a26f9ad3fdbf16..00000000000000 --- a/target/linux/generic/files-6.12/arch/mips/fw/myloader/myloader.c +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Compex's MyLoader specific prom routines - * - * Copyright (C) 2007-2008 Gabor Juhos - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published - * by the Free Software Foundation. - * - */ - -#include -#include -#include -#include - -#include -#include - -#define SYS_PARAMS_ADDR KSEG1ADDR(0x80000800) -#define BOARD_PARAMS_ADDR KSEG1ADDR(0x80000A00) -#define PART_TABLE_ADDR KSEG1ADDR(0x80000C00) -#define BOOT_PARAMS_ADDR KSEG1ADDR(0x80000E00) - -static struct myloader_info myloader_info __initdata; -static int myloader_found __initdata; - -struct myloader_info * __init myloader_get_info(void) -{ - struct mylo_system_params *sysp; - struct mylo_board_params *boardp; - struct mylo_partition_table *parts; - - if (myloader_found) - return &myloader_info; - - sysp = (struct mylo_system_params *)(SYS_PARAMS_ADDR); - boardp = (struct mylo_board_params *)(BOARD_PARAMS_ADDR); - parts = (struct mylo_partition_table *)(PART_TABLE_ADDR); - - printk(KERN_DEBUG "MyLoader: sysp=%08x, boardp=%08x, parts=%08x\n", - sysp->magic, boardp->magic, parts->magic); - - /* Check for some magic numbers */ - if (sysp->magic != MYLO_MAGIC_SYS_PARAMS || - boardp->magic != MYLO_MAGIC_BOARD_PARAMS || - le32_to_cpu(parts->magic) != MYLO_MAGIC_PARTITIONS) - return NULL; - - printk(KERN_DEBUG "MyLoader: id=%04x:%04x, sub_id=%04x:%04x\n", - sysp->vid, sysp->did, sysp->svid, sysp->sdid); - - myloader_info.vid = sysp->vid; - myloader_info.did = sysp->did; - myloader_info.svid = sysp->svid; - myloader_info.sdid = sysp->sdid; - - memcpy(myloader_info.macs, boardp->addr, sizeof(myloader_info.macs)); - - myloader_found = 1; - - return &myloader_info; -} diff --git a/target/linux/generic/files-6.12/drivers/bcma/fallback-sprom.c b/target/linux/generic/files-6.12/drivers/bcma/fallback-sprom.c deleted file mode 100644 index db583fca9cc2a7..00000000000000 --- a/target/linux/generic/files-6.12/drivers/bcma/fallback-sprom.c +++ /dev/null @@ -1,533 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * BCMA Fallback SPROM Driver - * - * Copyright (C) 2020 Álvaro Fernández Rojas - * Copyright (C) 2014 Jonas Gorski - * Copyright (C) 2008 Maxime Bizon - * Copyright (C) 2008 Florian Fainelli - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#define BCMA_FBS_MAX_SIZE 468 - -/* SPROM Extraction */ -#define SPOFF(offset) ((offset) / sizeof(u16)) - -#define SPEX(_outvar, _offset, _mask, _shift) \ - out->_outvar = ((in[SPOFF(_offset)] & (_mask)) >> (_shift)) - -#define SPEX32(_outvar, _offset, _mask, _shift) \ - out->_outvar = ((((u32)in[SPOFF((_offset)+2)] << 16 | \ - in[SPOFF(_offset)]) & (_mask)) >> (_shift)) - -#define SPEX_ARRAY8(_field, _offset, _mask, _shift) \ - do { \ - SPEX(_field[0], _offset + 0, _mask, _shift); \ - SPEX(_field[1], _offset + 2, _mask, _shift); \ - SPEX(_field[2], _offset + 4, _mask, _shift); \ - SPEX(_field[3], _offset + 6, _mask, _shift); \ - SPEX(_field[4], _offset + 8, _mask, _shift); \ - SPEX(_field[5], _offset + 10, _mask, _shift); \ - SPEX(_field[6], _offset + 12, _mask, _shift); \ - SPEX(_field[7], _offset + 14, _mask, _shift); \ - } while (0) - -struct bcma_fbs { - struct device *dev; - struct list_head list; - struct ssb_sprom sprom; - u32 pci_bus; - u32 pci_dev; - bool devid_override; -}; - -static DEFINE_SPINLOCK(bcma_fbs_lock); -static struct list_head bcma_fbs_list = LIST_HEAD_INIT(bcma_fbs_list); - -int bcma_get_fallback_sprom(struct bcma_bus *bus, struct ssb_sprom *out) -{ - struct bcma_fbs *pos; - u32 pci_bus, pci_dev; - - if (bus->hosttype != BCMA_HOSTTYPE_PCI) - return -ENOENT; - - pci_bus = bus->host_pci->bus->number; - pci_dev = PCI_SLOT(bus->host_pci->devfn); - - list_for_each_entry(pos, &bcma_fbs_list, list) { - if (pos->pci_bus != pci_bus || - pos->pci_dev != pci_dev) - continue; - - if (pos->devid_override) - bus->host_pci->device = pos->sprom.dev_id; - - memcpy(out, &pos->sprom, sizeof(struct ssb_sprom)); - dev_info(pos->dev, "requested by [%x:%x]", - pos->pci_bus, pos->pci_dev); - - return 0; - } - - pr_err("unable to fill SPROM for [%x:%x]\n", pci_bus, pci_dev); - - return -EINVAL; -} - -static s8 sprom_extract_antgain(const u16 *in, u16 offset, u16 mask, u16 shift) -{ - u16 v; - u8 gain; - - v = in[SPOFF(offset)]; - gain = (v & mask) >> shift; - if (gain == 0xFF) { - gain = 8; /* If unset use 2dBm */ - } else { - /* Q5.2 Fractional part is stored in 0xC0 */ - gain = ((gain & 0xC0) >> 6) | ((gain & 0x3F) << 2); - } - - return (s8)gain; -} - -static void sprom_extract_r8(struct ssb_sprom *out, const u16 *in) -{ - static const u16 pwr_info_offset[] = { - SSB_SROM8_PWR_INFO_CORE0, SSB_SROM8_PWR_INFO_CORE1, - SSB_SROM8_PWR_INFO_CORE2, SSB_SROM8_PWR_INFO_CORE3 - }; - u16 o; - int i; - - BUILD_BUG_ON(ARRAY_SIZE(pwr_info_offset) != - ARRAY_SIZE(out->core_pwr_info)); - - SPEX(board_rev, SSB_SPROM8_BOARDREV, ~0, 0); - SPEX(board_type, SSB_SPROM1_SPID, ~0, 0); - - SPEX(txpid2g[0], SSB_SPROM4_TXPID2G01, SSB_SPROM4_TXPID2G0, - SSB_SPROM4_TXPID2G0_SHIFT); - SPEX(txpid2g[1], SSB_SPROM4_TXPID2G01, SSB_SPROM4_TXPID2G1, - SSB_SPROM4_TXPID2G1_SHIFT); - SPEX(txpid2g[2], SSB_SPROM4_TXPID2G23, SSB_SPROM4_TXPID2G2, - SSB_SPROM4_TXPID2G2_SHIFT); - SPEX(txpid2g[3], SSB_SPROM4_TXPID2G23, SSB_SPROM4_TXPID2G3, - SSB_SPROM4_TXPID2G3_SHIFT); - - SPEX(txpid5gl[0], SSB_SPROM4_TXPID5GL01, SSB_SPROM4_TXPID5GL0, - SSB_SPROM4_TXPID5GL0_SHIFT); - SPEX(txpid5gl[1], SSB_SPROM4_TXPID5GL01, SSB_SPROM4_TXPID5GL1, - SSB_SPROM4_TXPID5GL1_SHIFT); - SPEX(txpid5gl[2], SSB_SPROM4_TXPID5GL23, SSB_SPROM4_TXPID5GL2, - SSB_SPROM4_TXPID5GL2_SHIFT); - SPEX(txpid5gl[3], SSB_SPROM4_TXPID5GL23, SSB_SPROM4_TXPID5GL3, - SSB_SPROM4_TXPID5GL3_SHIFT); - - SPEX(txpid5g[0], SSB_SPROM4_TXPID5G01, SSB_SPROM4_TXPID5G0, - SSB_SPROM4_TXPID5G0_SHIFT); - SPEX(txpid5g[1], SSB_SPROM4_TXPID5G01, SSB_SPROM4_TXPID5G1, - SSB_SPROM4_TXPID5G1_SHIFT); - SPEX(txpid5g[2], SSB_SPROM4_TXPID5G23, SSB_SPROM4_TXPID5G2, - SSB_SPROM4_TXPID5G2_SHIFT); - SPEX(txpid5g[3], SSB_SPROM4_TXPID5G23, SSB_SPROM4_TXPID5G3, - SSB_SPROM4_TXPID5G3_SHIFT); - - SPEX(txpid5gh[0], SSB_SPROM4_TXPID5GH01, SSB_SPROM4_TXPID5GH0, - SSB_SPROM4_TXPID5GH0_SHIFT); - SPEX(txpid5gh[1], SSB_SPROM4_TXPID5GH01, SSB_SPROM4_TXPID5GH1, - SSB_SPROM4_TXPID5GH1_SHIFT); - SPEX(txpid5gh[2], SSB_SPROM4_TXPID5GH23, SSB_SPROM4_TXPID5GH2, - SSB_SPROM4_TXPID5GH2_SHIFT); - SPEX(txpid5gh[3], SSB_SPROM4_TXPID5GH23, SSB_SPROM4_TXPID5GH3, - SSB_SPROM4_TXPID5GH3_SHIFT); - - SPEX(boardflags_lo, SSB_SPROM8_BFLLO, ~0, 0); - SPEX(boardflags_hi, SSB_SPROM8_BFLHI, ~0, 0); - SPEX(boardflags2_lo, SSB_SPROM8_BFL2LO, ~0, 0); - SPEX(boardflags2_hi, SSB_SPROM8_BFL2HI, ~0, 0); - - SPEX(alpha2[0], SSB_SPROM8_CCODE, 0xff00, 8); - SPEX(alpha2[1], SSB_SPROM8_CCODE, 0x00ff, 0); - - /* Extract core's power info */ - for (i = 0; i < ARRAY_SIZE(pwr_info_offset); i++) { - o = pwr_info_offset[i]; - SPEX(core_pwr_info[i].itssi_2g, o + SSB_SROM8_2G_MAXP_ITSSI, - SSB_SPROM8_2G_ITSSI, SSB_SPROM8_2G_ITSSI_SHIFT); - SPEX(core_pwr_info[i].maxpwr_2g, o + SSB_SROM8_2G_MAXP_ITSSI, - SSB_SPROM8_2G_MAXP, 0); - - SPEX(core_pwr_info[i].pa_2g[0], o + SSB_SROM8_2G_PA_0, ~0, 0); - SPEX(core_pwr_info[i].pa_2g[1], o + SSB_SROM8_2G_PA_1, ~0, 0); - SPEX(core_pwr_info[i].pa_2g[2], o + SSB_SROM8_2G_PA_2, ~0, 0); - - SPEX(core_pwr_info[i].itssi_5g, o + SSB_SROM8_5G_MAXP_ITSSI, - SSB_SPROM8_5G_ITSSI, SSB_SPROM8_5G_ITSSI_SHIFT); - SPEX(core_pwr_info[i].maxpwr_5g, o + SSB_SROM8_5G_MAXP_ITSSI, - SSB_SPROM8_5G_MAXP, 0); - SPEX(core_pwr_info[i].maxpwr_5gh, o + SSB_SPROM8_5GHL_MAXP, - SSB_SPROM8_5GH_MAXP, 0); - SPEX(core_pwr_info[i].maxpwr_5gl, o + SSB_SPROM8_5GHL_MAXP, - SSB_SPROM8_5GL_MAXP, SSB_SPROM8_5GL_MAXP_SHIFT); - - SPEX(core_pwr_info[i].pa_5gl[0], o + SSB_SROM8_5GL_PA_0, ~0, 0); - SPEX(core_pwr_info[i].pa_5gl[1], o + SSB_SROM8_5GL_PA_1, ~0, 0); - SPEX(core_pwr_info[i].pa_5gl[2], o + SSB_SROM8_5GL_PA_2, ~0, 0); - SPEX(core_pwr_info[i].pa_5g[0], o + SSB_SROM8_5G_PA_0, ~0, 0); - SPEX(core_pwr_info[i].pa_5g[1], o + SSB_SROM8_5G_PA_1, ~0, 0); - SPEX(core_pwr_info[i].pa_5g[2], o + SSB_SROM8_5G_PA_2, ~0, 0); - SPEX(core_pwr_info[i].pa_5gh[0], o + SSB_SROM8_5GH_PA_0, ~0, 0); - SPEX(core_pwr_info[i].pa_5gh[1], o + SSB_SROM8_5GH_PA_1, ~0, 0); - SPEX(core_pwr_info[i].pa_5gh[2], o + SSB_SROM8_5GH_PA_2, ~0, 0); - } - - SPEX(fem.ghz2.tssipos, SSB_SPROM8_FEM2G, SSB_SROM8_FEM_TSSIPOS, - SSB_SROM8_FEM_TSSIPOS_SHIFT); - SPEX(fem.ghz2.extpa_gain, SSB_SPROM8_FEM2G, SSB_SROM8_FEM_EXTPA_GAIN, - SSB_SROM8_FEM_EXTPA_GAIN_SHIFT); - SPEX(fem.ghz2.pdet_range, SSB_SPROM8_FEM2G, SSB_SROM8_FEM_PDET_RANGE, - SSB_SROM8_FEM_PDET_RANGE_SHIFT); - SPEX(fem.ghz2.tr_iso, SSB_SPROM8_FEM2G, SSB_SROM8_FEM_TR_ISO, - SSB_SROM8_FEM_TR_ISO_SHIFT); - SPEX(fem.ghz2.antswlut, SSB_SPROM8_FEM2G, SSB_SROM8_FEM_ANTSWLUT, - SSB_SROM8_FEM_ANTSWLUT_SHIFT); - - SPEX(fem.ghz5.tssipos, SSB_SPROM8_FEM5G, SSB_SROM8_FEM_TSSIPOS, - SSB_SROM8_FEM_TSSIPOS_SHIFT); - SPEX(fem.ghz5.extpa_gain, SSB_SPROM8_FEM5G, SSB_SROM8_FEM_EXTPA_GAIN, - SSB_SROM8_FEM_EXTPA_GAIN_SHIFT); - SPEX(fem.ghz5.pdet_range, SSB_SPROM8_FEM5G, SSB_SROM8_FEM_PDET_RANGE, - SSB_SROM8_FEM_PDET_RANGE_SHIFT); - SPEX(fem.ghz5.tr_iso, SSB_SPROM8_FEM5G, SSB_SROM8_FEM_TR_ISO, - SSB_SROM8_FEM_TR_ISO_SHIFT); - SPEX(fem.ghz5.antswlut, SSB_SPROM8_FEM5G, SSB_SROM8_FEM_ANTSWLUT, - SSB_SROM8_FEM_ANTSWLUT_SHIFT); - - SPEX(ant_available_a, SSB_SPROM8_ANTAVAIL, SSB_SPROM8_ANTAVAIL_A, - SSB_SPROM8_ANTAVAIL_A_SHIFT); - SPEX(ant_available_bg, SSB_SPROM8_ANTAVAIL, SSB_SPROM8_ANTAVAIL_BG, - SSB_SPROM8_ANTAVAIL_BG_SHIFT); - SPEX(maxpwr_bg, SSB_SPROM8_MAXP_BG, SSB_SPROM8_MAXP_BG_MASK, 0); - SPEX(itssi_bg, SSB_SPROM8_MAXP_BG, SSB_SPROM8_ITSSI_BG, - SSB_SPROM8_ITSSI_BG_SHIFT); - SPEX(maxpwr_a, SSB_SPROM8_MAXP_A, SSB_SPROM8_MAXP_A_MASK, 0); - SPEX(itssi_a, SSB_SPROM8_MAXP_A, SSB_SPROM8_ITSSI_A, - SSB_SPROM8_ITSSI_A_SHIFT); - SPEX(maxpwr_ah, SSB_SPROM8_MAXP_AHL, SSB_SPROM8_MAXP_AH_MASK, 0); - SPEX(maxpwr_al, SSB_SPROM8_MAXP_AHL, SSB_SPROM8_MAXP_AL_MASK, - SSB_SPROM8_MAXP_AL_SHIFT); - SPEX(gpio0, SSB_SPROM8_GPIOA, SSB_SPROM8_GPIOA_P0, 0); - SPEX(gpio1, SSB_SPROM8_GPIOA, SSB_SPROM8_GPIOA_P1, - SSB_SPROM8_GPIOA_P1_SHIFT); - SPEX(gpio2, SSB_SPROM8_GPIOB, SSB_SPROM8_GPIOB_P2, 0); - SPEX(gpio3, SSB_SPROM8_GPIOB, SSB_SPROM8_GPIOB_P3, - SSB_SPROM8_GPIOB_P3_SHIFT); - SPEX(tri2g, SSB_SPROM8_TRI25G, SSB_SPROM8_TRI2G, 0); - SPEX(tri5g, SSB_SPROM8_TRI25G, SSB_SPROM8_TRI5G, - SSB_SPROM8_TRI5G_SHIFT); - SPEX(tri5gl, SSB_SPROM8_TRI5GHL, SSB_SPROM8_TRI5GL, 0); - SPEX(tri5gh, SSB_SPROM8_TRI5GHL, SSB_SPROM8_TRI5GH, - SSB_SPROM8_TRI5GH_SHIFT); - SPEX(rxpo2g, SSB_SPROM8_RXPO, SSB_SPROM8_RXPO2G, - SSB_SPROM8_RXPO2G_SHIFT); - SPEX(rxpo5g, SSB_SPROM8_RXPO, SSB_SPROM8_RXPO5G, - SSB_SPROM8_RXPO5G_SHIFT); - SPEX(rssismf2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_RSSISMF2G, 0); - SPEX(rssismc2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_RSSISMC2G, - SSB_SPROM8_RSSISMC2G_SHIFT); - SPEX(rssisav2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_RSSISAV2G, - SSB_SPROM8_RSSISAV2G_SHIFT); - SPEX(bxa2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_BXA2G, - SSB_SPROM8_BXA2G_SHIFT); - SPEX(rssismf5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_RSSISMF5G, 0); - SPEX(rssismc5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_RSSISMC5G, - SSB_SPROM8_RSSISMC5G_SHIFT); - SPEX(rssisav5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_RSSISAV5G, - SSB_SPROM8_RSSISAV5G_SHIFT); - SPEX(bxa5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_BXA5G, - SSB_SPROM8_BXA5G_SHIFT); - - SPEX(pa0b0, SSB_SPROM8_PA0B0, ~0, 0); - SPEX(pa0b1, SSB_SPROM8_PA0B1, ~0, 0); - SPEX(pa0b2, SSB_SPROM8_PA0B2, ~0, 0); - SPEX(pa1b0, SSB_SPROM8_PA1B0, ~0, 0); - SPEX(pa1b1, SSB_SPROM8_PA1B1, ~0, 0); - SPEX(pa1b2, SSB_SPROM8_PA1B2, ~0, 0); - SPEX(pa1lob0, SSB_SPROM8_PA1LOB0, ~0, 0); - SPEX(pa1lob1, SSB_SPROM8_PA1LOB1, ~0, 0); - SPEX(pa1lob2, SSB_SPROM8_PA1LOB2, ~0, 0); - SPEX(pa1hib0, SSB_SPROM8_PA1HIB0, ~0, 0); - SPEX(pa1hib1, SSB_SPROM8_PA1HIB1, ~0, 0); - SPEX(pa1hib2, SSB_SPROM8_PA1HIB2, ~0, 0); - SPEX(cck2gpo, SSB_SPROM8_CCK2GPO, ~0, 0); - SPEX32(ofdm2gpo, SSB_SPROM8_OFDM2GPO, ~0, 0); - SPEX32(ofdm5glpo, SSB_SPROM8_OFDM5GLPO, ~0, 0); - SPEX32(ofdm5gpo, SSB_SPROM8_OFDM5GPO, ~0, 0); - SPEX32(ofdm5ghpo, SSB_SPROM8_OFDM5GHPO, ~0, 0); - - /* Extract the antenna gain values. */ - out->antenna_gain.a0 = sprom_extract_antgain(in, - SSB_SPROM8_AGAIN01, - SSB_SPROM8_AGAIN0, - SSB_SPROM8_AGAIN0_SHIFT); - out->antenna_gain.a1 = sprom_extract_antgain(in, - SSB_SPROM8_AGAIN01, - SSB_SPROM8_AGAIN1, - SSB_SPROM8_AGAIN1_SHIFT); - out->antenna_gain.a2 = sprom_extract_antgain(in, - SSB_SPROM8_AGAIN23, - SSB_SPROM8_AGAIN2, - SSB_SPROM8_AGAIN2_SHIFT); - out->antenna_gain.a3 = sprom_extract_antgain(in, - SSB_SPROM8_AGAIN23, - SSB_SPROM8_AGAIN3, - SSB_SPROM8_AGAIN3_SHIFT); - - SPEX(leddc_on_time, SSB_SPROM8_LEDDC, SSB_SPROM8_LEDDC_ON, - SSB_SPROM8_LEDDC_ON_SHIFT); - SPEX(leddc_off_time, SSB_SPROM8_LEDDC, SSB_SPROM8_LEDDC_OFF, - SSB_SPROM8_LEDDC_OFF_SHIFT); - - SPEX(txchain, SSB_SPROM8_TXRXC, SSB_SPROM8_TXRXC_TXCHAIN, - SSB_SPROM8_TXRXC_TXCHAIN_SHIFT); - SPEX(rxchain, SSB_SPROM8_TXRXC, SSB_SPROM8_TXRXC_RXCHAIN, - SSB_SPROM8_TXRXC_RXCHAIN_SHIFT); - SPEX(antswitch, SSB_SPROM8_TXRXC, SSB_SPROM8_TXRXC_SWITCH, - SSB_SPROM8_TXRXC_SWITCH_SHIFT); - - SPEX(opo, SSB_SPROM8_OFDM2GPO, 0x00ff, 0); - - SPEX_ARRAY8(mcs2gpo, SSB_SPROM8_2G_MCSPO, ~0, 0); - SPEX_ARRAY8(mcs5gpo, SSB_SPROM8_5G_MCSPO, ~0, 0); - SPEX_ARRAY8(mcs5glpo, SSB_SPROM8_5GL_MCSPO, ~0, 0); - SPEX_ARRAY8(mcs5ghpo, SSB_SPROM8_5GH_MCSPO, ~0, 0); - - SPEX(rawtempsense, SSB_SPROM8_RAWTS, SSB_SPROM8_RAWTS_RAWTEMP, - SSB_SPROM8_RAWTS_RAWTEMP_SHIFT); - SPEX(measpower, SSB_SPROM8_RAWTS, SSB_SPROM8_RAWTS_MEASPOWER, - SSB_SPROM8_RAWTS_MEASPOWER_SHIFT); - SPEX(tempsense_slope, SSB_SPROM8_OPT_CORRX, - SSB_SPROM8_OPT_CORRX_TEMP_SLOPE, - SSB_SPROM8_OPT_CORRX_TEMP_SLOPE_SHIFT); - SPEX(tempcorrx, SSB_SPROM8_OPT_CORRX, SSB_SPROM8_OPT_CORRX_TEMPCORRX, - SSB_SPROM8_OPT_CORRX_TEMPCORRX_SHIFT); - SPEX(tempsense_option, SSB_SPROM8_OPT_CORRX, - SSB_SPROM8_OPT_CORRX_TEMP_OPTION, - SSB_SPROM8_OPT_CORRX_TEMP_OPTION_SHIFT); - SPEX(freqoffset_corr, SSB_SPROM8_HWIQ_IQSWP, - SSB_SPROM8_HWIQ_IQSWP_FREQ_CORR, - SSB_SPROM8_HWIQ_IQSWP_FREQ_CORR_SHIFT); - SPEX(iqcal_swp_dis, SSB_SPROM8_HWIQ_IQSWP, - SSB_SPROM8_HWIQ_IQSWP_IQCAL_SWP, - SSB_SPROM8_HWIQ_IQSWP_IQCAL_SWP_SHIFT); - SPEX(hw_iqcal_en, SSB_SPROM8_HWIQ_IQSWP, SSB_SPROM8_HWIQ_IQSWP_HW_IQCAL, - SSB_SPROM8_HWIQ_IQSWP_HW_IQCAL_SHIFT); - - SPEX(bw40po, SSB_SPROM8_BW40PO, ~0, 0); - SPEX(cddpo, SSB_SPROM8_CDDPO, ~0, 0); - SPEX(stbcpo, SSB_SPROM8_STBCPO, ~0, 0); - SPEX(bwduppo, SSB_SPROM8_BWDUPPO, ~0, 0); - - SPEX(tempthresh, SSB_SPROM8_THERMAL, SSB_SPROM8_THERMAL_TRESH, - SSB_SPROM8_THERMAL_TRESH_SHIFT); - SPEX(tempoffset, SSB_SPROM8_THERMAL, SSB_SPROM8_THERMAL_OFFSET, - SSB_SPROM8_THERMAL_OFFSET_SHIFT); - SPEX(phycal_tempdelta, SSB_SPROM8_TEMPDELTA, - SSB_SPROM8_TEMPDELTA_PHYCAL, - SSB_SPROM8_TEMPDELTA_PHYCAL_SHIFT); - SPEX(temps_period, SSB_SPROM8_TEMPDELTA, SSB_SPROM8_TEMPDELTA_PERIOD, - SSB_SPROM8_TEMPDELTA_PERIOD_SHIFT); - SPEX(temps_hysteresis, SSB_SPROM8_TEMPDELTA, - SSB_SPROM8_TEMPDELTA_HYSTERESIS, - SSB_SPROM8_TEMPDELTA_HYSTERESIS_SHIFT); -} - -static int sprom_extract(struct bcma_fbs *priv, const u16 *in, u16 size) -{ - struct ssb_sprom *out = &priv->sprom; - - memset(out, 0, sizeof(*out)); - - out->revision = in[size - 1] & 0x00FF; - if (out->revision < 8 || out->revision > 11) { - dev_warn(priv->dev, - "Unsupported SPROM revision %d detected." - " Will extract v8\n", - out->revision); - out->revision = 8; - } - - sprom_extract_r8(out, in); - - return 0; -} - -static void bcma_fbs_fixup(struct bcma_fbs *priv, u16 *sprom) -{ - struct device_node *node = priv->dev->of_node; - u32 fixups, off, val; - int i = 0; - - if (!of_get_property(node, "brcm,sprom-fixups", &fixups)) - return; - - fixups /= sizeof(u32); - - dev_info(priv->dev, "patching SPROM with %u fixups...\n", fixups >> 1); - - while (i < fixups) { - if (of_property_read_u32_index(node, "brcm,sprom-fixups", - i++, &off)) { - dev_err(priv->dev, "error reading fixup[%u] offset\n", - i - 1); - return; - } - - if (of_property_read_u32_index(node, "brcm,sprom-fixups", - i++, &val)) { - dev_err(priv->dev, "error reading fixup[%u] value\n", - i - 1); - return; - } - - dev_dbg(priv->dev, "fixup[%d]=0x%04x\n", off, val); - - sprom[off] = val; - } -} - -static bool sprom_override_devid(struct bcma_fbs *priv, struct ssb_sprom *out, - const u16 *in) -{ - SPEX(dev_id, 0x0060, 0xFFFF, 0); - return !!out->dev_id; -} - -static void bcma_fbs_set(struct bcma_fbs *priv, struct device_node *node) -{ - struct ssb_sprom *sprom = &priv->sprom; - const struct firmware *fw; - const char *sprom_name; - int err; - - if (of_property_read_string(node, "brcm,sprom", &sprom_name)) - sprom_name = NULL; - - if (sprom_name) { - err = request_firmware_direct(&fw, sprom_name, priv->dev); - if (err) - dev_err(priv->dev, "%s load error\n", sprom_name); - } else { - err = -ENOENT; - } - - if (err) { - sprom->revision = 0x02; - sprom->board_rev = 0x0017; - sprom->country_code = 0x00; - sprom->ant_available_bg = 0x03; - sprom->pa0b0 = 0x15ae; - sprom->pa0b1 = 0xfa85; - sprom->pa0b2 = 0xfe8d; - sprom->pa1b0 = 0xffff; - sprom->pa1b1 = 0xffff; - sprom->pa1b2 = 0xffff; - sprom->gpio0 = 0xff; - sprom->gpio1 = 0xff; - sprom->gpio2 = 0xff; - sprom->gpio3 = 0xff; - sprom->maxpwr_bg = 0x4c; - sprom->itssi_bg = 0x00; - sprom->boardflags_lo = 0x2848; - sprom->boardflags_hi = 0x0000; - priv->devid_override = false; - - dev_warn(priv->dev, "using basic SPROM\n"); - } else { - size_t size = min(fw->size, (size_t) BCMA_FBS_MAX_SIZE); - u16 tmp_sprom[BCMA_FBS_MAX_SIZE >> 1]; - u32 i, j; - - for (i = 0, j = 0; i < size; i += 2, j++) - tmp_sprom[j] = (fw->data[i] << 8) | fw->data[i + 1]; - - release_firmware(fw); - bcma_fbs_fixup(priv, tmp_sprom); - sprom_extract(priv, tmp_sprom, size >> 1); - - priv->devid_override = sprom_override_devid(priv, sprom, - tmp_sprom); - } -} - -static int bcma_fbs_probe(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - struct device_node *node = dev->of_node; - struct bcma_fbs *priv; - unsigned long flags; - u8 mac[ETH_ALEN]; - - priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); - if (!priv) - return -ENOMEM; - - priv->dev = dev; - - bcma_fbs_set(priv, node); - - of_property_read_u32(node, "pci-bus", &priv->pci_bus); - of_property_read_u32(node, "pci-dev", &priv->pci_dev); - - of_get_mac_address(node, mac); - if (is_valid_ether_addr(mac)) { - dev_info(dev, "mtd mac %pM\n", mac); - } else { - eth_random_addr(mac); - dev_info(dev, "random mac %pM\n", mac); - } - - memcpy(priv->sprom.il0mac, mac, ETH_ALEN); - memcpy(priv->sprom.et0mac, mac, ETH_ALEN); - memcpy(priv->sprom.et1mac, mac, ETH_ALEN); - memcpy(priv->sprom.et2mac, mac, ETH_ALEN); - - spin_lock_irqsave(&bcma_fbs_lock, flags); - list_add(&priv->list, &bcma_fbs_list); - spin_unlock_irqrestore(&bcma_fbs_lock, flags); - - dev_info(dev, "registered SPROM for [%x:%x]\n", - priv->pci_bus, priv->pci_dev); - - return 0; -} - -static const struct of_device_id bcma_fbs_of_match[] = { - { .compatible = "brcm,bcma-sprom", }, - { /* sentinel */ } -}; -MODULE_DEVICE_TABLE(of, bcma_fbs_of_match); - -static struct platform_driver bcma_fbs_driver = { - .probe = bcma_fbs_probe, - .driver = { - .name = "bcma-sprom", - .of_match_table = bcma_fbs_of_match, - }, -}; - -int __init bcma_fbs_register(void) -{ - return platform_driver_register(&bcma_fbs_driver); -} diff --git a/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/Kconfig b/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/Kconfig deleted file mode 100644 index 17d590890da6e6..00000000000000 --- a/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/Kconfig +++ /dev/null @@ -1,112 +0,0 @@ -config MTD_SPLIT - def_bool n - help - Generic MTD split support. - -config MTD_SPLIT_SUPPORT - def_bool MTD = y - -comment "Rootfs partition parsers" - -config MTD_SPLIT_SQUASHFS_ROOT - bool "Squashfs based root partition parser" - depends on MTD_SPLIT_SUPPORT - select MTD_SPLIT - help - This provides a parsing function which allows to detect the - offset and size of the unused portion of a rootfs partition - containing a squashfs. - -comment "Firmware partition parsers" - -config MTD_SPLIT_BCM63XX_FW - bool "BCM63xx firmware parser" - depends on MTD_SPLIT_SUPPORT - select MTD_SPLIT - -config MTD_SPLIT_BCM_WFI_FW - bool "Broadcom Whole Flash Image parser" - depends on MTD_SPLIT_SUPPORT - select MTD_SPLIT - -config MTD_SPLIT_CFE_BOOTFS - bool "Parser finding rootfs appended to the CFE bootfs" - depends on MTD_SPLIT_SUPPORT && (ARCH_BCM4908 || ARCH_BCMBCA) - select MTD_SPLIT - help - cferom on BCM4908 (and bcm63xx) uses JFFS2 bootfs partition - for storing kernel, cferam and some device specific files. - There isn't any straight way of storing rootfs so it gets - appended to the JFFS2 bootfs partition. Kernel needs to find - it and run init from it. This parser is responsible for - finding appended rootfs. - -config MTD_SPLIT_SEAMA_FW - bool "Seama firmware parser" - depends on MTD_SPLIT_SUPPORT - select MTD_SPLIT - -config MTD_SPLIT_WRGG_FW - bool "WRGG firmware parser" - depends on MTD_SPLIT_SUPPORT - select MTD_SPLIT - -config MTD_SPLIT_UIMAGE_FW - bool "uImage based firmware partition parser" - depends on MTD_SPLIT_SUPPORT - select MTD_SPLIT - -config MTD_SPLIT_FIT_FW - bool "FIT based firmware partition parser" - depends on MTD_SPLIT_SUPPORT - select MTD_SPLIT - -config MTD_SPLIT_LZMA_FW - bool "LZMA compressed kernel based firmware partition parser" - depends on MTD_SPLIT_SUPPORT - select MTD_SPLIT - -config MTD_SPLIT_TPLINK_FW - bool "TP-Link firmware parser" - depends on MTD_SPLIT_SUPPORT - select MTD_SPLIT - -config MTD_SPLIT_TRX_FW - bool "TRX image based firmware partition parser" - depends on MTD_SPLIT_SUPPORT - select MTD_SPLIT - -config MTD_SPLIT_BRNIMAGE_FW - bool "brnImage (brnboot image) firmware parser" - depends on MTD_SPLIT_SUPPORT - select MTD_SPLIT - -config MTD_SPLIT_EVA_FW - bool "EVA image based firmware partition parser" - depends on MTD_SPLIT_SUPPORT - select MTD_SPLIT - -config MTD_SPLIT_MINOR_FW - bool "Mikrotik NOR image based firmware partition parser" - depends on MTD_SPLIT_SUPPORT - select MTD_SPLIT - -config MTD_SPLIT_JIMAGE_FW - bool "JBOOT Image based firmware partition parser" - depends on MTD_SPLIT_SUPPORT - select MTD_SPLIT - -config MTD_SPLIT_ELF_FW - bool "ELF loader firmware partition parser" - depends on MTD_SPLIT_SUPPORT - select MTD_SPLIT - -config MTD_SPLIT_H3C_VFS - bool "Parser finding rootfs appended to H3C VFS" - depends on MTD_SPLIT_SUPPORT - select MTD_SPLIT - -config MTD_SPLIT_SEIL_FW - bool "IIJ SEIL firmware parser" - depends on MTD_SPLIT_SUPPORT - select MTD_SPLIT diff --git a/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/Makefile b/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/Makefile deleted file mode 100644 index e9d63c833258ab..00000000000000 --- a/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/Makefile +++ /dev/null @@ -1,19 +0,0 @@ -obj-$(CONFIG_MTD_SPLIT) += mtdsplit.o -obj-$(CONFIG_MTD_SPLIT_BCM63XX_FW) += mtdsplit_bcm63xx.o -obj-$(CONFIG_MTD_SPLIT_BCM_WFI_FW) += mtdsplit_bcm_wfi.o -obj-$(CONFIG_MTD_SPLIT_CFE_BOOTFS) += mtdsplit_cfe_bootfs.o -obj-$(CONFIG_MTD_SPLIT_SEAMA_FW) += mtdsplit_seama.o -obj-$(CONFIG_MTD_SPLIT_SEIL_FW) += mtdsplit_seil.o -obj-$(CONFIG_MTD_SPLIT_SQUASHFS_ROOT) += mtdsplit_squashfs.o -obj-$(CONFIG_MTD_SPLIT_UIMAGE_FW) += mtdsplit_uimage.o -obj-$(CONFIG_MTD_SPLIT_FIT_FW) += mtdsplit_fit.o -obj-$(CONFIG_MTD_SPLIT_LZMA_FW) += mtdsplit_lzma.o -obj-$(CONFIG_MTD_SPLIT_TPLINK_FW) += mtdsplit_tplink.o -obj-$(CONFIG_MTD_SPLIT_TRX_FW) += mtdsplit_trx.o -obj-$(CONFIG_MTD_SPLIT_BRNIMAGE_FW) += mtdsplit_brnimage.o -obj-$(CONFIG_MTD_SPLIT_EVA_FW) += mtdsplit_eva.o -obj-$(CONFIG_MTD_SPLIT_WRGG_FW) += mtdsplit_wrgg.o -obj-$(CONFIG_MTD_SPLIT_MINOR_FW) += mtdsplit_minor.o -obj-$(CONFIG_MTD_SPLIT_JIMAGE_FW) += mtdsplit_jimage.o -obj-$(CONFIG_MTD_SPLIT_ELF_FW) += mtdsplit_elf.o -obj-$(CONFIG_MTD_SPLIT_H3C_VFS) += mtdsplit_h3c_vfs.o diff --git a/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/mtdsplit.c b/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/mtdsplit.c deleted file mode 100644 index b2e51dcfc66b6c..00000000000000 --- a/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/mtdsplit.c +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Copyright (C) 2009-2013 Felix Fietkau - * Copyright (C) 2009-2013 Gabor Juhos - * Copyright (C) 2012 Jonas Gorski - * Copyright (C) 2013 Hauke Mehrtens - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published - * by the Free Software Foundation. - * - */ - -#define pr_fmt(fmt) "mtdsplit: " fmt - -#include -#include -#include -#include -#include -#include -#include - -#include "mtdsplit.h" - -#define UBI_EC_MAGIC 0x55424923 /* UBI# */ - -struct squashfs_super_block { - __le32 s_magic; - __le32 pad0[9]; - __le64 bytes_used; -}; - -int mtd_get_squashfs_len(struct mtd_info *master, - size_t offset, - size_t *squashfs_len) -{ - struct squashfs_super_block sb; - size_t retlen; - int err; - - err = mtd_read(master, offset, sizeof(sb), &retlen, (void *)&sb); - if (err || (retlen != sizeof(sb))) { - pr_alert("error occured while reading from \"%s\"\n", - master->name); - return -EIO; - } - - if (le32_to_cpu(sb.s_magic) != SQUASHFS_MAGIC) { - pr_alert("no squashfs found in \"%s\"\n", master->name); - return -EINVAL; - } - - retlen = le64_to_cpu(sb.bytes_used); - if (retlen <= 0) { - pr_alert("squashfs is empty in \"%s\"\n", master->name); - return -ENODEV; - } - - if (offset + retlen > master->size) { - pr_alert("squashfs has invalid size in \"%s\"\n", - master->name); - return -EINVAL; - } - - *squashfs_len = retlen; - return 0; -} -EXPORT_SYMBOL_GPL(mtd_get_squashfs_len); - -static ssize_t mtd_next_eb(struct mtd_info *mtd, size_t offset) -{ - return mtd_rounddown_to_eb(offset, mtd) + mtd->erasesize; -} - -int mtd_check_rootfs_magic(struct mtd_info *mtd, size_t offset, - enum mtdsplit_part_type *type) -{ - u32 magic; - size_t retlen; - int ret; - - ret = mtd_read(mtd, offset, sizeof(magic), &retlen, - (unsigned char *) &magic); - if (ret) - return ret; - - if (retlen != sizeof(magic)) - return -EIO; - - if (le32_to_cpu(magic) == SQUASHFS_MAGIC) { - if (type) - *type = MTDSPLIT_PART_TYPE_SQUASHFS; - return 0; - } else if (magic == 0x19852003) { - if (type) - *type = MTDSPLIT_PART_TYPE_JFFS2; - return 0; - } else if (be32_to_cpu(magic) == UBI_EC_MAGIC) { - if (type) - *type = MTDSPLIT_PART_TYPE_UBI; - return 0; - } - - return -EINVAL; -} -EXPORT_SYMBOL_GPL(mtd_check_rootfs_magic); - -int mtd_find_rootfs_from(struct mtd_info *mtd, - size_t from, - size_t limit, - size_t *ret_offset, - enum mtdsplit_part_type *type) -{ - size_t offset; - int err; - - for (offset = from; offset < limit; - offset = mtd_next_eb(mtd, offset)) { - err = mtd_check_rootfs_magic(mtd, offset, type); - if (err) - continue; - - *ret_offset = offset; - return 0; - } - - return -ENODEV; -} -EXPORT_SYMBOL_GPL(mtd_find_rootfs_from); - diff --git a/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/mtdsplit.h b/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/mtdsplit.h deleted file mode 100644 index 71d62a8956b282..00000000000000 --- a/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/mtdsplit.h +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (C) 2009-2013 Felix Fietkau - * Copyright (C) 2009-2013 Gabor Juhos - * Copyright (C) 2012 Jonas Gorski - * Copyright (C) 2013 Hauke Mehrtens - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published - * by the Free Software Foundation. - * - */ - -#ifndef _MTDSPLIT_H -#define _MTDSPLIT_H - -#define KERNEL_PART_NAME "kernel" -#define ROOTFS_PART_NAME "rootfs" -#define UBI_PART_NAME "ubi" - -#define ROOTFS_SPLIT_NAME "rootfs_data" - -enum mtdsplit_part_type { - MTDSPLIT_PART_TYPE_UNK = 0, - MTDSPLIT_PART_TYPE_SQUASHFS, - MTDSPLIT_PART_TYPE_JFFS2, - MTDSPLIT_PART_TYPE_UBI, -}; - -#ifdef CONFIG_MTD_SPLIT -int mtd_get_squashfs_len(struct mtd_info *master, - size_t offset, - size_t *squashfs_len); - -int mtd_check_rootfs_magic(struct mtd_info *mtd, size_t offset, - enum mtdsplit_part_type *type); - -int mtd_find_rootfs_from(struct mtd_info *mtd, - size_t from, - size_t limit, - size_t *ret_offset, - enum mtdsplit_part_type *type); - -#else -static inline int mtd_get_squashfs_len(struct mtd_info *master, - size_t offset, - size_t *squashfs_len) -{ - return -ENODEV; -} - -static inline int mtd_check_rootfs_magic(struct mtd_info *mtd, size_t offset, - enum mtdsplit_part_type *type) -{ - return -EINVAL; -} - -static inline int mtd_find_rootfs_from(struct mtd_info *mtd, - size_t from, - size_t limit, - size_t *ret_offset, - enum mtdsplit_part_type *type) -{ - return -ENODEV; -} -#endif /* CONFIG_MTD_SPLIT */ - -#endif /* _MTDSPLIT_H */ diff --git a/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/mtdsplit_bcm63xx.c b/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/mtdsplit_bcm63xx.c deleted file mode 100644 index 3a4b8a754fdea6..00000000000000 --- a/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/mtdsplit_bcm63xx.c +++ /dev/null @@ -1,186 +0,0 @@ -/* - * Firmware MTD split for BCM63XX, based on bcm63xxpart.c - * - * Copyright (C) 2006-2008 Florian Fainelli - * Copyright (C) 2006-2008 Mike Albon - * Copyright (C) 2009-2010 Daniel Dickinson - * Copyright (C) 2011-2013 Jonas Gorski - * Copyright (C) 2015 Simon Arlott - * Copyright (C) 2017 Álvaro Fernández Rojas - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published - * by the Free Software Foundation. - * - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "mtdsplit.h" - -/* Ensure strings read from flash structs are null terminated */ -#define STR_NULL_TERMINATE(x) \ - do { char *_str = (x); _str[sizeof(x) - 1] = 0; } while (0) - -#define BCM63XX_NR_PARTS 2 - -static int bcm63xx_read_image_tag(struct mtd_info *master, loff_t offset, - struct bcm_tag *hdr) -{ - int ret; - size_t retlen; - u32 computed_crc; - - ret = mtd_read(master, offset, sizeof(*hdr), &retlen, (void *) hdr); - if (ret) - return ret; - - if (retlen != sizeof(*hdr)) - return -EIO; - - computed_crc = crc32_le(IMAGETAG_CRC_START, (u8 *)hdr, - offsetof(struct bcm_tag, header_crc)); - if (computed_crc == hdr->header_crc) { - STR_NULL_TERMINATE(hdr->board_id); - STR_NULL_TERMINATE(hdr->tag_version); - - pr_info("CFE image tag found at 0x%llx with version %s, " - "board type %s\n", offset, hdr->tag_version, - hdr->board_id); - - return 0; - } else { - pr_err("CFE image tag at 0x%llx CRC invalid " - "(expected %08x, actual %08x)\n", - offset, hdr->header_crc, computed_crc); - - return 1; - } -} - -static int bcm63xx_parse_partitions(struct mtd_info *master, - const struct mtd_partition **pparts, - struct bcm_tag *hdr) -{ - struct mtd_partition *parts; - unsigned int flash_image_start; - unsigned int kernel_address; - unsigned int kernel_length; - size_t kernel_offset = 0, kernel_size = 0; - size_t rootfs_offset = 0, rootfs_size = 0; - int kernel_part, rootfs_part; - - STR_NULL_TERMINATE(hdr->flash_image_start); - if (kstrtouint(hdr->flash_image_start, 10, &flash_image_start) || - flash_image_start < BCM963XX_EXTENDED_SIZE) { - pr_err("invalid rootfs address: %*ph\n", - (int) sizeof(hdr->flash_image_start), - hdr->flash_image_start); - return -EINVAL; - } - - STR_NULL_TERMINATE(hdr->kernel_address); - if (kstrtouint(hdr->kernel_address, 10, &kernel_address) || - kernel_address < BCM963XX_EXTENDED_SIZE) { - pr_err("invalid kernel address: %*ph\n", - (int) sizeof(hdr->kernel_address), hdr->kernel_address); - return -EINVAL; - } - - STR_NULL_TERMINATE(hdr->kernel_length); - if (kstrtouint(hdr->kernel_length, 10, &kernel_length) || - !kernel_length) { - pr_err("invalid kernel length: %*ph\n", - (int) sizeof(hdr->kernel_length), hdr->kernel_length); - return -EINVAL; - } - - kernel_offset = kernel_address - BCM963XX_EXTENDED_SIZE - - mtdpart_get_offset(master); - kernel_size = kernel_length; - - if (flash_image_start < kernel_address) { - /* rootfs first */ - rootfs_part = 0; - kernel_part = 1; - rootfs_offset = flash_image_start - BCM963XX_EXTENDED_SIZE - - mtdpart_get_offset(master); - rootfs_size = kernel_offset - rootfs_offset; - } else { - /* kernel first */ - kernel_part = 0; - rootfs_part = 1; - rootfs_offset = kernel_offset + kernel_size; - rootfs_size = master->size - rootfs_offset; - } - - if (mtd_check_rootfs_magic(master, rootfs_offset, NULL)) - pr_warn("rootfs magic not found\n"); - - parts = kzalloc(BCM63XX_NR_PARTS * sizeof(*parts), GFP_KERNEL); - if (!parts) - return -ENOMEM; - - parts[kernel_part].name = KERNEL_PART_NAME; - parts[kernel_part].offset = kernel_offset; - parts[kernel_part].size = kernel_size; - - parts[rootfs_part].name = ROOTFS_PART_NAME; - parts[rootfs_part].offset = rootfs_offset; - parts[rootfs_part].size = rootfs_size; - - *pparts = parts; - return BCM63XX_NR_PARTS; -} - -static int mtdsplit_parse_bcm63xx(struct mtd_info *master, - const struct mtd_partition **pparts, - struct mtd_part_parser_data *data) -{ - struct bcm_tag hdr; - loff_t offset; - - if (mtd_type_is_nand(master)) - return -EINVAL; - - /* find bcm63xx_cfe image on erase block boundaries */ - for (offset = 0; offset < master->size; offset += master->erasesize) { - if (!bcm63xx_read_image_tag(master, offset, (void *) &hdr)) - return bcm63xx_parse_partitions(master, pparts, - (void *) &hdr); - } - - return -EINVAL; -} - -static const struct of_device_id mtdsplit_fit_of_match_table[] = { - { .compatible = "brcm,bcm963xx-imagetag" }, - { }, -}; - -static struct mtd_part_parser mtdsplit_bcm63xx_parser = { - .owner = THIS_MODULE, - .name = "bcm63xx-fw", - .of_match_table = mtdsplit_fit_of_match_table, - .parse_fn = mtdsplit_parse_bcm63xx, - .type = MTD_PARSER_TYPE_FIRMWARE, -}; - -static int __init mtdsplit_bcm63xx_init(void) -{ - register_mtd_parser(&mtdsplit_bcm63xx_parser); - - return 0; -} - -module_init(mtdsplit_bcm63xx_init); diff --git a/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/mtdsplit_bcm_wfi.c b/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/mtdsplit_bcm_wfi.c deleted file mode 100644 index 1cafc91fded3dc..00000000000000 --- a/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/mtdsplit_bcm_wfi.c +++ /dev/null @@ -1,535 +0,0 @@ -/* - * MTD split for Broadcom Whole Flash Image - * - * Copyright (C) 2020 Álvaro Fernández Rojas - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published - * by the Free Software Foundation. - * - */ - -#define je16_to_cpu(x) ((x).v16) -#define je32_to_cpu(x) ((x).v32) - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "mtdsplit.h" - -#define char_to_num(c) ((c >= '0' && c <= '9') ? (c - '0') : (0)) - -#define BCM_WFI_PARTS 3 -#define BCM_WFI_SPLIT_PARTS 2 - -#define CFERAM_NAME "cferam" -#define CFERAM_NAME_LEN (sizeof(CFERAM_NAME) - 1) -#define CFERAM_NAME_MAX_LEN 32 -#define KERNEL_NAME "vmlinux.lz" -#define KERNEL_NAME_LEN (sizeof(KERNEL_NAME) - 1) -#define OPENWRT_NAME "1-openwrt" -#define OPENWRT_NAME_LEN (sizeof(OPENWRT_NAME) - 1) - -#define UBI_MAGIC 0x55424923 - -#define CFE_MAGIC_PFX "cferam." -#define CFE_MAGIC_PFX_LEN (sizeof(CFE_MAGIC_PFX) - 1) -#define CFE_MAGIC "cferam.000" -#define CFE_MAGIC_LEN (sizeof(CFE_MAGIC) - 1) -#define SERCOMM_MAGIC_PFX "eRcOmM." -#define SERCOMM_MAGIC_PFX_LEN (sizeof(SERCOMM_MAGIC_PFX) - 1) -#define SERCOMM_MAGIC "eRcOmM.000" -#define SERCOMM_MAGIC_LEN (sizeof(SERCOMM_MAGIC) - 1) - -#define PART_CFERAM "cferam" -#define PART_FIRMWARE "firmware" -#define PART_IMAGE_1 "img1" -#define PART_IMAGE_2 "img2" - -static u32 jffs2_dirent_crc(struct jffs2_raw_dirent *node) -{ - return crc32(0, node, sizeof(struct jffs2_raw_dirent) - 8); -} - -static bool jffs2_dirent_valid(struct jffs2_raw_dirent *node) -{ - return ((je16_to_cpu(node->magic) == JFFS2_MAGIC_BITMASK) && - (je16_to_cpu(node->nodetype) == JFFS2_NODETYPE_DIRENT) && - je32_to_cpu(node->ino) && - je32_to_cpu(node->node_crc) == jffs2_dirent_crc(node)); -} - -static int jffs2_find_file(struct mtd_info *mtd, uint8_t *buf, - const char *name, size_t name_len, - loff_t *offs, loff_t size, - char **out_name, size_t *out_name_len) -{ - const loff_t end = *offs + size; - struct jffs2_raw_dirent *node; - bool valid = false; - size_t retlen; - uint16_t magic; - int rc; - - for (; *offs < end; *offs += mtd->erasesize) { - unsigned int block_offs = 0; - - /* Skip CFE erased blocks */ - rc = mtd_read(mtd, *offs, sizeof(magic), &retlen, - (void *) &magic); - if (rc || retlen != sizeof(magic)) { - continue; - } - - /* Skip blocks not starting with JFFS2 magic */ - if (magic != JFFS2_MAGIC_BITMASK) - continue; - - /* Read full block */ - rc = mtd_read(mtd, *offs, mtd->erasesize, &retlen, - (void *) buf); - if (rc) - return rc; - if (retlen != mtd->erasesize) - return -EINVAL; - - while (block_offs < mtd->erasesize) { - node = (struct jffs2_raw_dirent *) &buf[block_offs]; - - if (!jffs2_dirent_valid(node)) { - block_offs += 4; - continue; - } - - if (!memcmp(node->name, OPENWRT_NAME, - OPENWRT_NAME_LEN)) { - valid = true; - } else if (!memcmp(node->name, name, name_len)) { - if (!valid) - return -EINVAL; - - if (out_name) - *out_name = kstrndup(node->name, - node->nsize, - GFP_KERNEL); - - if (out_name_len) - *out_name_len = node->nsize; - - return 0; - } - - block_offs += je32_to_cpu(node->totlen); - block_offs = (block_offs + 0x3) & ~0x3; - } - } - - return -ENOENT; -} - -static int ubifs_find(struct mtd_info *mtd, loff_t *offs, loff_t size) -{ - const loff_t end = *offs + size; - uint32_t magic; - size_t retlen; - int rc; - - for (; *offs < end; *offs += mtd->erasesize) { - rc = mtd_read(mtd, *offs, sizeof(magic), &retlen, - (unsigned char *) &magic); - if (rc || retlen != sizeof(magic)) - continue; - - if (be32_to_cpu(magic) == UBI_MAGIC) - return 0; - } - - return -ENOENT; -} - -static int parse_bcm_wfi(struct mtd_info *master, - const struct mtd_partition **pparts, - uint8_t *buf, loff_t off, loff_t size, bool cfe_part) -{ - struct device_node *mtd_node; - struct mtd_partition *parts; - loff_t cfe_off, kernel_off, rootfs_off; - unsigned int num_parts = BCM_WFI_PARTS, cur_part = 0; - const char *cferam_name = CFERAM_NAME; - size_t cferam_name_len; - int ret; - - mtd_node = mtd_get_of_node(master); - if (mtd_node) - of_property_read_string(mtd_node, "brcm,cferam", &cferam_name); - - cferam_name_len = strnlen(cferam_name, CFERAM_NAME_MAX_LEN); - if (cferam_name_len > 0) - cferam_name_len--; - - if (cfe_part) { - num_parts++; - cfe_off = off; - - ret = jffs2_find_file(master, buf, cferam_name, - cferam_name_len, &cfe_off, - size - (cfe_off - off), NULL, NULL); - if (ret) - return ret; - - kernel_off = cfe_off + master->erasesize; - } else { - kernel_off = off; - } - - ret = jffs2_find_file(master, buf, KERNEL_NAME, KERNEL_NAME_LEN, - &kernel_off, size - (kernel_off - off), - NULL, NULL); - if (ret) - return ret; - - rootfs_off = kernel_off + master->erasesize; - ret = ubifs_find(master, &rootfs_off, size - (rootfs_off - off)); - if (ret) - return ret; - - parts = kzalloc(num_parts * sizeof(*parts), GFP_KERNEL); - if (!parts) - return -ENOMEM; - - if (cfe_part) { - parts[cur_part].name = PART_CFERAM; - parts[cur_part].mask_flags = MTD_WRITEABLE; - parts[cur_part].offset = cfe_off; - parts[cur_part].size = kernel_off - cfe_off; - cur_part++; - } - - parts[cur_part].name = PART_FIRMWARE; - parts[cur_part].offset = kernel_off; - parts[cur_part].size = size - (kernel_off - off); - cur_part++; - - parts[cur_part].name = KERNEL_PART_NAME; - parts[cur_part].offset = kernel_off; - parts[cur_part].size = rootfs_off - kernel_off; - cur_part++; - - parts[cur_part].name = UBI_PART_NAME; - parts[cur_part].offset = rootfs_off; - parts[cur_part].size = size - (rootfs_off - off); - cur_part++; - - *pparts = parts; - - return num_parts; -} - -static int mtdsplit_parse_bcm_wfi(struct mtd_info *master, - const struct mtd_partition **pparts, - struct mtd_part_parser_data *data) -{ - struct device_node *mtd_node; - bool cfe_part = true; - uint8_t *buf; - int ret; - - mtd_node = mtd_get_of_node(master); - if (!mtd_node) - return -EINVAL; - - buf = kzalloc(master->erasesize, GFP_KERNEL); - if (!buf) - return -ENOMEM; - - if (of_property_read_bool(mtd_node, "brcm,no-cferam")) - cfe_part = false; - - ret = parse_bcm_wfi(master, pparts, buf, 0, master->size, cfe_part); - - kfree(buf); - - return ret; -} - -static const struct of_device_id mtdsplit_bcm_wfi_of_match[] = { - { .compatible = "brcm,wfi" }, - { }, -}; - -static struct mtd_part_parser mtdsplit_bcm_wfi_parser = { - .owner = THIS_MODULE, - .name = "bcm-wfi-fw", - .of_match_table = mtdsplit_bcm_wfi_of_match, - .parse_fn = mtdsplit_parse_bcm_wfi, - .type = MTD_PARSER_TYPE_FIRMWARE, -}; - -static int cferam_bootflag_value(const char *name, size_t name_len) -{ - int rc = -ENOENT; - - if (name && - (name_len >= CFE_MAGIC_LEN) && - !memcmp(name, CFE_MAGIC_PFX, CFE_MAGIC_PFX_LEN)) { - rc = char_to_num(name[CFE_MAGIC_PFX_LEN + 0]) * 100; - rc += char_to_num(name[CFE_MAGIC_PFX_LEN + 1]) * 10; - rc += char_to_num(name[CFE_MAGIC_PFX_LEN + 2]) * 1; - } - - return rc; -} - -static int mtdsplit_parse_bcm_wfi_split(struct mtd_info *master, - const struct mtd_partition **pparts, - struct mtd_part_parser_data *data) -{ - struct mtd_partition *parts; - loff_t cfe_off; - loff_t img1_off = 0; - loff_t img2_off = master->size / 2; - loff_t img1_size = (img2_off - img1_off); - loff_t img2_size = (master->size - img2_off); - loff_t active_off, inactive_off; - loff_t active_size, inactive_size; - const char *inactive_name; - uint8_t *buf; - char *cfe1_name = NULL, *cfe2_name = NULL; - size_t cfe1_size = 0, cfe2_size = 0; - int ret; - int bf1, bf2; - - buf = kzalloc(master->erasesize, GFP_KERNEL); - if (!buf) - return -ENOMEM; - - cfe_off = img1_off; - ret = jffs2_find_file(master, buf, CFERAM_NAME, CFERAM_NAME_LEN, - &cfe_off, img1_size, &cfe1_name, &cfe1_size); - - cfe_off = img2_off; - ret = jffs2_find_file(master, buf, CFERAM_NAME, CFERAM_NAME_LEN, - &cfe_off, img2_size, &cfe2_name, &cfe2_size); - - bf1 = cferam_bootflag_value(cfe1_name, cfe1_size); - if (bf1 >= 0) - printk("cferam: bootflag1=%d\n", bf1); - - bf2 = cferam_bootflag_value(cfe2_name, cfe2_size); - if (bf2 >= 0) - printk("cferam: bootflag2=%d\n", bf2); - - kfree(cfe1_name); - kfree(cfe2_name); - - if (bf1 >= bf2) { - active_off = img1_off; - active_size = img1_size; - inactive_off = img2_off; - inactive_size = img2_size; - inactive_name = PART_IMAGE_2; - } else { - active_off = img2_off; - active_size = img2_size; - inactive_off = img1_off; - inactive_size = img1_size; - inactive_name = PART_IMAGE_1; - } - - ret = parse_bcm_wfi(master, pparts, buf, active_off, active_size, true); - - kfree(buf); - - if (ret > 0) { - parts = kzalloc((ret + 1) * sizeof(*parts), GFP_KERNEL); - if (!parts) - return -ENOMEM; - - memcpy(parts, *pparts, ret * sizeof(*parts)); - kfree(*pparts); - - parts[ret].name = inactive_name; - parts[ret].offset = inactive_off; - parts[ret].size = inactive_size; - ret++; - - *pparts = parts; - } else { - parts = kzalloc(BCM_WFI_SPLIT_PARTS * sizeof(*parts), GFP_KERNEL); - - parts[0].name = PART_IMAGE_1; - parts[0].offset = img1_off; - parts[0].size = img1_size; - - parts[1].name = PART_IMAGE_2; - parts[1].offset = img2_off; - parts[1].size = img2_size; - - *pparts = parts; - } - - return ret; -} - -static const struct of_device_id mtdsplit_bcm_wfi_split_of_match[] = { - { .compatible = "brcm,wfi-split" }, - { }, -}; - -static struct mtd_part_parser mtdsplit_bcm_wfi_split_parser = { - .owner = THIS_MODULE, - .name = "bcm-wfi-split-fw", - .of_match_table = mtdsplit_bcm_wfi_split_of_match, - .parse_fn = mtdsplit_parse_bcm_wfi_split, - .type = MTD_PARSER_TYPE_FIRMWARE, -}; - -static int sercomm_bootflag_value(struct mtd_info *mtd, uint8_t *buf) -{ - size_t retlen; - loff_t offs; - int rc; - - for (offs = 0; offs < mtd->size; offs += mtd->erasesize) { - rc = mtd_read(mtd, offs, SERCOMM_MAGIC_LEN, &retlen, buf); - if (rc || retlen != SERCOMM_MAGIC_LEN) - continue; - - if (memcmp(buf, SERCOMM_MAGIC_PFX, SERCOMM_MAGIC_PFX_LEN)) - continue; - - rc = char_to_num(buf[SERCOMM_MAGIC_PFX_LEN + 0]) * 100; - rc += char_to_num(buf[SERCOMM_MAGIC_PFX_LEN + 1]) * 10; - rc += char_to_num(buf[SERCOMM_MAGIC_PFX_LEN + 2]) * 1; - - return rc; - } - - return -ENOENT; -} - -static int mtdsplit_parse_ser_wfi(struct mtd_info *master, - const struct mtd_partition **pparts, - struct mtd_part_parser_data *data) -{ - struct mtd_partition *parts; - struct mtd_info *mtd_bf1, *mtd_bf2; - loff_t img1_off = 0; - loff_t img2_off = master->size / 2; - loff_t img1_size = (img2_off - img1_off); - loff_t img2_size = (master->size - img2_off); - loff_t active_off, inactive_off; - loff_t active_size, inactive_size; - const char *inactive_name; - uint8_t *buf; - int bf1, bf2; - int ret; - - mtd_bf1 = get_mtd_device_nm("bootflag1"); - if (IS_ERR(mtd_bf1)) - return -ENOENT; - - mtd_bf2 = get_mtd_device_nm("bootflag2"); - if (IS_ERR(mtd_bf2)) - return -ENOENT; - - buf = kzalloc(master->erasesize, GFP_KERNEL); - if (!buf) - return -ENOMEM; - - bf1 = sercomm_bootflag_value(mtd_bf1, buf); - if (bf1 >= 0) - printk("sercomm: bootflag1=%d\n", bf1); - - bf2 = sercomm_bootflag_value(mtd_bf2, buf); - if (bf2 >= 0) - printk("sercomm: bootflag2=%d\n", bf2); - - if (bf1 == bf2 && bf2 >= 0) { - struct erase_info bf_erase; - - bf2 = -ENOENT; - bf_erase.addr = 0; - bf_erase.len = mtd_bf2->size; - mtd_erase(mtd_bf2, &bf_erase); - } - - if (bf1 >= bf2) { - active_off = img1_off; - active_size = img1_size; - inactive_off = img2_off; - inactive_size = img2_size; - inactive_name = PART_IMAGE_2; - } else { - active_off = img2_off; - active_size = img2_size; - inactive_off = img1_off; - inactive_size = img1_size; - inactive_name = PART_IMAGE_1; - } - - ret = parse_bcm_wfi(master, pparts, buf, active_off, active_size, false); - - kfree(buf); - - if (ret > 0) { - parts = kzalloc((ret + 1) * sizeof(*parts), GFP_KERNEL); - if (!parts) - return -ENOMEM; - - memcpy(parts, *pparts, ret * sizeof(*parts)); - kfree(*pparts); - - parts[ret].name = inactive_name; - parts[ret].offset = inactive_off; - parts[ret].size = inactive_size; - ret++; - - *pparts = parts; - } else { - parts = kzalloc(BCM_WFI_SPLIT_PARTS * sizeof(*parts), GFP_KERNEL); - - parts[0].name = PART_IMAGE_1; - parts[0].offset = img1_off; - parts[0].size = img1_size; - - parts[1].name = PART_IMAGE_2; - parts[1].offset = img2_off; - parts[1].size = img2_size; - - *pparts = parts; - } - - return ret; -} - -static const struct of_device_id mtdsplit_ser_wfi_of_match[] = { - { .compatible = "sercomm,wfi" }, - { }, -}; - -static struct mtd_part_parser mtdsplit_ser_wfi_parser = { - .owner = THIS_MODULE, - .name = "ser-wfi-fw", - .of_match_table = mtdsplit_ser_wfi_of_match, - .parse_fn = mtdsplit_parse_ser_wfi, - .type = MTD_PARSER_TYPE_FIRMWARE, -}; - -static int __init mtdsplit_bcm_wfi_init(void) -{ - register_mtd_parser(&mtdsplit_bcm_wfi_parser); - register_mtd_parser(&mtdsplit_bcm_wfi_split_parser); - register_mtd_parser(&mtdsplit_ser_wfi_parser); - - return 0; -} - -module_init(mtdsplit_bcm_wfi_init); diff --git a/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/mtdsplit_brnimage.c b/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/mtdsplit_brnimage.c deleted file mode 100644 index 3f2d79601a1446..00000000000000 --- a/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/mtdsplit_brnimage.c +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright (C) 2012 John Crispin - * Copyright (C) 2015 Martin Blumenstingl - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published - * by the Free Software Foundation. - * - */ - -#include -#include -#include -#include -#include -#include -#include - -#include "mtdsplit.h" - -#define BRNIMAGE_NR_PARTS 2 - -#define BRNIMAGE_ALIGN_BYTES 0x400 -#define BRNIMAGE_FOOTER_SIZE 12 - -#define BRNIMAGE_MIN_OVERHEAD (BRNIMAGE_FOOTER_SIZE) -#define BRNIMAGE_MAX_OVERHEAD (BRNIMAGE_ALIGN_BYTES + BRNIMAGE_FOOTER_SIZE) - -static int mtdsplit_parse_brnimage(struct mtd_info *master, - const struct mtd_partition **pparts, - struct mtd_part_parser_data *data) -{ - struct mtd_partition *parts; - uint32_t buf; - unsigned long rootfs_offset, rootfs_size, kernel_size; - size_t len; - int ret = 0; - - for (rootfs_offset = 0; rootfs_offset < master->size; - rootfs_offset += BRNIMAGE_ALIGN_BYTES) { - ret = mtd_check_rootfs_magic(master, rootfs_offset, NULL); - if (!ret) - break; - } - - if (ret) - return ret; - - if (rootfs_offset >= master->size) - return -EINVAL; - - ret = mtd_read(master, rootfs_offset - BRNIMAGE_FOOTER_SIZE, 4, &len, - (void *)&buf); - if (ret) - return ret; - - if (len != 4) - return -EIO; - - kernel_size = le32_to_cpu(buf); - - if (kernel_size > (rootfs_offset - BRNIMAGE_MIN_OVERHEAD)) - return -EINVAL; - - if (kernel_size < (rootfs_offset - BRNIMAGE_MAX_OVERHEAD)) - return -EINVAL; - - /* - * The footer must be untouched as it contains the checksum of the - * original brnImage (kernel + squashfs)! - */ - rootfs_size = master->size - rootfs_offset - BRNIMAGE_FOOTER_SIZE; - - parts = kzalloc(BRNIMAGE_NR_PARTS * sizeof(*parts), GFP_KERNEL); - if (!parts) - return -ENOMEM; - - parts[0].name = KERNEL_PART_NAME; - parts[0].offset = 0; - parts[0].size = kernel_size; - - parts[1].name = ROOTFS_PART_NAME; - parts[1].offset = rootfs_offset; - parts[1].size = rootfs_size; - - *pparts = parts; - return BRNIMAGE_NR_PARTS; -} - -static struct mtd_part_parser mtdsplit_brnimage_parser = { - .owner = THIS_MODULE, - .name = "brnimage-fw", - .parse_fn = mtdsplit_parse_brnimage, - .type = MTD_PARSER_TYPE_FIRMWARE, -}; - -static int __init mtdsplit_brnimage_init(void) -{ - register_mtd_parser(&mtdsplit_brnimage_parser); - - return 0; -} - -subsys_initcall(mtdsplit_brnimage_init); diff --git a/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/mtdsplit_cfe_bootfs.c b/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/mtdsplit_cfe_bootfs.c deleted file mode 100644 index a3474c9dc27403..00000000000000 --- a/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/mtdsplit_cfe_bootfs.c +++ /dev/null @@ -1,90 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (C) 2021 Rafał Miłecki - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "mtdsplit.h" - -#define je16_to_cpu(x) ((x).v16) -#define je32_to_cpu(x) ((x).v32) - -#define NR_PARTS 2 - -static int mtdsplit_cfe_bootfs_parse(struct mtd_info *mtd, - const struct mtd_partition **pparts, - struct mtd_part_parser_data *data) -{ - struct jffs2_raw_dirent node; - enum mtdsplit_part_type type; - struct mtd_partition *parts; - size_t rootfs_offset; - size_t retlen; - size_t offset; - int err; - - /* Don't parse backup partitions */ - if (strcmp(mtd->name, "firmware")) - return -EINVAL; - - /* Find the end of JFFS2 bootfs partition */ - offset = 0; - do { - err = mtd_read(mtd, offset, sizeof(node), &retlen, (void *)&node); - if (err || retlen != sizeof(node)) - break; - - if (je16_to_cpu(node.magic) != JFFS2_MAGIC_BITMASK) - break; - - offset += je32_to_cpu(node.totlen); - offset = (offset + 0x3) & ~0x3; - } while (offset < mtd->size); - - /* Find rootfs partition that follows the bootfs */ - err = mtd_find_rootfs_from(mtd, mtd->erasesize, mtd->size, &rootfs_offset, &type); - if (err) - return err; - - parts = kzalloc(NR_PARTS * sizeof(*parts), GFP_KERNEL); - if (!parts) - return -ENOMEM; - - parts[0].name = "bootfs"; - parts[0].offset = 0; - parts[0].size = rootfs_offset; - - if (type == MTDSPLIT_PART_TYPE_UBI) - parts[1].name = UBI_PART_NAME; - else - parts[1].name = ROOTFS_PART_NAME; - parts[1].offset = rootfs_offset; - parts[1].size = mtd->size - rootfs_offset; - - *pparts = parts; - - return NR_PARTS; -} - -static const struct of_device_id mtdsplit_cfe_bootfs_of_match_table[] = { - { .compatible = "brcm,bcm4908-firmware" }, - {}, -}; -MODULE_DEVICE_TABLE(of, mtdsplit_cfe_bootfs_of_match_table); - -static struct mtd_part_parser mtdsplit_cfe_bootfs_parser = { - .owner = THIS_MODULE, - .name = "cfe-bootfs", - .of_match_table = mtdsplit_cfe_bootfs_of_match_table, - .parse_fn = mtdsplit_cfe_bootfs_parse, -}; - -module_mtd_part_parser(mtdsplit_cfe_bootfs_parser); diff --git a/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/mtdsplit_elf.c b/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/mtdsplit_elf.c deleted file mode 100644 index 47818416f61c1a..00000000000000 --- a/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/mtdsplit_elf.c +++ /dev/null @@ -1,287 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * MTD splitter for ELF loader firmware partitions - * - * Copyright (C) 2020 Sander Vanheule - * - * 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. - * - * To parse the ELF kernel loader, a small ELF parser is used that can - * handle both ELF32 or ELF64 class loaders. The splitter assumes that the - * kernel is always located before the rootfs, whether it is embedded in the - * loader or not. - * - * The kernel image is preferably embedded inside the ELF loader, so the end - * of the loader equals the end of the kernel partition. This is due to the - * way mtd_find_rootfs_from searches for the the rootfs: - * - if the kernel image is embedded in the loader, the appended rootfs may - * follow the loader immediately, within the same erase block. - * - if the kernel image is not embedded in the loader, but placed at some - * offset behind the loader (OKLI-style loader), the rootfs must be - * aligned to an erase-block after the loader and kernel image. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "mtdsplit.h" - -#define ELF_NR_PARTS 2 - -#define ELF_MAGIC 0x7f454c46 /* 0x7f E L F */ -#define ELF_CLASS_32 1 -#define ELF_CLASS_64 2 - -struct elf_header_ident { - uint32_t magic; - uint8_t class; - uint8_t data; - uint8_t version; - uint8_t osabi; - uint8_t abiversion; - uint8_t pad[7]; -}; - -struct elf_header_32 { - uint16_t type; - uint16_t machine; - uint32_t version; - uint32_t entry; - uint32_t phoff; - uint32_t shoff; - uint32_t flags; - uint16_t ehsize; - uint16_t phentsize; - uint16_t phnum; - uint16_t shentsize; - uint16_t shnum; - uint16_t shstrndx; -}; - -struct elf_header_64 { - uint16_t type; - uint16_t machine; - uint32_t version; - uint64_t entry; - uint64_t phoff; - uint64_t shoff; - uint32_t flags; - uint16_t ehsize; - uint16_t phentsize; - uint16_t phnum; - uint16_t shentsize; - uint16_t shnum; - uint16_t shstrndx; -}; - -struct elf_header { - struct elf_header_ident ident; - union { - struct elf_header_32 elf32; - struct elf_header_64 elf64; - }; -}; - -struct elf_program_header_32 { - uint32_t type; - uint32_t offset; - uint32_t vaddr; - uint32_t paddr; - uint32_t filesize; - uint32_t memsize; - uint32_t flags; -}; - -struct elf_program_header_64 { - uint32_t type; - uint32_t flags; - uint64_t offset; - uint64_t vaddr; - uint64_t paddr; - uint64_t filesize; - uint64_t memsize; -}; - - -static int mtdsplit_elf_read_mtd(struct mtd_info *mtd, size_t offset, - uint8_t *dst, size_t len) -{ - size_t retlen; - int ret; - - ret = mtd_read(mtd, offset, len, &retlen, dst); - if (ret) { - pr_debug("read error in \"%s\"\n", mtd->name); - return ret; - } - - if (retlen != len) { - pr_debug("short read in \"%s\"\n", mtd->name); - return -EIO; - } - - return 0; -} - -static int elf32_determine_size(struct mtd_info *mtd, struct elf_header *hdr, - size_t *size) -{ - struct elf_header_32 *hdr32 = &(hdr->elf32); - int err; - size_t section_end, ph_table_end, ph_entry; - struct elf_program_header_32 ph; - - *size = 0; - - if (hdr32->shoff > 0) { - *size = hdr32->shoff + hdr32->shentsize * hdr32->shnum; - return 0; - } - - ph_entry = hdr32->phoff; - ph_table_end = hdr32->phoff + hdr32->phentsize * hdr32->phnum; - - while (ph_entry < ph_table_end) { - err = mtdsplit_elf_read_mtd(mtd, ph_entry, (uint8_t *)(&ph), - sizeof(ph)); - if (err) - return err; - - section_end = ph.offset + ph.filesize; - if (section_end > *size) - *size = section_end; - - ph_entry += hdr32->phentsize; - } - - return 0; -} - -static int elf64_determine_size(struct mtd_info *mtd, struct elf_header *hdr, - size_t *size) -{ - struct elf_header_64 *hdr64 = &(hdr->elf64); - int err; - size_t section_end, ph_table_end, ph_entry; - struct elf_program_header_64 ph; - - *size = 0; - - if (hdr64->shoff > 0) { - *size = hdr64->shoff + hdr64->shentsize * hdr64->shnum; - return 0; - } - - ph_entry = hdr64->phoff; - ph_table_end = hdr64->phoff + hdr64->phentsize * hdr64->phnum; - - while (ph_entry < ph_table_end) { - err = mtdsplit_elf_read_mtd(mtd, ph_entry, (uint8_t *)(&ph), - sizeof(ph)); - if (err) - return err; - - section_end = ph.offset + ph.filesize; - if (section_end > *size) - *size = section_end; - - ph_entry += hdr64->phentsize; - } - - return 0; -} - -static int mtdsplit_parse_elf(struct mtd_info *mtd, - const struct mtd_partition **pparts, - struct mtd_part_parser_data *data) -{ - struct elf_header hdr; - size_t loader_size, rootfs_offset; - enum mtdsplit_part_type type; - struct mtd_partition *parts; - int err; - - err = mtdsplit_elf_read_mtd(mtd, 0, (uint8_t *)&hdr, sizeof(hdr)); - if (err) - return err; - - if (be32_to_cpu(hdr.ident.magic) != ELF_MAGIC) { - pr_debug("invalid ELF magic %08x\n", - be32_to_cpu(hdr.ident.magic)); - return -EINVAL; - } - - switch (hdr.ident.class) { - case ELF_CLASS_32: - err = elf32_determine_size(mtd, &hdr, &loader_size); - break; - case ELF_CLASS_64: - err = elf64_determine_size(mtd, &hdr, &loader_size); - break; - default: - pr_debug("invalid ELF class %i\n", hdr.ident.class); - err = -EINVAL; - } - - if (err) - return err; - - err = mtd_find_rootfs_from(mtd, loader_size, mtd->size, - &rootfs_offset, &type); - if (err) - return err; - - if (rootfs_offset == mtd->size) { - pr_debug("no rootfs found in \"%s\"\n", mtd->name); - return -ENODEV; - } - - parts = kzalloc(ELF_NR_PARTS * sizeof(*parts), GFP_KERNEL); - if (!parts) - return -ENOMEM; - - parts[0].name = KERNEL_PART_NAME; - parts[0].offset = 0; - parts[0].size = rootfs_offset; - - if (type == MTDSPLIT_PART_TYPE_UBI) - parts[1].name = UBI_PART_NAME; - else - parts[1].name = ROOTFS_PART_NAME; - parts[1].offset = rootfs_offset; - parts[1].size = mtd->size - rootfs_offset; - - *pparts = parts; - return ELF_NR_PARTS; -} - -static const struct of_device_id mtdsplit_elf_of_match_table[] = { - { .compatible = "openwrt,elf" }, - {}, -}; -MODULE_DEVICE_TABLE(of, mtdsplit_elf_of_match_table); - -static struct mtd_part_parser mtdsplit_elf_parser = { - .owner = THIS_MODULE, - .name = "elf-loader-fw", - .of_match_table = mtdsplit_elf_of_match_table, - .parse_fn = mtdsplit_parse_elf, - .type = MTD_PARSER_TYPE_FIRMWARE, -}; - -static int __init mtdsplit_elf_init(void) -{ - register_mtd_parser(&mtdsplit_elf_parser); - - return 0; -} - -subsys_initcall(mtdsplit_elf_init); diff --git a/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/mtdsplit_eva.c b/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/mtdsplit_eva.c deleted file mode 100644 index 55004a6d36d7c3..00000000000000 --- a/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/mtdsplit_eva.c +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright (C) 2012 John Crispin - * Copyright (C) 2015 Martin Blumenstingl - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published - * by the Free Software Foundation. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "mtdsplit.h" - -#define EVA_NR_PARTS 2 -#define EVA_MAGIC 0xfeed1281 -#define EVA_FOOTER_SIZE 0x18 -#define EVA_DUMMY_SQUASHFS_SIZE 0x100 - -struct eva_image_header { - uint32_t magic; - uint32_t size; -}; - -static int mtdsplit_parse_eva(struct mtd_info *master, - const struct mtd_partition **pparts, - struct mtd_part_parser_data *data) -{ - struct mtd_partition *parts; - struct eva_image_header hdr; - size_t retlen; - unsigned long kernel_size, rootfs_offset; - int err; - - err = mtd_read(master, 0, sizeof(hdr), &retlen, (void *) &hdr); - if (err) - return err; - - if (retlen != sizeof(hdr)) - return -EIO; - - if (le32_to_cpu(hdr.magic) != EVA_MAGIC) - return -EINVAL; - - kernel_size = le32_to_cpu(hdr.size) + EVA_FOOTER_SIZE; - - /* rootfs starts at the next 0x10000 boundary: */ - rootfs_offset = round_up(kernel_size, 0x10000); - - /* skip the dummy EVA squashfs partition (with wrong endianness): */ - rootfs_offset += EVA_DUMMY_SQUASHFS_SIZE; - - if (rootfs_offset >= master->size) - return -EINVAL; - - err = mtd_check_rootfs_magic(master, rootfs_offset, NULL); - if (err) - return err; - - parts = kzalloc(EVA_NR_PARTS * sizeof(*parts), GFP_KERNEL); - if (!parts) - return -ENOMEM; - - parts[0].name = KERNEL_PART_NAME; - parts[0].offset = 0; - parts[0].size = kernel_size; - - parts[1].name = ROOTFS_PART_NAME; - parts[1].offset = rootfs_offset; - parts[1].size = master->size - rootfs_offset; - - *pparts = parts; - return EVA_NR_PARTS; -} - -static const struct of_device_id mtdsplit_eva_of_match_table[] = { - { .compatible = "avm,eva-firmware" }, - {}, -}; - -static struct mtd_part_parser mtdsplit_eva_parser = { - .owner = THIS_MODULE, - .name = "eva-fw", - .of_match_table = mtdsplit_eva_of_match_table, - .parse_fn = mtdsplit_parse_eva, - .type = MTD_PARSER_TYPE_FIRMWARE, -}; - -static int __init mtdsplit_eva_init(void) -{ - register_mtd_parser(&mtdsplit_eva_parser); - - return 0; -} - -subsys_initcall(mtdsplit_eva_init); diff --git a/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/mtdsplit_fit.c b/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/mtdsplit_fit.c deleted file mode 100644 index a271a676e10e10..00000000000000 --- a/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/mtdsplit_fit.c +++ /dev/null @@ -1,365 +0,0 @@ -/* - * Copyright (c) 2015 The Linux Foundation - * Copyright (C) 2014 Gabor Juhos - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "mtdsplit.h" - -// string macros from git://git.denx.de/u-boot.git/include/image.h - -#define FIT_IMAGES_PATH "/images" -#define FIT_DATA_PROP "data" -#define FIT_DATA_POSITION_PROP "data-position" -#define FIT_DATA_OFFSET_PROP "data-offset" -#define FIT_DATA_SIZE_PROP "data-size" - -// functions from git://git.denx.de/u-boot.git/common/image-fit.c - -/** - * fit_image_get_data - get data property and its size for a given component image node - * @fit: pointer to the FIT format image header - * @noffset: component image node offset - * @data: double pointer to void, will hold data property's data address - * @size: pointer to size_t, will hold data property's data size - * - * fit_image_get_data() finds data property in a given component image node. - * If the property is found its data start address and size are returned to - * the caller. - * - * returns: - * 0, on success - * -1, on failure - */ -static int fit_image_get_data(const void *fit, int noffset, - const void **data, size_t *size) -{ - int len; - - *data = fdt_getprop(fit, noffset, FIT_DATA_PROP, &len); - if (*data == NULL) { - *size = 0; - return -1; - } - - *size = len; - return 0; -} - - -/** - * Get 'data-offset' property from a given image node. - * - * @fit: pointer to the FIT image header - * @noffset: component image node offset - * @data_offset: holds the data-offset property - * - * returns: - * 0, on success - * -ENOENT if the property could not be found - */ -static int fit_image_get_data_offset(const void *fit, int noffset, int *data_offset) -{ - const fdt32_t *val; - - val = fdt_getprop(fit, noffset, FIT_DATA_OFFSET_PROP, NULL); - if (!val) - return -ENOENT; - - *data_offset = fdt32_to_cpu(*val); - - return 0; -} - -/** - * Get 'data-position' property from a given image node. - * - * @fit: pointer to the FIT image header - * @noffset: component image node offset - * @data_position: holds the data-position property - * - * returns: - * 0, on success - * -ENOENT if the property could not be found - */ -static int fit_image_get_data_position(const void *fit, int noffset, - int *data_position) -{ - const fdt32_t *val; - - val = fdt_getprop(fit, noffset, FIT_DATA_POSITION_PROP, NULL); - if (!val) - return -ENOENT; - - *data_position = fdt32_to_cpu(*val); - - return 0; -} - -/** - * Get 'data-size' property from a given image node. - * - * @fit: pointer to the FIT image header - * @noffset: component image node offset - * @data_size: holds the data-size property - * - * returns: - * 0, on success - * -ENOENT if the property could not be found - */ -static int fit_image_get_data_size(const void *fit, int noffset, int *data_size) -{ - const fdt32_t *val; - - val = fdt_getprop(fit, noffset, FIT_DATA_SIZE_PROP, NULL); - if (!val) - return -ENOENT; - - *data_size = fdt32_to_cpu(*val); - - return 0; -} - -/** - * fit_image_get_data_and_size - get data and its size including - * both embedded and external data - * @fit: pointer to the FIT format image header - * @noffset: component image node offset - * @data: double pointer to void, will hold data property's data address - * @size: pointer to size_t, will hold data property's data size - * - * fit_image_get_data_and_size() finds data and its size including - * both embedded and external data. If the property is found - * its data start address and size are returned to the caller. - * - * returns: - * 0, on success - * otherwise, on failure - */ -static int fit_image_get_data_and_size(const void *fit, int noffset, - const void **data, size_t *size) -{ - bool external_data = false; - int offset; - int len; - int ret; - - if (!fit_image_get_data_position(fit, noffset, &offset)) { - external_data = true; - } else if (!fit_image_get_data_offset(fit, noffset, &offset)) { - external_data = true; - /* - * For FIT with external data, figure out where - * the external images start. This is the base - * for the data-offset properties in each image. - */ - offset += ((fdt_totalsize(fit) + 3) & ~3); - } - - if (external_data) { - ret = fit_image_get_data_size(fit, noffset, &len); - if (!ret) { - *data = fit + offset; - *size = len; - } - } else { - ret = fit_image_get_data(fit, noffset, data, size); - } - - return ret; -} - -static int -mtdsplit_fit_parse(struct mtd_info *mtd, - const struct mtd_partition **pparts, - struct mtd_part_parser_data *data) -{ - struct device_node *np = mtd_get_of_node(mtd); - const char *cmdline_match = NULL; - struct fdt_header hdr; - size_t hdr_len, retlen; - size_t offset; - u32 offset_start = 0; - size_t fit_offset, fit_size; - size_t rootfs_offset, rootfs_size; - size_t data_size, img_total, max_size = 0; - struct mtd_partition *parts; - int ret, ndepth, noffset, images_noffset; - const void *img_data; - void *fit; - - of_property_read_string(np, "openwrt,cmdline-match", &cmdline_match); - if (cmdline_match && !strstr(saved_command_line, cmdline_match)) - return -ENODEV; - - of_property_read_u32(np, "openwrt,fit-offset", &offset_start); - - hdr_len = sizeof(struct fdt_header); - - /* Parse the MTD device & search for the FIT image location */ - for(offset = 0; offset + hdr_len <= mtd->size; offset += mtd->erasesize) { - ret = mtd_read(mtd, offset + offset_start, hdr_len, &retlen, (void*) &hdr); - if (ret) { - pr_err("read error in \"%s\" at offset 0x%llx\n", - mtd->name, (unsigned long long) offset); - return ret; - } - - if (retlen != hdr_len) { - pr_err("short read in \"%s\"\n", mtd->name); - return -EIO; - } - - /* Check the magic - see if this is a FIT image */ - if (be32_to_cpu(hdr.magic) != OF_DT_HEADER) { - pr_debug("no valid FIT image found in \"%s\" at offset %llx\n", - mtd->name, (unsigned long long) offset); - continue; - } - - /* We found a FIT image. Let's keep going */ - break; - } - - fit_offset = offset; - fit_size = be32_to_cpu(hdr.totalsize); - - if (fit_size == 0) { - pr_err("FIT image in \"%s\" at offset %llx has null size\n", - mtd->name, (unsigned long long) fit_offset); - return -ENODEV; - } - - /* - * Classic uImage.FIT has all data embedded into the FDT - * data structure. Hence the total size of the image equals - * the total size of the FDT structure. - * Modern uImage.FIT may have only references to data in FDT, - * hence we need to parse FDT structure to find the end of the - * last external data refernced. - */ - if (fit_size > 0x1000) { - enum mtdsplit_part_type type; - - /* Search for the rootfs partition after the FIT image */ - ret = mtd_find_rootfs_from(mtd, fit_offset + fit_size + offset_start, mtd->size, - &rootfs_offset, &type); - if (ret) { - pr_info("no rootfs found after FIT image in \"%s\"\n", - mtd->name); - return ret; - } - - rootfs_size = mtd->size - rootfs_offset; - - parts = kzalloc(2 * sizeof(*parts), GFP_KERNEL); - if (!parts) - return -ENOMEM; - - parts[0].name = KERNEL_PART_NAME; - parts[0].offset = fit_offset; - parts[0].size = mtd_roundup_to_eb(fit_size + offset_start, mtd); - - if (type == MTDSPLIT_PART_TYPE_UBI) - parts[1].name = UBI_PART_NAME; - else - parts[1].name = ROOTFS_PART_NAME; - parts[1].offset = rootfs_offset; - parts[1].size = rootfs_size; - - *pparts = parts; - - return 2; - } else { - /* Search for rootfs_data after FIT external data */ - fit = kzalloc(fit_size, GFP_KERNEL); - ret = mtd_read(mtd, offset, fit_size + offset_start, &retlen, fit); - if (ret) { - pr_err("read error in \"%s\" at offset 0x%llx\n", - mtd->name, (unsigned long long) offset); - return ret; - } - - images_noffset = fdt_path_offset(fit, FIT_IMAGES_PATH); - if (images_noffset < 0) { - pr_err("Can't find images parent node '%s' (%s)\n", - FIT_IMAGES_PATH, fdt_strerror(images_noffset)); - return -ENODEV; - } - - for (ndepth = 0, - noffset = fdt_next_node(fit, images_noffset, &ndepth); - (noffset >= 0) && (ndepth > 0); - noffset = fdt_next_node(fit, noffset, &ndepth)) { - if (ndepth == 1) { - ret = fit_image_get_data_and_size(fit, noffset, &img_data, &data_size); - if (ret) - return 0; - - img_total = data_size + (img_data - fit); - - max_size = (max_size > img_total) ? max_size : img_total; - } - } - - parts = kzalloc(sizeof(*parts), GFP_KERNEL); - if (!parts) - return -ENOMEM; - - parts[0].name = ROOTFS_SPLIT_NAME; - parts[0].offset = fit_offset + mtd_roundup_to_eb(max_size, mtd); - parts[0].size = mtd->size - parts[0].offset; - - *pparts = parts; - - kfree(fit); - - return 1; - } -} - -static const struct of_device_id mtdsplit_fit_of_match_table[] = { - { .compatible = "denx,fit" }, - {}, -}; - -static struct mtd_part_parser uimage_parser = { - .owner = THIS_MODULE, - .name = "fit-fw", - .of_match_table = mtdsplit_fit_of_match_table, - .parse_fn = mtdsplit_fit_parse, - .type = MTD_PARSER_TYPE_FIRMWARE, -}; - -/************************************************** - * Init - **************************************************/ - -static int __init mtdsplit_fit_init(void) -{ - register_mtd_parser(&uimage_parser); - - return 0; -} - -module_init(mtdsplit_fit_init); diff --git a/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/mtdsplit_h3c_vfs.c b/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/mtdsplit_h3c_vfs.c deleted file mode 100644 index f264233dbd9de3..00000000000000 --- a/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/mtdsplit_h3c_vfs.c +++ /dev/null @@ -1,170 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Some devices made by H3C use a "VFS" filesystem to store firmware images. - * This parses the start of the filesystem to read the length of the first - * file (the kernel image). It then searches for the rootfs after the end of - * the file data. This driver assumes that the filesystem was generated by - * mkh3cvfs, and only works if the filesystem matches the expected layout, - * which includes the file name of the kernel image. - */ - -#include -#include -#include -#include -#include -#include -#include - -#include "mtdsplit.h" - -#define VFS_ERASEBLOCK_SIZE 0x10000 -#define VFS_BLOCK_SIZE 0x400 -#define VFS_BLOCKS_PER_ERASEBLOCK (VFS_ERASEBLOCK_SIZE / VFS_BLOCK_SIZE) - -#define FORMAT_FLAG_OFFSET 0x0 - -#define FORMAT_FLAG (VFS_ERASEBLOCK_SIZE << 12 | VFS_BLOCK_SIZE) - -#define FILE_ENTRY_OFFSET 0x800 - -#define FILE_ENTRY_FLAGS 0x3f -#define FILE_ENTRY_PARENT_BLOCK 0 -#define FILE_ENTRY_PARENT_INDEX 0 -#define FILE_ENTRY_DATA_BLOCK 2 -#define FILE_ENTRY_NAME "openwrt-kernel.bin" - -#define NR_PARTS 2 - -struct file_entry { - uint8_t flags; - - uint8_t res0[5]; - - uint16_t year; - uint8_t month; - uint8_t day; - uint8_t hour; - uint8_t minute; - uint8_t second; - - uint8_t res1[3]; - - uint32_t length; - - uint32_t parent_block; - uint16_t parent_index; - - uint8_t res2[2]; - - uint32_t data_block; - - char name[96]; -} __attribute__ ((packed)); - -static inline size_t block_offset(int block) -{ - return VFS_ERASEBLOCK_SIZE * (block / (VFS_BLOCKS_PER_ERASEBLOCK-1)) - + VFS_BLOCK_SIZE * (1 + (block % (VFS_BLOCKS_PER_ERASEBLOCK-1))); -} - -static inline int block_count(size_t size) -{ - return (size + VFS_BLOCK_SIZE - 1) / VFS_BLOCK_SIZE; -} - -static int mtdsplit_h3c_vfs_parse(struct mtd_info *mtd, - const struct mtd_partition **pparts, - struct mtd_part_parser_data *data) -{ - struct mtd_partition *parts; - uint32_t format_flag; - struct file_entry file_entry; - size_t retlen; - int err; - size_t kernel_size; - size_t expected_offset; - size_t rootfs_offset; - - if (mtd->erasesize != VFS_ERASEBLOCK_SIZE) - return -EINVAL; - - /* Check format flag */ - err = mtd_read(mtd, FORMAT_FLAG_OFFSET, sizeof(format_flag), &retlen, - (void *) &format_flag); - if (err) - return err; - - if (retlen != sizeof(format_flag)) - return -EIO; - - if (format_flag != FORMAT_FLAG) - return -EINVAL; - - /* Check file entry */ - err = mtd_read(mtd, FILE_ENTRY_OFFSET, sizeof(file_entry), &retlen, - (void *) &file_entry); - if (err) - return err; - - if (retlen != sizeof(file_entry)) - return -EIO; - - if (file_entry.flags != FILE_ENTRY_FLAGS) - return -EINVAL; - - if (file_entry.parent_block != FILE_ENTRY_PARENT_BLOCK) - return -EINVAL; - - if (file_entry.parent_index != FILE_ENTRY_PARENT_INDEX) - return -EINVAL; - - if (file_entry.data_block != FILE_ENTRY_DATA_BLOCK) - return -EINVAL; - - if (strncmp(file_entry.name, FILE_ENTRY_NAME, sizeof(file_entry.name)) != 0) - return -EINVAL; - - /* Find rootfs offset */ - kernel_size = block_offset(file_entry.data_block + - block_count(file_entry.length) - 1) + - VFS_BLOCK_SIZE; - - expected_offset = mtd_roundup_to_eb(kernel_size, mtd); - - err = mtd_find_rootfs_from(mtd, expected_offset, mtd->size, - &rootfs_offset, NULL); - if (err) - return err; - - parts = kzalloc(NR_PARTS * sizeof(*parts), GFP_KERNEL); - if (!parts) - return -ENOMEM; - - parts[0].name = KERNEL_PART_NAME; - parts[0].offset = 0; - parts[0].size = rootfs_offset; - - parts[1].name = ROOTFS_PART_NAME; - parts[1].offset = rootfs_offset; - parts[1].size = mtd->size - rootfs_offset; - - *pparts = parts; - return NR_PARTS; -} - -static const struct of_device_id mtdsplit_h3c_vfs_of_match_table[] = { - { .compatible = "h3c,vfs-firmware" }, - {}, -}; -MODULE_DEVICE_TABLE(of, mtdsplit_h3c_vfs_of_match_table); - -static struct mtd_part_parser mtdsplit_h3c_vfs_parser = { - .owner = THIS_MODULE, - .name = "h3c-vfs", - .of_match_table = mtdsplit_h3c_vfs_of_match_table, - .parse_fn = mtdsplit_h3c_vfs_parse, - .type = MTD_PARSER_TYPE_FIRMWARE, -}; - -module_mtd_part_parser(mtdsplit_h3c_vfs_parser); diff --git a/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/mtdsplit_jimage.c b/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/mtdsplit_jimage.c deleted file mode 100644 index 1770dd47ce15f3..00000000000000 --- a/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/mtdsplit_jimage.c +++ /dev/null @@ -1,284 +0,0 @@ -/* - * Copyright (C) 2018 Paweł Dembicki - * - * Based on: mtdsplit_uimage.c - * Copyright (C) 2013 Gabor Juhos - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published - * by the Free Software Foundation. - * - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "mtdsplit.h" - -#define MAX_HEADER_LEN ( STAG_SIZE + SCH2_SIZE ) - -#define STAG_SIZE 16 -#define STAG_ID 0x04 -#define STAG_MAGIC 0x2B24 - -#define SCH2_SIZE 40 -#define SCH2_MAGIC 0x2124 -#define SCH2_VER 0x02 - -/* - * Jboot image header, - * all data in little endian. - */ - -struct jimage_header //stag + sch2 jboot joined headers -{ - uint8_t stag_cmark; // in factory 0xFF , in sysupgrade must be the same as stag_id - uint8_t stag_id; // 0x04 - uint16_t stag_magic; //magic 0x2B24 - uint32_t stag_time_stamp; // timestamp calculated in jboot way - uint32_t stag_image_length; // lentgh of kernel + sch2 header - uint16_t stag_image_checksum; // negated jboot_checksum of sch2 + kernel - uint16_t stag_tag_checksum; // negated jboot_checksum of stag header data - uint16_t sch2_magic; // magic 0x2124 - uint8_t sch2_cp_type; // 0x00 for flat, 0x01 for jz, 0x02 for gzip, 0x03 for lzma - uint8_t sch2_version; // 0x02 for sch2 - uint32_t sch2_ram_addr; // ram entry address - uint32_t sch2_image_len; // kernel image length - uint32_t sch2_image_crc32; // kernel image crc - uint32_t sch2_start_addr; // ram start address - uint32_t sch2_rootfs_addr; // rootfs flash address - uint32_t sch2_rootfs_len; // rootfls length - uint32_t sch2_rootfs_crc32; // rootfs crc32 - uint32_t sch2_header_crc32; // sch2 header crc32, durring calculation this area is replaced by zero - uint16_t sch2_header_length; // sch2 header length: 0x28 - uint16_t sch2_cmd_line_length; // cmd line length, known zeros -}; - -static int -read_jimage_header(struct mtd_info *mtd, size_t offset, u_char *buf, - size_t header_len) -{ - size_t retlen; - int ret; - - ret = mtd_read(mtd, offset, header_len, &retlen, buf); - if (ret) { - pr_debug("read error in \"%s\"\n", mtd->name); - return ret; - } - - if (retlen != header_len) { - pr_debug("short read in \"%s\"\n", mtd->name); - return -EIO; - } - - return 0; -} - -/** - * __mtdsplit_parse_jimage - scan partition and create kernel + rootfs parts - * - * @find_header: function to call for a block of data that will return offset - * of a valid jImage header if found - */ -static int __mtdsplit_parse_jimage(struct mtd_info *master, - const struct mtd_partition **pparts, - struct mtd_part_parser_data *data, - ssize_t (*find_header)(u_char *buf, size_t len)) -{ - struct mtd_partition *parts; - u_char *buf; - int nr_parts; - size_t offset; - size_t jimage_offset; - size_t jimage_size = 0; - size_t rootfs_offset; - size_t rootfs_size = 0; - int jimage_part, rf_part; - int ret; - enum mtdsplit_part_type type; - - nr_parts = 2; - parts = kzalloc(nr_parts * sizeof(*parts), GFP_KERNEL); - if (!parts) - return -ENOMEM; - - buf = vmalloc(MAX_HEADER_LEN); - if (!buf) { - ret = -ENOMEM; - goto err_free_parts; - } - - /* find jImage on erase block boundaries */ - for (offset = 0; offset < master->size; offset += master->erasesize) { - struct jimage_header *header; - - jimage_size = 0; - - ret = read_jimage_header(master, offset, buf, MAX_HEADER_LEN); - if (ret) - continue; - - ret = find_header(buf, MAX_HEADER_LEN); - if (ret < 0) { - pr_debug("no valid jImage found in \"%s\" at offset %llx\n", - master->name, (unsigned long long) offset); - continue; - } - header = (struct jimage_header *)(buf + ret); - - jimage_size = sizeof(*header) + header->sch2_image_len + ret; - if ((offset + jimage_size) > master->size) { - pr_debug("jImage exceeds MTD device \"%s\"\n", - master->name); - continue; - } - break; - } - - if (jimage_size == 0) { - pr_debug("no jImage found in \"%s\"\n", master->name); - ret = -ENODEV; - goto err_free_buf; - } - - jimage_offset = offset; - - if (jimage_offset == 0) { - jimage_part = 0; - rf_part = 1; - - /* find the roots after the jImage */ - ret = mtd_find_rootfs_from(master, jimage_offset + jimage_size, - master->size, &rootfs_offset, &type); - if (ret) { - pr_debug("no rootfs after jImage in \"%s\"\n", - master->name); - goto err_free_buf; - } - - rootfs_size = master->size - rootfs_offset; - jimage_size = rootfs_offset - jimage_offset; - } else { - rf_part = 0; - jimage_part = 1; - - /* check rootfs presence at offset 0 */ - ret = mtd_check_rootfs_magic(master, 0, &type); - if (ret) { - pr_debug("no rootfs before jImage in \"%s\"\n", - master->name); - goto err_free_buf; - } - - rootfs_offset = 0; - rootfs_size = jimage_offset; - } - - if (rootfs_size == 0) { - pr_debug("no rootfs found in \"%s\"\n", master->name); - ret = -ENODEV; - goto err_free_buf; - } - - parts[jimage_part].name = KERNEL_PART_NAME; - parts[jimage_part].offset = jimage_offset; - parts[jimage_part].size = jimage_size; - - if (type == MTDSPLIT_PART_TYPE_UBI) - parts[rf_part].name = UBI_PART_NAME; - else - parts[rf_part].name = ROOTFS_PART_NAME; - parts[rf_part].offset = rootfs_offset; - parts[rf_part].size = rootfs_size; - - vfree(buf); - - *pparts = parts; - return nr_parts; - -err_free_buf: - vfree(buf); - -err_free_parts: - kfree(parts); - return ret; -} - -static ssize_t jimage_verify_default(u_char *buf, size_t len) -{ - struct jimage_header *header = (struct jimage_header *)buf; - - /* default sanity checks */ - if (header->stag_magic != STAG_MAGIC) { - pr_debug("invalid jImage stag header magic: %04x\n", - header->stag_magic); - return -EINVAL; - } - if (header->sch2_magic != SCH2_MAGIC) { - pr_debug("invalid jImage sch2 header magic: %04x\n", - header->stag_magic); - return -EINVAL; - } - if (header->stag_cmark != header->stag_id) { - pr_debug("invalid jImage stag header cmark: %02x\n", - header->stag_magic); - return -EINVAL; - } - if (header->stag_id != STAG_ID) { - pr_debug("invalid jImage stag header id: %02x\n", - header->stag_magic); - return -EINVAL; - } - if (header->sch2_version != SCH2_VER) { - pr_debug("invalid jImage sch2 header version: %02x\n", - header->stag_magic); - return -EINVAL; - } - - return 0; -} - -static int -mtdsplit_jimage_parse_generic(struct mtd_info *master, - const struct mtd_partition **pparts, - struct mtd_part_parser_data *data) -{ - return __mtdsplit_parse_jimage(master, pparts, data, - jimage_verify_default); -} - -static const struct of_device_id mtdsplit_jimage_of_match_table[] = { - { .compatible = "amit,jimage" }, - {}, -}; - -static struct mtd_part_parser jimage_generic_parser = { - .owner = THIS_MODULE, - .name = "jimage-fw", - .of_match_table = mtdsplit_jimage_of_match_table, - .parse_fn = mtdsplit_jimage_parse_generic, - .type = MTD_PARSER_TYPE_FIRMWARE, -}; - -/************************************************** - * Init - **************************************************/ - -static int __init mtdsplit_jimage_init(void) -{ - register_mtd_parser(&jimage_generic_parser); - - return 0; -} - -module_init(mtdsplit_jimage_init); diff --git a/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/mtdsplit_lzma.c b/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/mtdsplit_lzma.c deleted file mode 100644 index c58f7ae4bf066b..00000000000000 --- a/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/mtdsplit_lzma.c +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright (C) 2014 Gabor Juhos - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published - * by the Free Software Foundation. - * - */ - -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "mtdsplit.h" - -#define LZMA_NR_PARTS 2 -#define LZMA_PROPERTIES_SIZE 5 - -struct lzma_header { - u8 props[LZMA_PROPERTIES_SIZE]; - u8 size_low[4]; - u8 size_high[4]; -}; - -static int mtdsplit_parse_lzma(struct mtd_info *master, - const struct mtd_partition **pparts, - struct mtd_part_parser_data *data) -{ - struct lzma_header hdr; - size_t hdr_len, retlen; - size_t rootfs_offset; - u32 t; - struct mtd_partition *parts; - int err; - - hdr_len = sizeof(hdr); - err = mtd_read(master, 0, hdr_len, &retlen, (void *) &hdr); - if (err) - return err; - - if (retlen != hdr_len) - return -EIO; - - /* verify LZMA properties */ - if (hdr.props[0] >= (9 * 5 * 5)) - return -EINVAL; - - t = get_unaligned_le32(&hdr.props[1]); - if (!is_power_of_2(t)) - return -EINVAL; - - t = get_unaligned_le32(&hdr.size_high); - if (t) - return -EINVAL; - - err = mtd_find_rootfs_from(master, master->erasesize, master->size, - &rootfs_offset, NULL); - if (err) - return err; - - parts = kzalloc(LZMA_NR_PARTS * sizeof(*parts), GFP_KERNEL); - if (!parts) - return -ENOMEM; - - parts[0].name = KERNEL_PART_NAME; - parts[0].offset = 0; - parts[0].size = rootfs_offset; - - parts[1].name = ROOTFS_PART_NAME; - parts[1].offset = rootfs_offset; - parts[1].size = master->size - rootfs_offset; - - *pparts = parts; - return LZMA_NR_PARTS; -} - -static const struct of_device_id mtdsplit_lzma_of_match_table[] = { - { .compatible = "lzma" }, - {}, -}; -MODULE_DEVICE_TABLE(of, mtdsplit_lzma_of_match_table); - -static struct mtd_part_parser mtdsplit_lzma_parser = { - .owner = THIS_MODULE, - .name = "lzma-fw", - .of_match_table = mtdsplit_lzma_of_match_table, - .parse_fn = mtdsplit_parse_lzma, - .type = MTD_PARSER_TYPE_FIRMWARE, -}; - -static int __init mtdsplit_lzma_init(void) -{ - register_mtd_parser(&mtdsplit_lzma_parser); - - return 0; -} - -subsys_initcall(mtdsplit_lzma_init); diff --git a/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/mtdsplit_minor.c b/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/mtdsplit_minor.c deleted file mode 100644 index af6822e11ab344..00000000000000 --- a/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/mtdsplit_minor.c +++ /dev/null @@ -1,125 +0,0 @@ -/* - * MTD splitter for MikroTik NOR devices - * - * Copyright (C) 2017 Thibaut VARENE - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published - * by the Free Software Foundation. - * - * The rootfs is expected at erase-block boundary due to the use of - * mtd_find_rootfs_from(). We use a trimmed down version of the yaffs header - * for two main reasons: - * - the original header uses weakly defined types (int, enum...) which can - * vary in length depending on build host (and the struct is not packed), - * and the name field can have a different total length depending on - * whether or not the yaffs code was _built_ with unicode support. - * - the only field that could be of real use here (file_size_low) contains - * invalid data in the header generated by kernel2minor, so we cannot use - * it to infer the exact position of the rootfs and do away with - * mtd_find_rootfs_from() (and thus have non-EB-aligned rootfs). - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "mtdsplit.h" - -#define YAFFS_OBJECT_TYPE_FILE 0x1 -#define YAFFS_OBJECTID_ROOT 0x1 -#define YAFFS_SUM_UNUSED 0xFFFF -#define YAFFS_NAME "kernel" - -#define MINOR_NR_PARTS 2 - -/* - * This structure is based on yaffs_obj_hdr from yaffs_guts.h - * The weak types match upstream. The fields have cpu-endianness - */ -struct minor_header { - int yaffs_type; - int yaffs_obj_id; - u16 yaffs_sum_unused; - char yaffs_name[sizeof(YAFFS_NAME)]; -}; - -static int mtdsplit_parse_minor(struct mtd_info *master, - const struct mtd_partition **pparts, - struct mtd_part_parser_data *data) -{ - struct minor_header hdr; - size_t hdr_len, retlen; - size_t rootfs_offset; - struct mtd_partition *parts; - int err; - - hdr_len = sizeof(hdr); - err = mtd_read(master, 0, hdr_len, &retlen, (void *) &hdr); - if (err) - return err; - - if (retlen != hdr_len) - return -EIO; - - /* match header */ - if (hdr.yaffs_type != YAFFS_OBJECT_TYPE_FILE) - return -EINVAL; - - if (hdr.yaffs_obj_id != YAFFS_OBJECTID_ROOT) - return -EINVAL; - - if (hdr.yaffs_sum_unused != YAFFS_SUM_UNUSED) - return -EINVAL; - - if (memcmp(hdr.yaffs_name, YAFFS_NAME, sizeof(YAFFS_NAME))) - return -EINVAL; - - err = mtd_find_rootfs_from(master, master->erasesize, master->size, - &rootfs_offset, NULL); - if (err) - return err; - - parts = kzalloc(MINOR_NR_PARTS * sizeof(*parts), GFP_KERNEL); - if (!parts) - return -ENOMEM; - - parts[0].name = KERNEL_PART_NAME; - parts[0].offset = 0; - parts[0].size = rootfs_offset; - - parts[1].name = ROOTFS_PART_NAME; - parts[1].offset = rootfs_offset; - parts[1].size = master->size - rootfs_offset; - - *pparts = parts; - return MINOR_NR_PARTS; -} - -static const struct of_device_id mtdsplit_minor_of_match_table[] = { - { .compatible = "mikrotik,minor" }, - {}, -}; -MODULE_DEVICE_TABLE(of, mtdsplit_minor_of_match_table); - -static struct mtd_part_parser mtdsplit_minor_parser = { - .owner = THIS_MODULE, - .name = "minor-fw", - .of_match_table = mtdsplit_minor_of_match_table, - .parse_fn = mtdsplit_parse_minor, - .type = MTD_PARSER_TYPE_FIRMWARE, -}; - -static int __init mtdsplit_minor_init(void) -{ - register_mtd_parser(&mtdsplit_minor_parser); - - return 0; -} - -subsys_initcall(mtdsplit_minor_init); diff --git a/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/mtdsplit_seama.c b/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/mtdsplit_seama.c deleted file mode 100644 index 5d49171b1f7476..00000000000000 --- a/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/mtdsplit_seama.c +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright (C) 2013 Gabor Juhos - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published - * by the Free Software Foundation. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "mtdsplit.h" - -#define SEAMA_MAGIC 0x5EA3A417 -#define SEAMA_NR_PARTS 2 -#define SEAMA_MIN_ROOTFS_OFFS 0x80000 /* 512KiB */ - -struct seama_header { - __be32 magic; /* should always be SEAMA_MAGIC. */ - __be16 reserved; /* reserved for */ - __be16 metasize; /* size of the META data */ - __be32 size; /* size of the image */ - u8 md5[16]; /* digest */ -}; - -static int mtdsplit_parse_seama(struct mtd_info *master, - const struct mtd_partition **pparts, - struct mtd_part_parser_data *data) -{ - struct seama_header hdr; - size_t hdr_len, retlen, kernel_ent_size; - size_t rootfs_offset; - struct mtd_partition *parts; - enum mtdsplit_part_type type; - int err; - - hdr_len = sizeof(hdr); - err = mtd_read(master, 0, hdr_len, &retlen, (void *) &hdr); - if (err) - return err; - - if (retlen != hdr_len) - return -EIO; - - /* sanity checks */ - if (be32_to_cpu(hdr.magic) != SEAMA_MAGIC) - return -EINVAL; - - kernel_ent_size = hdr_len + be32_to_cpu(hdr.size) + - be16_to_cpu(hdr.metasize); - if (kernel_ent_size > master->size) - return -EINVAL; - - /* Check for the rootfs right after Seama entity with a kernel. */ - err = mtd_check_rootfs_magic(master, kernel_ent_size, &type); - if (!err) { - rootfs_offset = kernel_ent_size; - } else { - /* - * On some devices firmware entity might contain both: kernel - * and rootfs. We can't determine kernel size so we just have to - * look for rootfs magic. - * Start the search from an arbitrary offset. - */ - err = mtd_find_rootfs_from(master, SEAMA_MIN_ROOTFS_OFFS, - master->size, &rootfs_offset, &type); - if (err) - return err; - } - - parts = kzalloc(SEAMA_NR_PARTS * sizeof(*parts), GFP_KERNEL); - if (!parts) - return -ENOMEM; - - parts[0].name = KERNEL_PART_NAME; - parts[0].offset = sizeof hdr + be16_to_cpu(hdr.metasize); - parts[0].size = rootfs_offset - parts[0].offset; - - if (type == MTDSPLIT_PART_TYPE_UBI) - parts[1].name = UBI_PART_NAME; - else - parts[1].name = ROOTFS_PART_NAME; - parts[1].offset = rootfs_offset; - parts[1].size = master->size - rootfs_offset; - - *pparts = parts; - return SEAMA_NR_PARTS; -} - -static const struct of_device_id mtdsplit_seama_of_match_table[] = { - { .compatible = "seama" }, - {}, -}; -MODULE_DEVICE_TABLE(of, mtdsplit_seama_of_match_table); - -static struct mtd_part_parser mtdsplit_seama_parser = { - .owner = THIS_MODULE, - .name = "seama-fw", - .of_match_table = mtdsplit_seama_of_match_table, - .parse_fn = mtdsplit_parse_seama, - .type = MTD_PARSER_TYPE_FIRMWARE, -}; - -static int __init mtdsplit_seama_init(void) -{ - register_mtd_parser(&mtdsplit_seama_parser); - - return 0; -} - -subsys_initcall(mtdsplit_seama_init); diff --git a/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/mtdsplit_seil.c b/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/mtdsplit_seil.c deleted file mode 100644 index e58bb49b23fcb3..00000000000000 --- a/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/mtdsplit_seil.c +++ /dev/null @@ -1,191 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* a mtdsplit driver for IIJ SEIL devices */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "mtdsplit.h" - -#define NR_PARTS 2 -#define SEIL_VFMT 1 -#define LDR_ENV_PART_NAME "bootloader-env" -#define LDR_ENV_KEY_BOOTDEV "BOOTDEV" - -struct seil_header { - uint64_t id; /* Identifier */ - uint8_t copy[80]; /* Copyright */ - uint32_t dcrc; /* Data CRC Checksum */ - uint32_t vfmt; /* Image Version Format */ - uint32_t vmjr; /* Image Version Major */ - uint32_t vmnr; /* Image Version Minor */ - uint8_t vrel[32]; /* Image Version Release */ - uint32_t dxor; /* xor value for Data? */ - uint32_t dlen; /* Data Length */ -}; - -/* - * check whether the current mtd device is active or not - * - * example of BOOTDEV value (IIJ SA-W2): - * - "flash" : primary image on flash - * - "rescue" : secondary image on flash - * - "usb" : usb storage - * - "lan0/1" : network - */ -static bool seil_bootdev_is_active(struct device_node *np) -{ - struct mtd_info *env_mtd; - char *buf, *var, *value, *eq; - const char *devnm; - size_t rdlen; - int ret; - - /* - * read bootdev name of the partition - * if doesn't exist, return true and skip checking of active device - */ - ret = of_property_read_string(np, "iij,bootdev-name", &devnm); - if (ret == -EINVAL) - return true; - else if (ret < 0) - return false; - - env_mtd = get_mtd_device_nm(LDR_ENV_PART_NAME); - if (IS_ERR(env_mtd)) { - pr_err("failed to get mtd device \"%s\"", LDR_ENV_PART_NAME); - return false; - } - - buf = vmalloc(env_mtd->size); - if (!buf) - return false; - - ret = mtd_read(env_mtd, 0, env_mtd->size, &rdlen, buf); - if (ret || rdlen != env_mtd->size) { - pr_err("failed to read from mtd (%d)\n", ret); - ret = 0; - goto exit_vfree; - } - - for (var = buf, ret = false; - var < buf + env_mtd->size && *var; - var = value + strlen(value) + 1) { - eq = strchr(var, '='); - if (!eq) - break; - *eq = '\0'; - value = eq + 1; - - pr_debug("ENV: %s=%s\n", var, value); - if (!strcmp(var, LDR_ENV_KEY_BOOTDEV)) { - ret = !strcmp(devnm, value); - break; - } - } - -exit_vfree: - vfree(buf); - - return ret; -} - -static int mtdsplit_parse_seil_fw(struct mtd_info *master, - const struct mtd_partition **pparts, - struct mtd_part_parser_data *data) -{ - struct device_node *np = mtd_get_of_node(master); - struct mtd_partition *parts; - struct seil_header header; - size_t image_size = 0; - size_t rootfs_offset; - size_t hdrlen = sizeof(header); - size_t retlen; - int ret; - u64 id; - - if (!seil_bootdev_is_active(np)) - return -ENODEV; - - ret = of_property_read_u64(np, "iij,seil-id", &id); - if (ret) { - pr_err("failed to get iij,seil-id from dt\n"); - return ret; - } - pr_debug("got seil-id=0x%016llx from dt\n", id); - - parts = kcalloc(NR_PARTS, sizeof(*parts), GFP_KERNEL); - if (!parts) - return -ENOMEM; - - ret = mtd_read(master, 0, hdrlen, &retlen, (void *)&header); - if (ret) - goto err_free_parts; - - if (retlen != hdrlen) { - ret = -EIO; - goto err_free_parts; - } - - if (be64_to_cpu(header.id) != id || - be32_to_cpu(header.vfmt) != SEIL_VFMT) { - pr_debug("no valid seil image found in \"%s\"\n", master->name); - ret = -ENODEV; - goto err_free_parts; - } - - image_size = hdrlen + be32_to_cpu(header.dlen); - if (image_size > master->size) { - pr_err("seil image exceeds MTD device \"%s\"\n", master->name); - ret = -EINVAL; - goto err_free_parts; - } - - /* find the roots after the seil image */ - ret = mtd_find_rootfs_from(master, image_size, - master->size, &rootfs_offset, NULL); - if (ret || (master->size - rootfs_offset) == 0) { - pr_debug("no rootfs after seil image in \"%s\"\n", - master->name); - ret = -ENODEV; - goto err_free_parts; - } - - parts[0].name = KERNEL_PART_NAME; - parts[0].offset = 0; - parts[0].size = rootfs_offset; - - parts[1].name = ROOTFS_PART_NAME; - parts[1].offset = rootfs_offset; - parts[1].size = master->size - rootfs_offset; - - *pparts = parts; - return NR_PARTS; - -err_free_parts: - kfree(parts); - return ret; -} - -static const struct of_device_id mtdsplit_seil_fw_of_match_table[] = { - { .compatible = "iij,seil-firmware" }, - {}, -}; -MODULE_DEVICE_TABLE(of, mtdsplit_seil_fw_of_match_table); - -static struct mtd_part_parser mtdsplit_seil_fw_parser = { - .owner = THIS_MODULE, - .name = "seil-fw", - .of_match_table = mtdsplit_seil_fw_of_match_table, - .parse_fn = mtdsplit_parse_seil_fw, - .type = MTD_PARSER_TYPE_FIRMWARE, -}; - -module_mtd_part_parser(mtdsplit_seil_fw_parser); diff --git a/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/mtdsplit_squashfs.c b/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/mtdsplit_squashfs.c deleted file mode 100644 index f6353da65b0e44..00000000000000 --- a/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/mtdsplit_squashfs.c +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (C) 2013 Felix Fietkau - * Copyright (C) 2013 Gabor Juhos - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published - * by the Free Software Foundation. - * - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "mtdsplit.h" - -static int -mtdsplit_parse_squashfs(struct mtd_info *master, - const struct mtd_partition **pparts, - struct mtd_part_parser_data *data) -{ - struct mtd_partition *part; - struct mtd_info *parent_mtd; - size_t part_offset; - size_t squashfs_len; - int err; - - err = mtd_get_squashfs_len(master, 0, &squashfs_len); - if (err) - return err; - - parent_mtd = mtd_get_master(master); - part_offset = mtdpart_get_offset(master); - - part = kzalloc(sizeof(*part), GFP_KERNEL); - if (!part) { - pr_alert("unable to allocate memory for \"%s\" partition\n", - ROOTFS_SPLIT_NAME); - return -ENOMEM; - } - - part->name = ROOTFS_SPLIT_NAME; - part->offset = mtd_roundup_to_eb(part_offset + squashfs_len, - parent_mtd) - part_offset; - part->size = mtd_rounddown_to_eb(master->size - part->offset, master); - - *pparts = part; - return 1; -} - -static struct mtd_part_parser mtdsplit_squashfs_parser = { - .owner = THIS_MODULE, - .name = "squashfs-split", - .parse_fn = mtdsplit_parse_squashfs, - .type = MTD_PARSER_TYPE_ROOTFS, -}; - -static int __init mtdsplit_squashfs_init(void) -{ - register_mtd_parser(&mtdsplit_squashfs_parser); - - return 0; -} - -subsys_initcall(mtdsplit_squashfs_init); diff --git a/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/mtdsplit_tplink.c b/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/mtdsplit_tplink.c deleted file mode 100644 index 8909c107a09489..00000000000000 --- a/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/mtdsplit_tplink.c +++ /dev/null @@ -1,176 +0,0 @@ -/* - * Copyright (C) 2013 Gabor Juhos - * Copyright (C) 2014 Felix Fietkau - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published - * by the Free Software Foundation. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "mtdsplit.h" - -#define TPLINK_NR_PARTS 2 -#define TPLINK_MIN_ROOTFS_OFFS 0x80000 /* 512KiB */ - -#define MD5SUM_LEN 16 - -struct fw_v1 { - char vendor_name[24]; - char fw_version[36]; - uint32_t hw_id; /* hardware id */ - uint32_t hw_rev; /* hardware revision */ - uint32_t unk1; - uint8_t md5sum1[MD5SUM_LEN]; - uint32_t unk2; - uint8_t md5sum2[MD5SUM_LEN]; - uint32_t unk3; - uint32_t kernel_la; /* kernel load address */ - uint32_t kernel_ep; /* kernel entry point */ - uint32_t fw_length; /* total length of the firmware */ - uint32_t kernel_ofs; /* kernel data offset */ - uint32_t kernel_len; /* kernel data length */ - uint32_t rootfs_ofs; /* rootfs data offset */ - uint32_t rootfs_len; /* rootfs data length */ - uint32_t boot_ofs; /* bootloader data offset */ - uint32_t boot_len; /* bootloader data length */ - uint8_t pad[360]; -} __attribute__ ((packed)); - -struct fw_v2 { - char fw_version[48]; /* 0x04: fw version string */ - uint32_t hw_id; /* 0x34: hardware id */ - uint32_t hw_rev; /* 0x38: FIXME: hardware revision? */ - uint32_t unk1; /* 0x3c: 0x00000000 */ - uint8_t md5sum1[MD5SUM_LEN]; /* 0x40 */ - uint32_t unk2; /* 0x50: 0x00000000 */ - uint8_t md5sum2[MD5SUM_LEN]; /* 0x54 */ - uint32_t unk3; /* 0x64: 0xffffffff */ - - uint32_t kernel_la; /* 0x68: kernel load address */ - uint32_t kernel_ep; /* 0x6c: kernel entry point */ - uint32_t fw_length; /* 0x70: total length of the image */ - uint32_t kernel_ofs; /* 0x74: kernel data offset */ - uint32_t kernel_len; /* 0x78: kernel data length */ - uint32_t rootfs_ofs; /* 0x7c: rootfs data offset */ - uint32_t rootfs_len; /* 0x80: rootfs data length */ - uint32_t boot_ofs; /* 0x84: FIXME: seems to be unused */ - uint32_t boot_len; /* 0x88: FIXME: seems to be unused */ - uint16_t unk4; /* 0x8c: 0x55aa */ - uint8_t sver_hi; /* 0x8e */ - uint8_t sver_lo; /* 0x8f */ - uint8_t unk5; /* 0x90: magic: 0xa5 */ - uint8_t ver_hi; /* 0x91 */ - uint8_t ver_mid; /* 0x92 */ - uint8_t ver_lo; /* 0x93 */ - uint8_t pad[364]; -} __attribute__ ((packed)); - -struct tplink_fw_header { - uint32_t version; - union { - struct fw_v1 v1; - struct fw_v2 v2; - }; -}; - -static int mtdsplit_parse_tplink(struct mtd_info *master, - const struct mtd_partition **pparts, - struct mtd_part_parser_data *data) -{ - struct tplink_fw_header hdr; - size_t hdr_len, retlen, kernel_size; - size_t rootfs_offset; - struct mtd_partition *parts; - int err; - - hdr_len = sizeof(hdr); - err = mtd_read(master, 0, hdr_len, &retlen, (void *) &hdr); - if (err) - return err; - - if (retlen != hdr_len) - return -EIO; - - switch (le32_to_cpu(hdr.version)) { - case 1: - if (be32_to_cpu(hdr.v1.kernel_ofs) != sizeof(hdr)) - return -EINVAL; - - kernel_size = sizeof(hdr) + be32_to_cpu(hdr.v1.kernel_len); - rootfs_offset = be32_to_cpu(hdr.v1.rootfs_ofs); - break; - case 2: - case 3: - if (be32_to_cpu(hdr.v2.kernel_ofs) != sizeof(hdr)) - return -EINVAL; - - kernel_size = sizeof(hdr) + be32_to_cpu(hdr.v2.kernel_len); - rootfs_offset = be32_to_cpu(hdr.v2.rootfs_ofs); - break; - default: - return -EINVAL; - } - - if (kernel_size > master->size) - return -EINVAL; - - /* Find the rootfs */ - err = mtd_check_rootfs_magic(master, rootfs_offset, NULL); - if (err) { - /* - * The size in the header might cover the rootfs as well. - * Start the search from an arbitrary offset. - */ - err = mtd_find_rootfs_from(master, TPLINK_MIN_ROOTFS_OFFS, - master->size, &rootfs_offset, NULL); - if (err) - return err; - } - - parts = kzalloc(TPLINK_NR_PARTS * sizeof(*parts), GFP_KERNEL); - if (!parts) - return -ENOMEM; - - parts[0].name = KERNEL_PART_NAME; - parts[0].offset = 0; - parts[0].size = kernel_size; - - parts[1].name = ROOTFS_PART_NAME; - parts[1].offset = rootfs_offset; - parts[1].size = master->size - rootfs_offset; - - *pparts = parts; - return TPLINK_NR_PARTS; -} - -static const struct of_device_id mtdsplit_tplink_of_match_table[] = { - { .compatible = "tplink,firmware" }, - {}, -}; - -static struct mtd_part_parser mtdsplit_tplink_parser = { - .owner = THIS_MODULE, - .name = "tplink-fw", - .of_match_table = mtdsplit_tplink_of_match_table, - .parse_fn = mtdsplit_parse_tplink, - .type = MTD_PARSER_TYPE_FIRMWARE, -}; - -static int __init mtdsplit_tplink_init(void) -{ - register_mtd_parser(&mtdsplit_tplink_parser); - - return 0; -} - -subsys_initcall(mtdsplit_tplink_init); diff --git a/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/mtdsplit_trx.c b/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/mtdsplit_trx.c deleted file mode 100644 index b853ec9e528383..00000000000000 --- a/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/mtdsplit_trx.c +++ /dev/null @@ -1,155 +0,0 @@ -/* - * Copyright (C) 2013 Gabor Juhos - * Copyright (C) 2014 Felix Fietkau - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published - * by the Free Software Foundation. - * - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "mtdsplit.h" - -#define TRX_MAGIC 0x30524448 /* "HDR0" */ - -struct trx_header { - __le32 magic; - __le32 len; - __le32 crc32; - __le32 flag_version; - __le32 offset[4]; -}; - -static int -read_trx_header(struct mtd_info *mtd, size_t offset, - struct trx_header *header) -{ - size_t header_len; - size_t retlen; - int ret; - - header_len = sizeof(*header); - ret = mtd_read(mtd, offset, header_len, &retlen, - (unsigned char *) header); - if (ret) { - pr_debug("read error in \"%s\"\n", mtd->name); - return ret; - } - - if (retlen != header_len) { - pr_debug("short read in \"%s\"\n", mtd->name); - return -EIO; - } - - return 0; -} - -static int -mtdsplit_parse_trx(struct mtd_info *master, - const struct mtd_partition **pparts, - struct mtd_part_parser_data *data) -{ - struct mtd_partition *parts; - struct trx_header hdr; - int nr_parts; - size_t offset; - size_t trx_offset; - size_t trx_size = 0; - size_t rootfs_offset; - size_t rootfs_size = 0; - int ret; - - nr_parts = 2; - parts = kzalloc(nr_parts * sizeof(*parts), GFP_KERNEL); - if (!parts) - return -ENOMEM; - - /* find trx image on erase block boundaries */ - for (offset = 0; offset < master->size; offset += master->erasesize) { - trx_size = 0; - - ret = read_trx_header(master, offset, &hdr); - if (ret) - continue; - - if (hdr.magic != cpu_to_le32(TRX_MAGIC)) { - pr_debug("no valid trx header found in \"%s\" at offset %llx\n", - master->name, (unsigned long long) offset); - continue; - } - - trx_size = le32_to_cpu(hdr.len); - if ((offset + trx_size) > master->size) { - pr_debug("trx image exceeds MTD device \"%s\"\n", - master->name); - continue; - } - break; - } - - if (trx_size == 0) { - pr_debug("no trx header found in \"%s\"\n", master->name); - ret = -ENODEV; - goto err; - } - - trx_offset = offset + hdr.offset[0]; - rootfs_offset = offset + hdr.offset[1]; - rootfs_size = master->size - rootfs_offset; - trx_size = rootfs_offset - trx_offset; - - if (rootfs_size == 0) { - pr_debug("no rootfs found in \"%s\"\n", master->name); - ret = -ENODEV; - goto err; - } - - parts[0].name = KERNEL_PART_NAME; - parts[0].offset = trx_offset; - parts[0].size = trx_size; - - parts[1].name = ROOTFS_PART_NAME; - parts[1].offset = rootfs_offset; - parts[1].size = rootfs_size; - - *pparts = parts; - return nr_parts; - -err: - kfree(parts); - return ret; -} - -static const struct of_device_id trx_parser_of_match_table[] = { - { .compatible = "openwrt,trx" }, - {}, -}; -MODULE_DEVICE_TABLE(of, trx_parser_of_match_table); - -static struct mtd_part_parser trx_parser = { - .owner = THIS_MODULE, - .name = "trx-fw", - .of_match_table = trx_parser_of_match_table, - .parse_fn = mtdsplit_parse_trx, - .type = MTD_PARSER_TYPE_FIRMWARE, -}; - -static int __init mtdsplit_trx_init(void) -{ - register_mtd_parser(&trx_parser); - - return 0; -} - -module_init(mtdsplit_trx_init); diff --git a/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/mtdsplit_uimage.c b/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/mtdsplit_uimage.c deleted file mode 100644 index a3e55fb1fe38fd..00000000000000 --- a/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/mtdsplit_uimage.c +++ /dev/null @@ -1,282 +0,0 @@ -/* - * Copyright (C) 2013 Gabor Juhos - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published - * by the Free Software Foundation. - * - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "mtdsplit.h" - -/* - * Legacy format image header, - * all data in network byte order (aka natural aka bigendian). - */ -struct uimage_header { - uint32_t ih_magic; /* Image Header Magic Number */ - uint32_t ih_hcrc; /* Image Header CRC Checksum */ - uint32_t ih_time; /* Image Creation Timestamp */ - uint32_t ih_size; /* Image Data Size */ - uint32_t ih_load; /* Data Load Address */ - uint32_t ih_ep; /* Entry Point Address */ - uint32_t ih_dcrc; /* Image Data CRC Checksum */ - uint8_t ih_os; /* Operating System */ - uint8_t ih_arch; /* CPU architecture */ - uint8_t ih_type; /* Image Type */ - uint8_t ih_comp; /* Compression Type */ - uint8_t ih_name[IH_NMLEN]; /* Image Name */ -}; - -static int -read_uimage_header(struct mtd_info *mtd, size_t offset, u_char *buf, - size_t header_len) -{ - size_t retlen; - int ret; - - ret = mtd_read(mtd, offset, header_len, &retlen, buf); - if (ret) { - pr_debug("read error in \"%s\"\n", mtd->name); - return ret; - } - - if (retlen != header_len) { - pr_debug("short read in \"%s\"\n", mtd->name); - return -EIO; - } - - return 0; -} - -static void uimage_parse_dt(struct mtd_info *master, int *extralen, - u32 *ih_magic, u32 *ih_type, - u32 *header_offset, u32 *part_magic) -{ - struct device_node *np = mtd_get_of_node(master); - - if (!np || !of_device_is_compatible(np, "openwrt,uimage")) - return; - - if (!of_property_read_u32(np, "openwrt,padding", extralen)) - pr_debug("got openwrt,padding=%d from device-tree\n", *extralen); - if (!of_property_read_u32(np, "openwrt,ih-magic", ih_magic)) - pr_debug("got openwrt,ih-magic=%08x from device-tree\n", *ih_magic); - if (!of_property_read_u32(np, "openwrt,ih-type", ih_type)) - pr_debug("got openwrt,ih-type=%08x from device-tree\n", *ih_type); - if (!of_property_read_u32(np, "openwrt,offset", header_offset)) - pr_debug("got ih-start=%u from device-tree\n", *header_offset); - if (!of_property_read_u32(np, "openwrt,partition-magic", part_magic)) - pr_debug("got openwrt,partition-magic=%08x from device-tree\n", *part_magic); -} - -static ssize_t uimage_verify_default(u_char *buf, u32 ih_magic, u32 ih_type) -{ - struct uimage_header *header = (struct uimage_header *)buf; - - /* default sanity checks */ - if (be32_to_cpu(header->ih_magic) != ih_magic) { - pr_debug("invalid uImage magic: %08x != %08x\n", - be32_to_cpu(header->ih_magic), ih_magic); - return -EINVAL; - } - - if (header->ih_os != IH_OS_LINUX) { - pr_debug("invalid uImage OS: %08x != %08x\n", - be32_to_cpu(header->ih_os), IH_OS_LINUX); - return -EINVAL; - } - - if (header->ih_type != ih_type) { - pr_debug("invalid uImage type: %08x != %08x\n", - be32_to_cpu(header->ih_type), ih_type); - return -EINVAL; - } - - return 0; -} - -/** - * __mtdsplit_parse_uimage - scan partition and create kernel + rootfs parts - * - * @find_header: function to call for a block of data that will return offset - * and tail padding length of a valid uImage header if found - */ -static int __mtdsplit_parse_uimage(struct mtd_info *master, - const struct mtd_partition **pparts, - struct mtd_part_parser_data *data) -{ - struct mtd_partition *parts; - u_char *buf; - int nr_parts; - size_t offset; - size_t uimage_offset; - size_t uimage_size = 0; - size_t rootfs_offset; - size_t rootfs_size = 0; - size_t buflen; - int uimage_part, rf_part; - int ret; - int extralen = 0; - u32 ih_magic = IH_MAGIC; - u32 ih_type = IH_TYPE_KERNEL; - u32 header_offset = 0; - u32 part_magic = 0; - enum mtdsplit_part_type type; - - nr_parts = 2; - parts = kzalloc(nr_parts * sizeof(*parts), GFP_KERNEL); - if (!parts) - return -ENOMEM; - - uimage_parse_dt(master, &extralen, &ih_magic, &ih_type, &header_offset, &part_magic); - buflen = sizeof(struct uimage_header) + header_offset; - buf = vmalloc(buflen); - if (!buf) { - ret = -ENOMEM; - goto err_free_parts; - } - - /* find uImage on erase block boundaries */ - for (offset = 0; offset < master->size; offset += master->erasesize) { - struct uimage_header *header; - - uimage_size = 0; - - ret = read_uimage_header(master, offset, buf, buflen); - if (ret) - continue; - - /* verify optional partition magic before uimage header */ - if (header_offset && part_magic && (be32_to_cpu(*(u32 *)buf) != part_magic)) - continue; - - ret = uimage_verify_default(buf + header_offset, ih_magic, ih_type); - if (ret < 0) { - pr_debug("no valid uImage found in \"%s\" at offset %llx\n", - master->name, (unsigned long long) offset); - continue; - } - - header = (struct uimage_header *)(buf + header_offset); - - uimage_size = sizeof(*header) + - be32_to_cpu(header->ih_size) + header_offset + extralen; - - if ((offset + uimage_size) > master->size) { - pr_debug("uImage exceeds MTD device \"%s\"\n", - master->name); - continue; - } - break; - } - - if (uimage_size == 0) { - pr_debug("no uImage found in \"%s\"\n", master->name); - ret = -ENODEV; - goto err_free_buf; - } - - uimage_offset = offset; - - if (uimage_offset == 0) { - uimage_part = 0; - rf_part = 1; - - /* find the roots after the uImage */ - ret = mtd_find_rootfs_from(master, uimage_offset + uimage_size, - master->size, &rootfs_offset, &type); - if (ret) { - pr_debug("no rootfs after uImage in \"%s\"\n", - master->name); - goto err_free_buf; - } - - rootfs_size = master->size - rootfs_offset; - uimage_size = rootfs_offset - uimage_offset; - } else { - rf_part = 0; - uimage_part = 1; - - /* check rootfs presence at offset 0 */ - ret = mtd_check_rootfs_magic(master, 0, &type); - if (ret) { - pr_debug("no rootfs before uImage in \"%s\"\n", - master->name); - goto err_free_buf; - } - - rootfs_offset = 0; - rootfs_size = uimage_offset; - } - - if (rootfs_size == 0) { - pr_debug("no rootfs found in \"%s\"\n", master->name); - ret = -ENODEV; - goto err_free_buf; - } - - parts[uimage_part].name = KERNEL_PART_NAME; - parts[uimage_part].offset = uimage_offset; - parts[uimage_part].size = uimage_size; - - if (type == MTDSPLIT_PART_TYPE_UBI) - parts[rf_part].name = UBI_PART_NAME; - else - parts[rf_part].name = ROOTFS_PART_NAME; - parts[rf_part].offset = rootfs_offset; - parts[rf_part].size = rootfs_size; - - vfree(buf); - - *pparts = parts; - return nr_parts; - -err_free_buf: - vfree(buf); - -err_free_parts: - kfree(parts); - return ret; -} - -static const struct of_device_id mtdsplit_uimage_of_match_table[] = { - { .compatible = "denx,uimage" }, - { .compatible = "openwrt,uimage" }, - {}, -}; - -static struct mtd_part_parser uimage_generic_parser = { - .owner = THIS_MODULE, - .name = "uimage-fw", - .of_match_table = mtdsplit_uimage_of_match_table, - .parse_fn = __mtdsplit_parse_uimage, - .type = MTD_PARSER_TYPE_FIRMWARE, -}; - -/************************************************** - * Init - **************************************************/ - -static int __init mtdsplit_uimage_init(void) -{ - register_mtd_parser(&uimage_generic_parser); - - return 0; -} - -module_init(mtdsplit_uimage_init); diff --git a/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/mtdsplit_wrgg.c b/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/mtdsplit_wrgg.c deleted file mode 100644 index dfd6058ae7e48a..00000000000000 --- a/target/linux/generic/files-6.12/drivers/mtd/mtdsplit/mtdsplit_wrgg.c +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright (C) 2013 Gabor Juhos - * Copyright (C) 2014 Felix Fietkau - * Copyright (C) 2016 Stijn Tintel - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published - * by the Free Software Foundation. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "mtdsplit.h" - -#define WRGG_NR_PARTS 2 -#define WRGG_MIN_ROOTFS_OFFS 0x80000 /* 512KiB */ -#define WRGG03_MAGIC 0x20080321 -#define WRG_MAGIC 0x20040220 - -struct wrgg03_header { - char signature[32]; - uint32_t magic1; - uint32_t magic2; - char version[16]; - char model[16]; - uint32_t flag[2]; - uint32_t reserve[2]; - char buildno[16]; - uint32_t size; - uint32_t offset; - char devname[32]; - char digest[16]; -} __attribute__ ((packed)); - -struct wrg_header { - char signature[32]; - uint32_t magic1; - uint32_t magic2; - uint32_t size; - uint32_t offset; - char devname[32]; - char digest[16]; -} __attribute__ ((packed)); - - -static int mtdsplit_parse_wrgg(struct mtd_info *master, - const struct mtd_partition **pparts, - struct mtd_part_parser_data *data) -{ - struct wrgg03_header hdr; - size_t hdr_len, retlen, kernel_ent_size; - size_t rootfs_offset; - struct mtd_partition *parts; - enum mtdsplit_part_type type; - int err; - - hdr_len = sizeof(hdr); - err = mtd_read(master, 0, hdr_len, &retlen, (void *) &hdr); - if (err) - return err; - - if (retlen != hdr_len) - return -EIO; - - /* sanity checks */ - if (le32_to_cpu(hdr.magic1) == WRGG03_MAGIC) { - kernel_ent_size = hdr_len + be32_to_cpu(hdr.size); - /* - * If this becomes silly big it's probably because the - * WRGG image is little-endian. - */ - if (kernel_ent_size > master->size) - kernel_ent_size = hdr_len + le32_to_cpu(hdr.size); - - /* Now what ?! It's neither */ - if (kernel_ent_size > master->size) - return -EINVAL; - } else if (le32_to_cpu(hdr.magic1) == WRG_MAGIC) { - kernel_ent_size = sizeof(struct wrg_header) + le32_to_cpu( - ((struct wrg_header*)&hdr)->size); - } else { - return -EINVAL; - } - - if (kernel_ent_size > master->size) - return -EINVAL; - - /* - * The size in the header covers the rootfs as well. - * Start the search from an arbitrary offset. - */ - err = mtd_find_rootfs_from(master, WRGG_MIN_ROOTFS_OFFS, - master->size, &rootfs_offset, &type); - if (err) - return err; - - parts = kzalloc(WRGG_NR_PARTS * sizeof(*parts), GFP_KERNEL); - if (!parts) - return -ENOMEM; - - parts[0].name = KERNEL_PART_NAME; - parts[0].offset = 0; - parts[0].size = rootfs_offset; - - parts[1].name = ROOTFS_PART_NAME; - parts[1].offset = rootfs_offset; - parts[1].size = master->size - rootfs_offset; - - *pparts = parts; - return WRGG_NR_PARTS; -} - -static const struct of_device_id mtdsplit_wrgg_of_match_table[] = { - { .compatible = "wrg" }, - {}, -}; -MODULE_DEVICE_TABLE(of, mtdsplit_wrgg_of_match_table); - -static struct mtd_part_parser mtdsplit_wrgg_parser = { - .owner = THIS_MODULE, - .name = "wrgg-fw", - .of_match_table = mtdsplit_wrgg_of_match_table, - .parse_fn = mtdsplit_parse_wrgg, - .type = MTD_PARSER_TYPE_FIRMWARE, -}; - -static int __init mtdsplit_wrgg_init(void) -{ - register_mtd_parser(&mtdsplit_wrgg_parser); - - return 0; -} - -subsys_initcall(mtdsplit_wrgg_init); diff --git a/target/linux/generic/files-6.12/drivers/mtd/nand/mtk_bmt.c b/target/linux/generic/files-6.12/drivers/mtd/nand/mtk_bmt.c deleted file mode 100644 index bcff7d6ac82076..00000000000000 --- a/target/linux/generic/files-6.12/drivers/mtd/nand/mtk_bmt.c +++ /dev/null @@ -1,465 +0,0 @@ -/* - * Copyright (c) 2017 MediaTek Inc. - * Author: Xiangsheng Hou - * Copyright (c) 2020-2022 Felix Fietkau - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * 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. - */ - -#include -#include -#include -#include -#include "mtk_bmt.h" - -struct bmt_desc bmtd = {}; - -/* -------- Nand operations wrapper -------- */ -int bbt_nand_copy(u16 dest_blk, u16 src_blk, loff_t max_offset) -{ - int pages = bmtd.blk_size >> bmtd.pg_shift; - loff_t src = (loff_t)src_blk << bmtd.blk_shift; - loff_t dest = (loff_t)dest_blk << bmtd.blk_shift; - loff_t offset = 0; - uint8_t oob[64]; - int i, ret; - - for (i = 0; i < pages; i++) { - struct mtd_oob_ops rd_ops = { - .mode = MTD_OPS_PLACE_OOB, - .oobbuf = oob, - .ooblen = min_t(int, bmtd.mtd->oobsize / pages, sizeof(oob)), - .datbuf = bmtd.data_buf, - .len = bmtd.pg_size, - }; - struct mtd_oob_ops wr_ops = { - .mode = MTD_OPS_PLACE_OOB, - .oobbuf = oob, - .datbuf = bmtd.data_buf, - .len = bmtd.pg_size, - }; - - if (offset >= max_offset) - break; - - ret = bmtd._read_oob(bmtd.mtd, src + offset, &rd_ops); - if (ret < 0 && !mtd_is_bitflip(ret)) - return ret; - - if (!rd_ops.retlen) - break; - - ret = bmtd._write_oob(bmtd.mtd, dest + offset, &wr_ops); - if (ret < 0) - return ret; - - wr_ops.ooblen = rd_ops.oobretlen; - offset += rd_ops.retlen; - } - - return 0; -} - -/* -------- Bad Blocks Management -------- */ -bool mapping_block_in_range(int block, int *start, int *end) -{ - const __be32 *cur = bmtd.remap_range; - u32 addr = block << bmtd.blk_shift; - int i; - - if (!cur || !bmtd.remap_range_len) { - *start = 0; - *end = bmtd.total_blks; - return true; - } - - for (i = 0; i < bmtd.remap_range_len; i++, cur += 2) { - if (addr < be32_to_cpu(cur[0]) || addr >= be32_to_cpu(cur[1])) - continue; - - *start = be32_to_cpu(cur[0]); - *end = be32_to_cpu(cur[1]); - return true; - } - - return false; -} - -static bool -mtk_bmt_remap_block(u32 block, u32 mapped_block, int copy_len) -{ - int start, end; - - if (!mapping_block_in_range(block, &start, &end)) - return false; - - return bmtd.ops->remap_block(block, mapped_block, copy_len); -} - -static int -mtk_bmt_read(struct mtd_info *mtd, loff_t from, - struct mtd_oob_ops *ops) -{ - struct mtd_oob_ops cur_ops = *ops; - int retry_count = 0; - loff_t cur_from; - int ret = 0; - int max_bitflips = 0; - - ops->retlen = 0; - ops->oobretlen = 0; - - while (ops->retlen < ops->len || ops->oobretlen < ops->ooblen) { - int cur_ret; - - u32 offset = from & (bmtd.blk_size - 1); - u32 block = from >> bmtd.blk_shift; - int cur_block; - - cur_block = bmtd.ops->get_mapping_block(block); - if (cur_block < 0) - return -EIO; - - cur_from = ((loff_t)cur_block << bmtd.blk_shift) + offset; - - cur_ops.oobretlen = 0; - cur_ops.retlen = 0; - cur_ops.len = min_t(u32, mtd->erasesize - offset, - ops->len - ops->retlen); - cur_ret = bmtd._read_oob(mtd, cur_from, &cur_ops); - if (cur_ret < 0) - ret = cur_ret; - else - max_bitflips = max_t(int, max_bitflips, cur_ret); - if (cur_ret < 0 && !mtd_is_bitflip(cur_ret)) { - if (mtk_bmt_remap_block(block, cur_block, mtd->erasesize) && - retry_count++ < 10) - continue; - - goto out; - } - - if (mtd->bitflip_threshold && cur_ret >= mtd->bitflip_threshold) - mtk_bmt_remap_block(block, cur_block, mtd->erasesize); - - ops->retlen += cur_ops.retlen; - ops->oobretlen += cur_ops.oobretlen; - - cur_ops.ooboffs = 0; - cur_ops.datbuf += cur_ops.retlen; - cur_ops.oobbuf += cur_ops.oobretlen; - cur_ops.ooblen -= cur_ops.oobretlen; - - if (!cur_ops.len) - cur_ops.len = mtd->erasesize - offset; - - from += cur_ops.len; - retry_count = 0; - } - -out: - if (ret < 0) - return ret; - - return max_bitflips; -} - -static int -mtk_bmt_write(struct mtd_info *mtd, loff_t to, - struct mtd_oob_ops *ops) -{ - struct mtd_oob_ops cur_ops = *ops; - int retry_count = 0; - loff_t cur_to; - int ret; - - ops->retlen = 0; - ops->oobretlen = 0; - - while (ops->retlen < ops->len || ops->oobretlen < ops->ooblen) { - u32 offset = to & (bmtd.blk_size - 1); - u32 block = to >> bmtd.blk_shift; - int cur_block; - - cur_block = bmtd.ops->get_mapping_block(block); - if (cur_block < 0) - return -EIO; - - cur_to = ((loff_t)cur_block << bmtd.blk_shift) + offset; - - cur_ops.oobretlen = 0; - cur_ops.retlen = 0; - cur_ops.len = min_t(u32, bmtd.blk_size - offset, - ops->len - ops->retlen); - ret = bmtd._write_oob(mtd, cur_to, &cur_ops); - if (ret < 0) { - if (mtk_bmt_remap_block(block, cur_block, offset) && - retry_count++ < 10) - continue; - - return ret; - } - - ops->retlen += cur_ops.retlen; - ops->oobretlen += cur_ops.oobretlen; - - cur_ops.ooboffs = 0; - cur_ops.datbuf += cur_ops.retlen; - cur_ops.oobbuf += cur_ops.oobretlen; - cur_ops.ooblen -= cur_ops.oobretlen; - - if (!cur_ops.len) - cur_ops.len = mtd->erasesize - offset; - - to += cur_ops.len; - retry_count = 0; - } - - return 0; -} - -static int -mtk_bmt_mtd_erase(struct mtd_info *mtd, struct erase_info *instr) -{ - struct erase_info mapped_instr = { - .len = bmtd.blk_size, - }; - int retry_count = 0; - u64 start_addr, end_addr; - int ret; - u16 orig_block; - int block; - - start_addr = instr->addr & (~mtd->erasesize_mask); - end_addr = instr->addr + instr->len; - - while (start_addr < end_addr) { - orig_block = start_addr >> bmtd.blk_shift; - block = bmtd.ops->get_mapping_block(orig_block); - if (block < 0) - return -EIO; - mapped_instr.addr = (loff_t)block << bmtd.blk_shift; - ret = bmtd._erase(mtd, &mapped_instr); - if (ret) { - if (mtk_bmt_remap_block(orig_block, block, 0) && - retry_count++ < 10) - continue; - instr->fail_addr = start_addr; - break; - } - start_addr += mtd->erasesize; - retry_count = 0; - } - - return ret; -} -static int -mtk_bmt_block_isbad(struct mtd_info *mtd, loff_t ofs) -{ - int retry_count = 0; - u16 orig_block = ofs >> bmtd.blk_shift; - u16 block; - int ret; - -retry: - block = bmtd.ops->get_mapping_block(orig_block); - ret = bmtd._block_isbad(mtd, (loff_t)block << bmtd.blk_shift); - if (ret) { - if (mtk_bmt_remap_block(orig_block, block, bmtd.blk_size) && - retry_count++ < 10) - goto retry; - } - return ret; -} - -static int -mtk_bmt_block_markbad(struct mtd_info *mtd, loff_t ofs) -{ - u16 orig_block = ofs >> bmtd.blk_shift; - int block; - - block = bmtd.ops->get_mapping_block(orig_block); - if (block < 0) - return -EIO; - - mtk_bmt_remap_block(orig_block, block, bmtd.blk_size); - - return bmtd._block_markbad(mtd, (loff_t)block << bmtd.blk_shift); -} - -static void -mtk_bmt_replace_ops(struct mtd_info *mtd) -{ - bmtd._read_oob = mtd->_read_oob; - bmtd._write_oob = mtd->_write_oob; - bmtd._erase = mtd->_erase; - bmtd._block_isbad = mtd->_block_isbad; - bmtd._block_markbad = mtd->_block_markbad; - - mtd->_read_oob = mtk_bmt_read; - mtd->_write_oob = mtk_bmt_write; - mtd->_erase = mtk_bmt_mtd_erase; - mtd->_block_isbad = mtk_bmt_block_isbad; - mtd->_block_markbad = mtk_bmt_block_markbad; -} - -static int mtk_bmt_debug_repair(void *data, u64 val) -{ - int block = val >> bmtd.blk_shift; - int prev_block, new_block; - - prev_block = bmtd.ops->get_mapping_block(block); - if (prev_block < 0) - return -EIO; - - bmtd.ops->unmap_block(block); - new_block = bmtd.ops->get_mapping_block(block); - if (new_block < 0) - return -EIO; - - if (prev_block == new_block) - return 0; - - bbt_nand_erase(new_block); - bbt_nand_copy(new_block, prev_block, bmtd.blk_size); - - return 0; -} - -static int mtk_bmt_debug_mark_good(void *data, u64 val) -{ - bmtd.ops->unmap_block(val >> bmtd.blk_shift); - - return 0; -} - -static int mtk_bmt_debug_mark_bad(void *data, u64 val) -{ - u32 block = val >> bmtd.blk_shift; - int cur_block; - - cur_block = bmtd.ops->get_mapping_block(block); - if (cur_block < 0) - return -EIO; - - mtk_bmt_remap_block(block, cur_block, bmtd.blk_size); - - return 0; -} - -static int mtk_bmt_debug(void *data, u64 val) -{ - return bmtd.ops->debug(data, val); -} - - -DEFINE_DEBUGFS_ATTRIBUTE(fops_repair, NULL, mtk_bmt_debug_repair, "%llu\n"); -DEFINE_DEBUGFS_ATTRIBUTE(fops_mark_good, NULL, mtk_bmt_debug_mark_good, "%llu\n"); -DEFINE_DEBUGFS_ATTRIBUTE(fops_mark_bad, NULL, mtk_bmt_debug_mark_bad, "%llu\n"); -DEFINE_DEBUGFS_ATTRIBUTE(fops_debug, NULL, mtk_bmt_debug, "%llu\n"); - -static void -mtk_bmt_add_debugfs(void) -{ - struct dentry *dir; - - dir = bmtd.debugfs_dir = debugfs_create_dir("mtk-bmt", NULL); - if (!dir) - return; - - debugfs_create_file_unsafe("repair", S_IWUSR, dir, NULL, &fops_repair); - debugfs_create_file_unsafe("mark_good", S_IWUSR, dir, NULL, &fops_mark_good); - debugfs_create_file_unsafe("mark_bad", S_IWUSR, dir, NULL, &fops_mark_bad); - debugfs_create_file_unsafe("debug", S_IWUSR, dir, NULL, &fops_debug); -} - -void mtk_bmt_detach(struct mtd_info *mtd) -{ - if (bmtd.mtd != mtd) - return; - - if (bmtd.debugfs_dir) - debugfs_remove_recursive(bmtd.debugfs_dir); - bmtd.debugfs_dir = NULL; - - kfree(bmtd.bbt_buf); - kfree(bmtd.data_buf); - - mtd->_read_oob = bmtd._read_oob; - mtd->_write_oob = bmtd._write_oob; - mtd->_erase = bmtd._erase; - mtd->_block_isbad = bmtd._block_isbad; - mtd->_block_markbad = bmtd._block_markbad; - mtd->size = bmtd.total_blks << bmtd.blk_shift; - - memset(&bmtd, 0, sizeof(bmtd)); -} - - -int mtk_bmt_attach(struct mtd_info *mtd) -{ - struct device_node *np; - int ret = 0; - - if (bmtd.mtd) - return -ENOSPC; - - np = mtd_get_of_node(mtd); - if (!np) - return 0; - - if (of_property_read_bool(np, "mediatek,bmt-v2")) - bmtd.ops = &mtk_bmt_v2_ops; - else if (of_property_read_bool(np, "mediatek,nmbm")) - bmtd.ops = &mtk_bmt_nmbm_ops; - else if (of_property_read_bool(np, "mediatek,bbt")) - bmtd.ops = &mtk_bmt_bbt_ops; - else - return 0; - - bmtd.remap_range = of_get_property(np, "mediatek,bmt-remap-range", - &bmtd.remap_range_len); - bmtd.remap_range_len /= 8; - - bmtd.mtd = mtd; - mtk_bmt_replace_ops(mtd); - - bmtd.blk_size = mtd->erasesize; - bmtd.blk_shift = ffs(bmtd.blk_size) - 1; - bmtd.pg_size = mtd->writesize; - bmtd.pg_shift = ffs(bmtd.pg_size) - 1; - bmtd.total_blks = mtd->size >> bmtd.blk_shift; - - bmtd.data_buf = kzalloc(bmtd.pg_size + bmtd.mtd->oobsize, GFP_KERNEL); - if (!bmtd.data_buf) { - pr_info("nand: FATAL ERR: allocate buffer failed!\n"); - ret = -1; - goto error; - } - - memset(bmtd.data_buf, 0xff, bmtd.pg_size + bmtd.mtd->oobsize); - - ret = bmtd.ops->init(np); - if (ret) - goto error; - - mtk_bmt_add_debugfs(); - return 0; - -error: - mtk_bmt_detach(mtd); - return ret; -} - - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Xiangsheng Hou , Felix Fietkau "); -MODULE_DESCRIPTION("Bad Block mapping management v2 for MediaTek NAND Flash Driver"); - diff --git a/target/linux/generic/files-6.12/drivers/mtd/nand/mtk_bmt.h b/target/linux/generic/files-6.12/drivers/mtd/nand/mtk_bmt.h deleted file mode 100644 index 517ff7414f34ab..00000000000000 --- a/target/linux/generic/files-6.12/drivers/mtd/nand/mtk_bmt.h +++ /dev/null @@ -1,137 +0,0 @@ -#ifndef __MTK_BMT_PRIV_H -#define __MTK_BMT_PRIV_H - -#include -#include -#include -#include -#include -#include - -#define MAIN_SIGNATURE_OFFSET 0 -#define OOB_SIGNATURE_OFFSET 1 - -#define BBT_LOG(fmt, ...) pr_debug("[BBT][%s|%d] "fmt"\n", __func__, __LINE__, ##__VA_ARGS__) - -struct mtk_bmt_ops { - char *sig; - unsigned int sig_len; - int (*init)(struct device_node *np); - bool (*remap_block)(u16 block, u16 mapped_block, int copy_len); - void (*unmap_block)(u16 block); - int (*get_mapping_block)(int block); - int (*debug)(void *data, u64 val); -}; - -struct bbbt; -struct nmbm_instance; - -struct bmt_desc { - struct mtd_info *mtd; - unsigned char *bbt_buf; - unsigned char *data_buf; - - int (*_read_oob) (struct mtd_info *mtd, loff_t from, - struct mtd_oob_ops *ops); - int (*_write_oob) (struct mtd_info *mtd, loff_t to, - struct mtd_oob_ops *ops); - int (*_erase) (struct mtd_info *mtd, struct erase_info *instr); - int (*_block_isbad) (struct mtd_info *mtd, loff_t ofs); - int (*_block_markbad) (struct mtd_info *mtd, loff_t ofs); - - const struct mtk_bmt_ops *ops; - - union { - struct bbbt *bbt; - struct nmbm_instance *ni; - }; - - struct dentry *debugfs_dir; - - u32 table_size; - u32 pg_size; - u32 blk_size; - u16 pg_shift; - u16 blk_shift; - /* bbt logical address */ - u16 pool_lba; - /* bbt physical address */ - u16 pool_pba; - /* Maximum count of bad blocks that the vendor guaranteed */ - u16 bb_max; - /* Total blocks of the Nand Chip */ - u16 total_blks; - /* The block(n) BMT is located at (bmt_tbl[n]) */ - u16 bmt_blk_idx; - /* How many pages needs to store 'struct bbbt' */ - u32 bmt_pgs; - - const __be32 *remap_range; - int remap_range_len; - - /* to compensate for driver level remapping */ - u8 oob_offset; -}; - -extern struct bmt_desc bmtd; -extern const struct mtk_bmt_ops mtk_bmt_v2_ops; -extern const struct mtk_bmt_ops mtk_bmt_bbt_ops; -extern const struct mtk_bmt_ops mtk_bmt_nmbm_ops; - -static inline u32 blk_pg(u16 block) -{ - return (u32)(block << (bmtd.blk_shift - bmtd.pg_shift)); -} - -static inline int -bbt_nand_read(u32 page, unsigned char *dat, int dat_len, - unsigned char *fdm, int fdm_len) -{ - struct mtd_oob_ops ops = { - .mode = MTD_OPS_PLACE_OOB, - .ooboffs = bmtd.oob_offset, - .oobbuf = fdm, - .ooblen = fdm_len, - .datbuf = dat, - .len = dat_len, - }; - int ret; - - ret = bmtd._read_oob(bmtd.mtd, page << bmtd.pg_shift, &ops); - if (ret < 0) - return ret; - if (ret) - pr_info("%s: %d bitflips\n", __func__, ret); - return 0; -} - -static inline int bbt_nand_erase(u16 block) -{ - struct mtd_info *mtd = bmtd.mtd; - struct erase_info instr = { - .addr = (loff_t)block << bmtd.blk_shift, - .len = bmtd.blk_size, - }; - - return bmtd._erase(mtd, &instr); -} - -static inline int write_bmt(u16 block, unsigned char *dat) -{ - struct mtd_oob_ops ops = { - .mode = MTD_OPS_PLACE_OOB, - .ooboffs = OOB_SIGNATURE_OFFSET + bmtd.oob_offset, - .oobbuf = bmtd.ops->sig, - .ooblen = bmtd.ops->sig_len, - .datbuf = dat, - .len = bmtd.bmt_pgs << bmtd.pg_shift, - }; - loff_t addr = (loff_t)block << bmtd.blk_shift; - - return bmtd._write_oob(bmtd.mtd, addr, &ops); -} - -int bbt_nand_copy(u16 dest_blk, u16 src_blk, loff_t max_offset); -bool mapping_block_in_range(int block, int *start, int *end); - -#endif diff --git a/target/linux/generic/files-6.12/drivers/mtd/nand/mtk_bmt_bbt.c b/target/linux/generic/files-6.12/drivers/mtd/nand/mtk_bmt_bbt.c deleted file mode 100644 index 519e1ed70c7b8a..00000000000000 --- a/target/linux/generic/files-6.12/drivers/mtd/nand/mtk_bmt_bbt.c +++ /dev/null @@ -1,203 +0,0 @@ -/* - * Copyright (c) 2017 MediaTek Inc. - * Author: Xiangsheng Hou - * Copyright (c) 2020-2022 Felix Fietkau - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * 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. - */ - -#include -#include -#include "mtk_bmt.h" - -static bool -bbt_block_is_bad(u16 block) -{ - u8 cur = bmtd.bbt_buf[block / 4]; - - return cur & (3 << ((block % 4) * 2)); -} - -static void -bbt_set_block_state(u16 block, bool bad) -{ - u8 mask = (3 << ((block % 4) * 2)); - - if (bad) - bmtd.bbt_buf[block / 4] |= mask; - else - bmtd.bbt_buf[block / 4] &= ~mask; - - bbt_nand_erase(bmtd.bmt_blk_idx); - write_bmt(bmtd.bmt_blk_idx, bmtd.bbt_buf); -} - -static int -get_mapping_block_index_bbt(int block) -{ - int start, end, ofs; - int bad_blocks = 0; - int i; - - if (!mapping_block_in_range(block, &start, &end)) - return block; - - start >>= bmtd.blk_shift; - end >>= bmtd.blk_shift; - /* skip bad blocks within the mapping range */ - ofs = block - start; - for (i = start; i < end; i++) { - if (bbt_block_is_bad(i)) - bad_blocks++; - else if (ofs) - ofs--; - else - break; - } - - if (i < end) - return i; - - /* when overflowing, remap remaining blocks to bad ones */ - for (i = end - 1; bad_blocks > 0; i--) { - if (!bbt_block_is_bad(i)) - continue; - - bad_blocks--; - if (bad_blocks <= ofs) - return i; - } - - return block; -} - -static bool remap_block_bbt(u16 block, u16 mapped_blk, int copy_len) -{ - int start, end; - u16 new_blk; - - if (!mapping_block_in_range(block, &start, &end)) - return false; - - bbt_set_block_state(mapped_blk, true); - - new_blk = get_mapping_block_index_bbt(block); - bbt_nand_erase(new_blk); - if (copy_len > 0) - bbt_nand_copy(new_blk, mapped_blk, copy_len); - - return true; -} - -static void -unmap_block_bbt(u16 block) -{ - bbt_set_block_state(block, false); -} - -static int -mtk_bmt_read_bbt(void) -{ - u8 oob_buf[8]; - int i; - - for (i = bmtd.total_blks - 1; i >= bmtd.total_blks - 5; i--) { - u32 page = i << (bmtd.blk_shift - bmtd.pg_shift); - - if (bbt_nand_read(page, bmtd.bbt_buf, bmtd.pg_size, - oob_buf, sizeof(oob_buf))) { - pr_info("read_bbt: could not read block %d\n", i); - continue; - } - - if (oob_buf[0] != 0xff) { - pr_info("read_bbt: bad block at %d\n", i); - continue; - } - - if (memcmp(&oob_buf[1], "mtknand", 7) != 0) { - pr_info("read_bbt: signature mismatch in block %d\n", i); - print_hex_dump(KERN_INFO, "", DUMP_PREFIX_OFFSET, 16, 1, oob_buf, 8, 1); - continue; - } - - pr_info("read_bbt: found bbt at block %d\n", i); - bmtd.bmt_blk_idx = i; - return 0; - } - - return -EIO; -} - - -static int -mtk_bmt_init_bbt(struct device_node *np) -{ - int buf_size = round_up(bmtd.total_blks >> 2, bmtd.blk_size); - int ret; - - bmtd.bbt_buf = kmalloc(buf_size, GFP_KERNEL); - if (!bmtd.bbt_buf) - return -ENOMEM; - - memset(bmtd.bbt_buf, 0xff, buf_size); - bmtd.mtd->size -= 4 * bmtd.mtd->erasesize; - - ret = mtk_bmt_read_bbt(); - if (ret) - return ret; - - bmtd.bmt_pgs = buf_size / bmtd.pg_size; - - return 0; -} - -static int mtk_bmt_debug_bbt(void *data, u64 val) -{ - char buf[5]; - int i, k; - - switch (val) { - case 0: - for (i = 0; i < bmtd.total_blks; i += 4) { - u8 cur = bmtd.bbt_buf[i / 4]; - - for (k = 0; k < 4; k++, cur >>= 2) - buf[k] = (cur & 3) ? 'B' : '.'; - - buf[4] = 0; - printk("[%06x] %s\n", i * bmtd.blk_size, buf); - } - break; - case 100: -#if 0 - for (i = bmtd.bmt_blk_idx; i < bmtd.total_blks - 1; i++) - bbt_nand_erase(bmtd.bmt_blk_idx); -#endif - - bmtd.bmt_blk_idx = bmtd.total_blks - 1; - bbt_nand_erase(bmtd.bmt_blk_idx); - write_bmt(bmtd.bmt_blk_idx, bmtd.bbt_buf); - break; - default: - break; - } - return 0; -} - -const struct mtk_bmt_ops mtk_bmt_bbt_ops = { - .sig = "mtknand", - .sig_len = 7, - .init = mtk_bmt_init_bbt, - .remap_block = remap_block_bbt, - .unmap_block = unmap_block_bbt, - .get_mapping_block = get_mapping_block_index_bbt, - .debug = mtk_bmt_debug_bbt, -}; diff --git a/target/linux/generic/files-6.12/drivers/mtd/nand/mtk_bmt_nmbm.c b/target/linux/generic/files-6.12/drivers/mtd/nand/mtk_bmt_nmbm.c deleted file mode 100644 index a896e49ec04751..00000000000000 --- a/target/linux/generic/files-6.12/drivers/mtd/nand/mtk_bmt_nmbm.c +++ /dev/null @@ -1,2348 +0,0 @@ -#include -#include -#include "mtk_bmt.h" - -#define nlog_err(ni, ...) printk(KERN_ERR __VA_ARGS__) -#define nlog_info(ni, ...) printk(KERN_INFO __VA_ARGS__) -#define nlog_debug(ni, ...) printk(KERN_INFO __VA_ARGS__) -#define nlog_warn(ni, ...) printk(KERN_WARNING __VA_ARGS__) - -#define NMBM_MAGIC_SIGNATURE 0x304d4d4e /* NMM0 */ -#define NMBM_MAGIC_INFO_TABLE 0x314d4d4e /* NMM1 */ - -#define NMBM_VERSION_MAJOR_S 0 -#define NMBM_VERSION_MAJOR_M 0xffff -#define NMBM_VERSION_MINOR_S 16 -#define NMBM_VERSION_MINOR_M 0xffff -#define NMBM_VERSION_MAKE(major, minor) (((major) & NMBM_VERSION_MAJOR_M) | \ - (((minor) & NMBM_VERSION_MINOR_M) << \ - NMBM_VERSION_MINOR_S)) -#define NMBM_VERSION_MAJOR_GET(ver) (((ver) >> NMBM_VERSION_MAJOR_S) & \ - NMBM_VERSION_MAJOR_M) -#define NMBM_VERSION_MINOR_GET(ver) (((ver) >> NMBM_VERSION_MINOR_S) & \ - NMBM_VERSION_MINOR_M) - -#define NMBM_BITMAP_UNIT_SIZE (sizeof(u32)) -#define NMBM_BITMAP_BITS_PER_BLOCK 2 -#define NMBM_BITMAP_BITS_PER_UNIT (8 * sizeof(u32)) -#define NMBM_BITMAP_BLOCKS_PER_UNIT (NMBM_BITMAP_BITS_PER_UNIT / \ - NMBM_BITMAP_BITS_PER_BLOCK) - -#define NMBM_SPARE_BLOCK_MULTI 1 -#define NMBM_SPARE_BLOCK_DIV 2 -#define NMBM_SPARE_BLOCK_MIN 2 - -#define NMBM_MGMT_DIV 16 -#define NMBM_MGMT_BLOCKS_MIN 32 - -#define NMBM_TRY_COUNT 3 - -#define BLOCK_ST_BAD 0 -#define BLOCK_ST_NEED_REMAP 2 -#define BLOCK_ST_GOOD 3 -#define BLOCK_ST_MASK 3 - -#define NMBM_VER_MAJOR 1 -#define NMBM_VER_MINOR 0 -#define NMBM_VER NMBM_VERSION_MAKE(NMBM_VER_MAJOR, \ - NMBM_VER_MINOR) - -struct nmbm_header { - u32 magic; - u32 version; - u32 size; - u32 checksum; -}; - -struct nmbm_signature { - struct nmbm_header header; - uint64_t nand_size; - u32 block_size; - u32 page_size; - u32 spare_size; - u32 mgmt_start_pb; - u8 max_try_count; - u8 padding[3]; -}; - -struct nmbm_info_table_header { - struct nmbm_header header; - u32 write_count; - u32 state_table_off; - u32 mapping_table_off; - u32 padding; -}; - -struct nmbm_instance { - u32 rawpage_size; - u32 rawblock_size; - u32 rawchip_size; - - struct nmbm_signature signature; - - u8 *info_table_cache; - u32 info_table_size; - u32 info_table_spare_blocks; - struct nmbm_info_table_header info_table; - - u32 *block_state; - u32 block_state_changed; - u32 state_table_size; - - int32_t *block_mapping; - u32 block_mapping_changed; - u32 mapping_table_size; - - u8 *page_cache; - - int protected; - - u32 block_count; - u32 data_block_count; - - u32 mgmt_start_ba; - u32 main_table_ba; - u32 backup_table_ba; - u32 mapping_blocks_ba; - u32 mapping_blocks_top_ba; - u32 signature_ba; - - u32 max_ratio; - u32 max_reserved_blocks; - bool empty_page_ecc_ok; - bool force_create; -}; - -static inline u32 nmbm_crc32(u32 crcval, const void *buf, size_t size) -{ - unsigned int chksz; - const unsigned char *p = buf; - - while (size) { - if (size > UINT_MAX) - chksz = UINT_MAX; - else - chksz = (uint)size; - - crcval = crc32_le(crcval, p, chksz); - size -= chksz; - p += chksz; - } - - return crcval; -} -/* - * nlog_table_creation - Print log of table creation event - * @ni: NMBM instance structure - * @main_table: whether the table is main info table - * @start_ba: start block address of the table - * @end_ba: block address after the end of the table - */ -static void nlog_table_creation(struct nmbm_instance *ni, bool main_table, - uint32_t start_ba, uint32_t end_ba) -{ - if (start_ba == end_ba - 1) - nlog_info(ni, "%s info table has been written to block %u\n", - main_table ? "Main" : "Backup", start_ba); - else - nlog_info(ni, "%s info table has been written to block %u-%u\n", - main_table ? "Main" : "Backup", start_ba, end_ba - 1); -} - -/* - * nlog_table_update - Print log of table update event - * @ni: NMBM instance structure - * @main_table: whether the table is main info table - * @start_ba: start block address of the table - * @end_ba: block address after the end of the table - */ -static void nlog_table_update(struct nmbm_instance *ni, bool main_table, - uint32_t start_ba, uint32_t end_ba) -{ - if (start_ba == end_ba - 1) - nlog_debug(ni, "%s info table has been updated in block %u\n", - main_table ? "Main" : "Backup", start_ba); - else - nlog_debug(ni, "%s info table has been updated in block %u-%u\n", - main_table ? "Main" : "Backup", start_ba, end_ba - 1); -} - -/* - * nlog_table_found - Print log of table found event - * @ni: NMBM instance structure - * @first_table: whether the table is first found info table - * @write_count: write count of the info table - * @start_ba: start block address of the table - * @end_ba: block address after the end of the table - */ -static void nlog_table_found(struct nmbm_instance *ni, bool first_table, - uint32_t write_count, uint32_t start_ba, - uint32_t end_ba) -{ - if (start_ba == end_ba - 1) - nlog_info(ni, "%s info table with writecount %u found in block %u\n", - first_table ? "First" : "Second", write_count, - start_ba); - else - nlog_info(ni, "%s info table with writecount %u found in block %u-%u\n", - first_table ? "First" : "Second", write_count, - start_ba, end_ba - 1); -} - -/*****************************************************************************/ -/* Address conversion functions */ -/*****************************************************************************/ - -/* - * ba2addr - Convert a block address to linear address - * @ni: NMBM instance structure - * @ba: Block address - */ -static uint64_t ba2addr(struct nmbm_instance *ni, uint32_t ba) -{ - return (uint64_t)ba << bmtd.blk_shift; -} -/* - * size2blk - Get minimum required blocks for storing specific size of data - * @ni: NMBM instance structure - * @size: size for storing - */ -static uint32_t size2blk(struct nmbm_instance *ni, uint64_t size) -{ - return (size + bmtd.blk_size - 1) >> bmtd.blk_shift; -} - -/*****************************************************************************/ -/* High level NAND chip APIs */ -/*****************************************************************************/ - -/* - * nmbm_read_phys_page - Read page with retry - * @ni: NMBM instance structure - * @addr: linear address where the data will be read from - * @data: the main data to be read - * @oob: the oob data to be read - * - * Read a page for at most NMBM_TRY_COUNT times. - * - * Return 0 for success, positive value for corrected bitflip count, - * -EBADMSG for ecc error, other negative values for other errors - */ -static int nmbm_read_phys_page(struct nmbm_instance *ni, uint64_t addr, - void *data, void *oob) -{ - int tries, ret; - - for (tries = 0; tries < NMBM_TRY_COUNT; tries++) { - struct mtd_oob_ops ops = { - .mode = MTD_OPS_PLACE_OOB, - .oobbuf = oob, - .datbuf = data, - }; - - if (data) - ops.len = bmtd.pg_size; - if (oob) - ops.ooblen = mtd_oobavail(bmtd.mtd, &ops); - - ret = bmtd._read_oob(bmtd.mtd, addr, &ops); - if (ret == -EUCLEAN) - return min_t(u32, bmtd.mtd->bitflip_threshold + 1, - bmtd.mtd->ecc_strength); - if (ret >= 0) - return 0; - } - - if (ret != -EBADMSG) - nlog_err(ni, "Page read failed at address 0x%08llx\n", addr); - - return ret; -} - -/* - * nmbm_write_phys_page - Write page with retry - * @ni: NMBM instance structure - * @addr: linear address where the data will be written to - * @data: the main data to be written - * @oob: the oob data to be written - * - * Write a page for at most NMBM_TRY_COUNT times. - */ -static bool nmbm_write_phys_page(struct nmbm_instance *ni, uint64_t addr, - const void *data, const void *oob) -{ - int tries, ret; - - for (tries = 0; tries < NMBM_TRY_COUNT; tries++) { - struct mtd_oob_ops ops = { - .mode = MTD_OPS_PLACE_OOB, - .oobbuf = (void *)oob, - .datbuf = (void *)data, - }; - - if (data) - ops.len = bmtd.pg_size; - if (oob) - ops.ooblen = mtd_oobavail(bmtd.mtd, &ops); - - ret = bmtd._write_oob(bmtd.mtd, addr, &ops); - if (!ret) - return true; - } - - nlog_err(ni, "Page write failed at address 0x%08llx\n", addr); - - return false; -} - -/* - * nmbm_erase_phys_block - Erase a block with retry - * @ni: NMBM instance structure - * @addr: Linear address - * - * Erase a block for at most NMBM_TRY_COUNT times. - */ -static bool nmbm_erase_phys_block(struct nmbm_instance *ni, uint64_t addr) -{ - int tries, ret; - - for (tries = 0; tries < NMBM_TRY_COUNT; tries++) { - struct erase_info ei = { - .addr = addr, - .len = bmtd.mtd->erasesize, - }; - - ret = bmtd._erase(bmtd.mtd, &ei); - if (!ret) - return true; - } - - nlog_err(ni, "Block erasure failed at address 0x%08llx\n", addr); - - return false; -} - -/* - * nmbm_check_bad_phys_block - Check whether a block is marked bad in OOB - * @ni: NMBM instance structure - * @ba: block address - */ -static bool nmbm_check_bad_phys_block(struct nmbm_instance *ni, uint32_t ba) -{ - uint64_t addr = ba2addr(ni, ba); - - return bmtd._block_isbad(bmtd.mtd, addr); -} - -/* - * nmbm_mark_phys_bad_block - Mark a block bad - * @ni: NMBM instance structure - * @addr: Linear address - */ -static int nmbm_mark_phys_bad_block(struct nmbm_instance *ni, uint32_t ba) -{ - uint64_t addr = ba2addr(ni, ba); - - nlog_info(ni, "Block %u [0x%08llx] will be marked bad\n", ba, addr); - - return bmtd._block_markbad(bmtd.mtd, addr); -} - -/*****************************************************************************/ -/* NMBM related functions */ -/*****************************************************************************/ - -/* - * nmbm_check_header - Check whether a NMBM structure is valid - * @data: pointer to a NMBM structure with a NMBM header at beginning - * @size: Size of the buffer pointed by @header - * - * The size of the NMBM structure may be larger than NMBM header, - * e.g. block mapping table and block state table. - */ -static bool nmbm_check_header(const void *data, uint32_t size) -{ - const struct nmbm_header *header = data; - struct nmbm_header nhdr; - uint32_t new_checksum; - - /* - * Make sure expected structure size is equal or smaller than - * buffer size. - */ - if (header->size > size) - return false; - - memcpy(&nhdr, data, sizeof(nhdr)); - - nhdr.checksum = 0; - new_checksum = nmbm_crc32(0, &nhdr, sizeof(nhdr)); - if (header->size > sizeof(nhdr)) - new_checksum = nmbm_crc32(new_checksum, - (const uint8_t *)data + sizeof(nhdr), - header->size - sizeof(nhdr)); - - if (header->checksum != new_checksum) - return false; - - return true; -} - -/* - * nmbm_update_checksum - Update checksum of a NMBM structure - * @header: pointer to a NMBM structure with a NMBM header at beginning - * - * The size of the NMBM structure must be specified by @header->size - */ -static void nmbm_update_checksum(struct nmbm_header *header) -{ - header->checksum = 0; - header->checksum = nmbm_crc32(0, header, header->size); -} - -/* - * nmbm_get_spare_block_count - Calculate number of blocks should be reserved - * @block_count: number of blocks of data - * - * Calculate number of blocks should be reserved for data - */ -static uint32_t nmbm_get_spare_block_count(uint32_t block_count) -{ - uint32_t val; - - val = (block_count + NMBM_SPARE_BLOCK_DIV / 2) / NMBM_SPARE_BLOCK_DIV; - val *= NMBM_SPARE_BLOCK_MULTI; - - if (val < NMBM_SPARE_BLOCK_MIN) - val = NMBM_SPARE_BLOCK_MIN; - - return val; -} - -/* - * nmbm_get_block_state_raw - Get state of a block from raw block state table - * @block_state: pointer to raw block state table (bitmap) - * @ba: block address - */ -static uint32_t nmbm_get_block_state_raw(u32 *block_state, - uint32_t ba) -{ - uint32_t unit, shift; - - unit = ba / NMBM_BITMAP_BLOCKS_PER_UNIT; - shift = (ba % NMBM_BITMAP_BLOCKS_PER_UNIT) * NMBM_BITMAP_BITS_PER_BLOCK; - - return (block_state[unit] >> shift) & BLOCK_ST_MASK; -} - -/* - * nmbm_get_block_state - Get state of a block from block state table - * @ni: NMBM instance structure - * @ba: block address - */ -static uint32_t nmbm_get_block_state(struct nmbm_instance *ni, uint32_t ba) -{ - return nmbm_get_block_state_raw(ni->block_state, ba); -} - -/* - * nmbm_set_block_state - Set state of a block to block state table - * @ni: NMBM instance structure - * @ba: block address - * @state: block state - * - * Set state of a block. If the block state changed, ni->block_state_changed - * will be increased. - */ -static bool nmbm_set_block_state(struct nmbm_instance *ni, uint32_t ba, - uint32_t state) -{ - uint32_t unit, shift, orig; - u32 uv; - - unit = ba / NMBM_BITMAP_BLOCKS_PER_UNIT; - shift = (ba % NMBM_BITMAP_BLOCKS_PER_UNIT) * NMBM_BITMAP_BITS_PER_BLOCK; - - orig = (ni->block_state[unit] >> shift) & BLOCK_ST_MASK; - state &= BLOCK_ST_MASK; - - uv = ni->block_state[unit] & (~(BLOCK_ST_MASK << shift)); - uv |= state << shift; - ni->block_state[unit] = uv; - - if (orig != state) { - ni->block_state_changed++; - return true; - } - - return false; -} - -/* - * nmbm_block_walk_asc - Skip specified number of good blocks, ascending addr. - * @ni: NMBM instance structure - * @ba: start physical block address - * @nba: return physical block address after walk - * @count: number of good blocks to be skipped - * @limit: highest block address allowed for walking - * - * Start from @ba, skipping any bad blocks, counting @count good blocks, and - * return the next good block address. - * - * If no enough good blocks counted while @limit reached, false will be returned. - * - * If @count == 0, nearest good block address will be returned. - * @limit is not counted in walking. - */ -static bool nmbm_block_walk_asc(struct nmbm_instance *ni, uint32_t ba, - uint32_t *nba, uint32_t count, - uint32_t limit) -{ - int32_t nblock = count; - - if (limit >= ni->block_count) - limit = ni->block_count - 1; - - while (ba < limit) { - if (nmbm_get_block_state(ni, ba) == BLOCK_ST_GOOD) - nblock--; - - if (nblock < 0) { - *nba = ba; - return true; - } - - ba++; - } - - return false; -} - -/* - * nmbm_block_walk_desc - Skip specified number of good blocks, descending addr - * @ni: NMBM instance structure - * @ba: start physical block address - * @nba: return physical block address after walk - * @count: number of good blocks to be skipped - * @limit: lowest block address allowed for walking - * - * Start from @ba, skipping any bad blocks, counting @count good blocks, and - * return the next good block address. - * - * If no enough good blocks counted while @limit reached, false will be returned. - * - * If @count == 0, nearest good block address will be returned. - * @limit is not counted in walking. - */ -static bool nmbm_block_walk_desc(struct nmbm_instance *ni, uint32_t ba, - uint32_t *nba, uint32_t count, uint32_t limit) -{ - int32_t nblock = count; - - if (limit >= ni->block_count) - limit = ni->block_count - 1; - - while (ba > limit) { - if (nmbm_get_block_state(ni, ba) == BLOCK_ST_GOOD) - nblock--; - - if (nblock < 0) { - *nba = ba; - return true; - } - - ba--; - } - - return false; -} - -/* - * nmbm_block_walk - Skip specified number of good blocks from curr. block addr - * @ni: NMBM instance structure - * @ascending: whether to walk ascending - * @ba: start physical block address - * @nba: return physical block address after walk - * @count: number of good blocks to be skipped - * @limit: highest/lowest block address allowed for walking - * - * Start from @ba, skipping any bad blocks, counting @count good blocks, and - * return the next good block address. - * - * If no enough good blocks counted while @limit reached, false will be returned. - * - * If @count == 0, nearest good block address will be returned. - * @limit can be set to negative if no limit required. - * @limit is not counted in walking. - */ -static bool nmbm_block_walk(struct nmbm_instance *ni, bool ascending, - uint32_t ba, uint32_t *nba, int32_t count, - int32_t limit) -{ - if (ascending) - return nmbm_block_walk_asc(ni, ba, nba, count, limit); - - return nmbm_block_walk_desc(ni, ba, nba, count, limit); -} - -/* - * nmbm_scan_badblocks - Scan and record all bad blocks - * @ni: NMBM instance structure - * - * Scan the entire lower NAND chip and record all bad blocks in to block state - * table. - */ -static void nmbm_scan_badblocks(struct nmbm_instance *ni) -{ - uint32_t ba; - - for (ba = 0; ba < ni->block_count; ba++) { - if (nmbm_check_bad_phys_block(ni, ba)) { - nmbm_set_block_state(ni, ba, BLOCK_ST_BAD); - nlog_info(ni, "Bad block %u [0x%08llx]\n", ba, - ba2addr(ni, ba)); - } - } -} - -/* - * nmbm_build_mapping_table - Build initial block mapping table - * @ni: NMBM instance structure - * - * The initial mapping table will be compatible with the stratage of - * factory production. - */ -static void nmbm_build_mapping_table(struct nmbm_instance *ni) -{ - uint32_t pb, lb; - - for (pb = 0, lb = 0; pb < ni->mgmt_start_ba; pb++) { - if (nmbm_get_block_state(ni, pb) == BLOCK_ST_BAD) - continue; - - /* Always map to the next good block */ - ni->block_mapping[lb++] = pb; - } - - ni->data_block_count = lb; - - /* Unusable/Management blocks */ - for (pb = lb; pb < ni->block_count; pb++) - ni->block_mapping[pb] = -1; -} - -/* - * nmbm_erase_block_and_check - Erase a block and check its usability - * @ni: NMBM instance structure - * @ba: block address to be erased - * - * Erase a block anc check its usability - * - * Return true if the block is usable, false if erasure failure or the block - * has too many bitflips. - */ -static bool nmbm_erase_block_and_check(struct nmbm_instance *ni, uint32_t ba) -{ - uint64_t addr, off; - bool success; - int ret; - - success = nmbm_erase_phys_block(ni, ba2addr(ni, ba)); - if (!success) - return false; - - if (!ni->empty_page_ecc_ok) - return true; - - /* Check every page to make sure there aren't too many bitflips */ - - addr = ba2addr(ni, ba); - - for (off = 0; off < bmtd.blk_size; off += bmtd.pg_size) { - ret = nmbm_read_phys_page(ni, addr + off, ni->page_cache, NULL); - if (ret == -EBADMSG) { - /* - * empty_page_ecc_ok means the empty page is - * still protected by ECC. So reading pages with ECC - * enabled and -EBADMSG means there are too many - * bitflips that can't be recovered, and the block - * containing the page should be marked bad. - */ - nlog_err(ni, - "Too many bitflips in empty page at 0x%llx\n", - addr + off); - return false; - } - } - - return true; -} - -/* - * nmbm_erase_range - Erase a range of blocks - * @ni: NMBM instance structure - * @ba: block address where the erasure will start - * @limit: top block address allowed for erasure - * - * Erase blocks within the specific range. Newly-found bad blocks will be - * marked. - * - * @limit is not counted into the allowed erasure address. - */ -static void nmbm_erase_range(struct nmbm_instance *ni, uint32_t ba, - uint32_t limit) -{ - bool success; - - while (ba < limit) { - if (nmbm_get_block_state(ni, ba) != BLOCK_ST_GOOD) - goto next_block; - - /* Insurance to detect unexpected bad block marked by user */ - if (nmbm_check_bad_phys_block(ni, ba)) { - nmbm_set_block_state(ni, ba, BLOCK_ST_BAD); - goto next_block; - } - - success = nmbm_erase_block_and_check(ni, ba); - if (success) - goto next_block; - - nmbm_mark_phys_bad_block(ni, ba); - nmbm_set_block_state(ni, ba, BLOCK_ST_BAD); - - next_block: - ba++; - } -} - -/* - * nmbm_write_repeated_data - Write critical data to a block with retry - * @ni: NMBM instance structure - * @ba: block address where the data will be written to - * @data: the data to be written - * @size: size of the data - * - * Write data to every page of the block. Success only if all pages within - * this block have been successfully written. - * - * Make sure data size is not bigger than one page. - * - * This function will write and verify every page for at most - * NMBM_TRY_COUNT times. - */ -static bool nmbm_write_repeated_data(struct nmbm_instance *ni, uint32_t ba, - const void *data, uint32_t size) -{ - uint64_t addr, off; - bool success; - int ret; - - if (size > bmtd.pg_size) - return false; - - addr = ba2addr(ni, ba); - - for (off = 0; off < bmtd.blk_size; off += bmtd.pg_size) { - /* Prepare page data. fill 0xff to unused region */ - memcpy(ni->page_cache, data, size); - memset(ni->page_cache + size, 0xff, ni->rawpage_size - size); - - success = nmbm_write_phys_page(ni, addr + off, ni->page_cache, NULL); - if (!success) - return false; - - /* Verify the data just written. ECC error indicates failure */ - ret = nmbm_read_phys_page(ni, addr + off, ni->page_cache, NULL); - if (ret < 0) - return false; - - if (memcmp(ni->page_cache, data, size)) - return false; - } - - return true; -} - -/* - * nmbm_write_signature - Write signature to NAND chip - * @ni: NMBM instance structure - * @limit: top block address allowed for writing - * @signature: the signature to be written - * @signature_ba: the actual block address where signature is written to - * - * Write signature within a specific range, from chip bottom to limit. - * At most one block will be written. - * - * @limit is not counted into the allowed write address. - */ -static bool nmbm_write_signature(struct nmbm_instance *ni, uint32_t limit, - const struct nmbm_signature *signature, - uint32_t *signature_ba) -{ - uint32_t ba = ni->block_count - 1; - bool success; - - while (ba > limit) { - if (nmbm_get_block_state(ni, ba) != BLOCK_ST_GOOD) - goto next_block; - - /* Insurance to detect unexpected bad block marked by user */ - if (nmbm_check_bad_phys_block(ni, ba)) { - nmbm_set_block_state(ni, ba, BLOCK_ST_BAD); - goto next_block; - } - - success = nmbm_erase_block_and_check(ni, ba); - if (!success) - goto skip_bad_block; - - success = nmbm_write_repeated_data(ni, ba, signature, - sizeof(*signature)); - if (success) { - *signature_ba = ba; - return true; - } - - skip_bad_block: - nmbm_mark_phys_bad_block(ni, ba); - nmbm_set_block_state(ni, ba, BLOCK_ST_BAD); - - next_block: - ba--; - }; - - return false; -} - -/* - * nmbn_read_data - Read data - * @ni: NMBM instance structure - * @addr: linear address where the data will be read from - * @data: the data to be read - * @size: the size of data - * - * Read data range. - * Every page will be tried for at most NMBM_TRY_COUNT times. - * - * Return 0 for success, positive value for corrected bitflip count, - * -EBADMSG for ecc error, other negative values for other errors - */ -static int nmbn_read_data(struct nmbm_instance *ni, uint64_t addr, void *data, - uint32_t size) -{ - uint64_t off = addr; - uint8_t *ptr = data; - uint32_t sizeremain = size, chunksize, leading; - int ret; - - while (sizeremain) { - leading = off & (bmtd.pg_size - 1); - chunksize = bmtd.pg_size - leading; - if (chunksize > sizeremain) - chunksize = sizeremain; - - if (chunksize == bmtd.pg_size) { - ret = nmbm_read_phys_page(ni, off - leading, ptr, NULL); - if (ret < 0) - return ret; - } else { - ret = nmbm_read_phys_page(ni, off - leading, - ni->page_cache, NULL); - if (ret < 0) - return ret; - - memcpy(ptr, ni->page_cache + leading, chunksize); - } - - off += chunksize; - ptr += chunksize; - sizeremain -= chunksize; - } - - return 0; -} - -/* - * nmbn_write_verify_data - Write data with validation - * @ni: NMBM instance structure - * @addr: linear address where the data will be written to - * @data: the data to be written - * @size: the size of data - * - * Write data and verify. - * Every page will be tried for at most NMBM_TRY_COUNT times. - */ -static bool nmbn_write_verify_data(struct nmbm_instance *ni, uint64_t addr, - const void *data, uint32_t size) -{ - uint64_t off = addr; - const uint8_t *ptr = data; - uint32_t sizeremain = size, chunksize, leading; - bool success; - int ret; - - while (sizeremain) { - leading = off & (bmtd.pg_size - 1); - chunksize = bmtd.pg_size - leading; - if (chunksize > sizeremain) - chunksize = sizeremain; - - /* Prepare page data. fill 0xff to unused region */ - memset(ni->page_cache, 0xff, ni->rawpage_size); - memcpy(ni->page_cache + leading, ptr, chunksize); - - success = nmbm_write_phys_page(ni, off - leading, - ni->page_cache, NULL); - if (!success) - return false; - - /* Verify the data just written. ECC error indicates failure */ - ret = nmbm_read_phys_page(ni, off - leading, ni->page_cache, NULL); - if (ret < 0) - return false; - - if (memcmp(ni->page_cache + leading, ptr, chunksize)) - return false; - - off += chunksize; - ptr += chunksize; - sizeremain -= chunksize; - } - - return true; -} - -/* - * nmbm_write_mgmt_range - Write management data into NAND within a range - * @ni: NMBM instance structure - * @addr: preferred start block address for writing - * @limit: highest block address allowed for writing - * @data: the data to be written - * @size: the size of data - * @actual_start_ba: actual start block address of data - * @actual_end_ba: block address after the end of data - * - * @limit is not counted into the allowed write address. - */ -static bool nmbm_write_mgmt_range(struct nmbm_instance *ni, uint32_t ba, - uint32_t limit, const void *data, - uint32_t size, uint32_t *actual_start_ba, - uint32_t *actual_end_ba) -{ - const uint8_t *ptr = data; - uint32_t sizeremain = size, chunksize; - bool success; - - while (sizeremain && ba < limit) { - chunksize = sizeremain; - if (chunksize > bmtd.blk_size) - chunksize = bmtd.blk_size; - - if (nmbm_get_block_state(ni, ba) != BLOCK_ST_GOOD) - goto next_block; - - /* Insurance to detect unexpected bad block marked by user */ - if (nmbm_check_bad_phys_block(ni, ba)) { - nmbm_set_block_state(ni, ba, BLOCK_ST_BAD); - goto next_block; - } - - success = nmbm_erase_block_and_check(ni, ba); - if (!success) - goto skip_bad_block; - - success = nmbn_write_verify_data(ni, ba2addr(ni, ba), ptr, - chunksize); - if (!success) - goto skip_bad_block; - - if (sizeremain == size) - *actual_start_ba = ba; - - ptr += chunksize; - sizeremain -= chunksize; - - goto next_block; - - skip_bad_block: - nmbm_mark_phys_bad_block(ni, ba); - nmbm_set_block_state(ni, ba, BLOCK_ST_BAD); - - next_block: - ba++; - } - - if (sizeremain) - return false; - - *actual_end_ba = ba; - - return true; -} - -/* - * nmbm_generate_info_table_cache - Generate info table cache data - * @ni: NMBM instance structure - * - * Generate info table cache data to be written into flash. - */ -static bool nmbm_generate_info_table_cache(struct nmbm_instance *ni) -{ - bool changed = false; - - memset(ni->info_table_cache, 0xff, ni->info_table_size); - - memcpy(ni->info_table_cache + ni->info_table.state_table_off, - ni->block_state, ni->state_table_size); - - memcpy(ni->info_table_cache + ni->info_table.mapping_table_off, - ni->block_mapping, ni->mapping_table_size); - - ni->info_table.header.magic = NMBM_MAGIC_INFO_TABLE; - ni->info_table.header.version = NMBM_VER; - ni->info_table.header.size = ni->info_table_size; - - if (ni->block_state_changed || ni->block_mapping_changed) { - ni->info_table.write_count++; - changed = true; - } - - memcpy(ni->info_table_cache, &ni->info_table, sizeof(ni->info_table)); - - nmbm_update_checksum((struct nmbm_header *)ni->info_table_cache); - - return changed; -} - -/* - * nmbm_write_info_table - Write info table into NAND within a range - * @ni: NMBM instance structure - * @ba: preferred start block address for writing - * @limit: highest block address allowed for writing - * @actual_start_ba: actual start block address of info table - * @actual_end_ba: block address after the end of info table - * - * @limit is counted into the allowed write address. - */ -static bool nmbm_write_info_table(struct nmbm_instance *ni, uint32_t ba, - uint32_t limit, uint32_t *actual_start_ba, - uint32_t *actual_end_ba) -{ - return nmbm_write_mgmt_range(ni, ba, limit, ni->info_table_cache, - ni->info_table_size, actual_start_ba, - actual_end_ba); -} - -/* - * nmbm_mark_tables_clean - Mark info table `clean' - * @ni: NMBM instance structure - */ -static void nmbm_mark_tables_clean(struct nmbm_instance *ni) -{ - ni->block_state_changed = 0; - ni->block_mapping_changed = 0; -} - -/* - * nmbm_try_reserve_blocks - Reserve blocks with compromisation - * @ni: NMBM instance structure - * @ba: start physical block address - * @nba: return physical block address after reservation - * @count: number of good blocks to be skipped - * @min_count: minimum number of good blocks to be skipped - * @limit: highest/lowest block address allowed for walking - * - * Reserve specific blocks. If failed, try to reserve as many as possible. - */ -static bool nmbm_try_reserve_blocks(struct nmbm_instance *ni, uint32_t ba, - uint32_t *nba, uint32_t count, - int32_t min_count, int32_t limit) -{ - int32_t nblocks = count; - bool success; - - while (nblocks >= min_count) { - success = nmbm_block_walk(ni, true, ba, nba, nblocks, limit); - if (success) - return true; - - nblocks--; - } - - return false; -} - -/* - * nmbm_rebuild_info_table - Build main & backup info table from scratch - * @ni: NMBM instance structure - * @allow_no_gap: allow no spare blocks between two tables - */ -static bool nmbm_rebuild_info_table(struct nmbm_instance *ni) -{ - uint32_t table_start_ba, table_end_ba, next_start_ba; - uint32_t main_table_end_ba; - bool success; - - /* Set initial value */ - ni->main_table_ba = 0; - ni->backup_table_ba = 0; - ni->mapping_blocks_ba = ni->mapping_blocks_top_ba; - - /* Write main table */ - success = nmbm_write_info_table(ni, ni->mgmt_start_ba, - ni->mapping_blocks_top_ba, - &table_start_ba, &table_end_ba); - if (!success) { - /* Failed to write main table, data will be lost */ - nlog_err(ni, "Unable to write at least one info table!\n"); - nlog_err(ni, "Please save your data before power off!\n"); - ni->protected = 1; - return false; - } - - /* Main info table is successfully written, record its offset */ - ni->main_table_ba = table_start_ba; - main_table_end_ba = table_end_ba; - - /* Adjust mapping_blocks_ba */ - ni->mapping_blocks_ba = table_end_ba; - - nmbm_mark_tables_clean(ni); - - nlog_table_creation(ni, true, table_start_ba, table_end_ba); - - /* Reserve spare blocks for main info table. */ - success = nmbm_try_reserve_blocks(ni, table_end_ba, - &next_start_ba, - ni->info_table_spare_blocks, 0, - ni->mapping_blocks_top_ba - - size2blk(ni, ni->info_table_size)); - if (!success) { - /* There is no spare block. */ - nlog_debug(ni, "No room for backup info table\n"); - return true; - } - - /* Write backup info table. */ - success = nmbm_write_info_table(ni, next_start_ba, - ni->mapping_blocks_top_ba, - &table_start_ba, &table_end_ba); - if (!success) { - /* There is no enough blocks for backup table. */ - nlog_debug(ni, "No room for backup info table\n"); - return true; - } - - /* Backup table is successfully written, record its offset */ - ni->backup_table_ba = table_start_ba; - - /* Adjust mapping_blocks_off */ - ni->mapping_blocks_ba = table_end_ba; - - /* Erase spare blocks of main table to clean possible interference data */ - nmbm_erase_range(ni, main_table_end_ba, ni->backup_table_ba); - - nlog_table_creation(ni, false, table_start_ba, table_end_ba); - - return true; -} - -/* - * nmbm_rescue_single_info_table - Rescue when there is only one info table - * @ni: NMBM instance structure - * - * This function is called when there is only one info table exists. - * This function may fail if we can't write new info table - */ -static bool nmbm_rescue_single_info_table(struct nmbm_instance *ni) -{ - uint32_t table_start_ba, table_end_ba, write_ba; - bool success; - - /* Try to write new info table in front of existing table */ - success = nmbm_write_info_table(ni, ni->mgmt_start_ba, - ni->main_table_ba, - &table_start_ba, - &table_end_ba); - if (success) { - /* - * New table becomes the main table, existing table becomes - * the backup table. - */ - ni->backup_table_ba = ni->main_table_ba; - ni->main_table_ba = table_start_ba; - - nmbm_mark_tables_clean(ni); - - /* Erase spare blocks of main table to clean possible interference data */ - nmbm_erase_range(ni, table_end_ba, ni->backup_table_ba); - - nlog_table_creation(ni, true, table_start_ba, table_end_ba); - - return true; - } - - /* Try to reserve spare blocks for existing table */ - success = nmbm_try_reserve_blocks(ni, ni->mapping_blocks_ba, &write_ba, - ni->info_table_spare_blocks, 0, - ni->mapping_blocks_top_ba - - size2blk(ni, ni->info_table_size)); - if (!success) { - nlog_warn(ni, "Failed to rescue single info table\n"); - return false; - } - - /* Try to write new info table next to the existing table */ - while (write_ba >= ni->mapping_blocks_ba) { - success = nmbm_write_info_table(ni, write_ba, - ni->mapping_blocks_top_ba, - &table_start_ba, - &table_end_ba); - if (success) - break; - - write_ba--; - } - - if (success) { - /* Erase spare blocks of main table to clean possible interference data */ - nmbm_erase_range(ni, ni->mapping_blocks_ba, table_start_ba); - - /* New table becomes the backup table */ - ni->backup_table_ba = table_start_ba; - ni->mapping_blocks_ba = table_end_ba; - - nmbm_mark_tables_clean(ni); - - nlog_table_creation(ni, false, table_start_ba, table_end_ba); - - return true; - } - - nlog_warn(ni, "Failed to rescue single info table\n"); - return false; -} - -/* - * nmbm_update_single_info_table - Update specific one info table - * @ni: NMBM instance structure - */ -static bool nmbm_update_single_info_table(struct nmbm_instance *ni, - bool update_main_table) -{ - uint32_t write_start_ba, write_limit, table_start_ba, table_end_ba; - bool success; - - /* Determine the write range */ - if (update_main_table) { - write_start_ba = ni->main_table_ba; - write_limit = ni->backup_table_ba; - } else { - write_start_ba = ni->backup_table_ba; - write_limit = ni->mapping_blocks_top_ba; - } - - success = nmbm_write_info_table(ni, write_start_ba, write_limit, - &table_start_ba, &table_end_ba); - if (success) { - if (update_main_table) { - ni->main_table_ba = table_start_ba; - } else { - ni->backup_table_ba = table_start_ba; - ni->mapping_blocks_ba = table_end_ba; - } - - nmbm_mark_tables_clean(ni); - - nlog_table_update(ni, update_main_table, table_start_ba, - table_end_ba); - - return true; - } - - if (update_main_table) { - /* - * If failed to update main table, make backup table the new - * main table, and call nmbm_rescue_single_info_table() - */ - nlog_warn(ni, "Unable to update %s info table\n", - update_main_table ? "Main" : "Backup"); - - ni->main_table_ba = ni->backup_table_ba; - ni->backup_table_ba = 0; - return nmbm_rescue_single_info_table(ni); - } - - /* Only one table left */ - ni->mapping_blocks_ba = ni->backup_table_ba; - ni->backup_table_ba = 0; - - return false; -} - -/* - * nmbm_rescue_main_info_table - Rescue when failed to write main info table - * @ni: NMBM instance structure - * - * This function is called when main info table failed to be written, and - * backup info table exists. - */ -static bool nmbm_rescue_main_info_table(struct nmbm_instance *ni) -{ - uint32_t tmp_table_start_ba, tmp_table_end_ba, main_table_start_ba; - uint32_t main_table_end_ba, write_ba; - uint32_t info_table_erasesize = size2blk(ni, ni->info_table_size); - bool success; - - /* Try to reserve spare blocks for existing backup info table */ - success = nmbm_try_reserve_blocks(ni, ni->mapping_blocks_ba, &write_ba, - ni->info_table_spare_blocks, 0, - ni->mapping_blocks_top_ba - - info_table_erasesize); - if (!success) { - /* There is no spare block. Backup info table becomes the main table. */ - nlog_err(ni, "No room for temporary info table\n"); - ni->main_table_ba = ni->backup_table_ba; - ni->backup_table_ba = 0; - return true; - } - - /* Try to write temporary info table into spare unmapped blocks */ - while (write_ba >= ni->mapping_blocks_ba) { - success = nmbm_write_info_table(ni, write_ba, - ni->mapping_blocks_top_ba, - &tmp_table_start_ba, - &tmp_table_end_ba); - if (success) - break; - - write_ba--; - } - - if (!success) { - /* Backup info table becomes the main table */ - nlog_err(ni, "Failed to update main info table\n"); - ni->main_table_ba = ni->backup_table_ba; - ni->backup_table_ba = 0; - return true; - } - - /* Adjust mapping_blocks_off */ - ni->mapping_blocks_ba = tmp_table_end_ba; - - /* - * Now write main info table at the beginning of management area. - * This operation will generally destroy the original backup info - * table. - */ - success = nmbm_write_info_table(ni, ni->mgmt_start_ba, - tmp_table_start_ba, - &main_table_start_ba, - &main_table_end_ba); - if (!success) { - /* Temporary info table becomes the main table */ - ni->main_table_ba = tmp_table_start_ba; - ni->backup_table_ba = 0; - - nmbm_mark_tables_clean(ni); - - nlog_err(ni, "Failed to update main info table\n"); - - return true; - } - - /* Main info table has been successfully written, record its offset */ - ni->main_table_ba = main_table_start_ba; - - nmbm_mark_tables_clean(ni); - - nlog_table_creation(ni, true, main_table_start_ba, main_table_end_ba); - - /* - * Temporary info table becomes the new backup info table if it's - * not overwritten. - */ - if (main_table_end_ba <= tmp_table_start_ba) { - ni->backup_table_ba = tmp_table_start_ba; - - nlog_table_creation(ni, false, tmp_table_start_ba, - tmp_table_end_ba); - - return true; - } - - /* Adjust mapping_blocks_off */ - ni->mapping_blocks_ba = main_table_end_ba; - - /* Try to reserve spare blocks for new main info table */ - success = nmbm_try_reserve_blocks(ni, main_table_end_ba, &write_ba, - ni->info_table_spare_blocks, 0, - ni->mapping_blocks_top_ba - - info_table_erasesize); - if (!success) { - /* There is no spare block. Only main table exists. */ - nlog_err(ni, "No room for backup info table\n"); - ni->backup_table_ba = 0; - return true; - } - - /* Write new backup info table. */ - while (write_ba >= main_table_end_ba) { - success = nmbm_write_info_table(ni, write_ba, - ni->mapping_blocks_top_ba, - &tmp_table_start_ba, - &tmp_table_end_ba); - if (success) - break; - - write_ba--; - } - - if (!success) { - nlog_err(ni, "No room for backup info table\n"); - ni->backup_table_ba = 0; - return true; - } - - /* Backup info table has been successfully written, record its offset */ - ni->backup_table_ba = tmp_table_start_ba; - - /* Adjust mapping_blocks_off */ - ni->mapping_blocks_ba = tmp_table_end_ba; - - /* Erase spare blocks of main table to clean possible interference data */ - nmbm_erase_range(ni, main_table_end_ba, ni->backup_table_ba); - - nlog_table_creation(ni, false, tmp_table_start_ba, tmp_table_end_ba); - - return true; -} - -/* - * nmbm_update_info_table_once - Update info table once - * @ni: NMBM instance structure - * @force: force update - * - * Update both main and backup info table. Return true if at least one info - * table has been successfully written. - * This function only try to update info table once regard less of the result. - */ -static bool nmbm_update_info_table_once(struct nmbm_instance *ni, bool force) -{ - uint32_t table_start_ba, table_end_ba; - uint32_t main_table_limit; - bool success; - - /* Do nothing if there is no change */ - if (!nmbm_generate_info_table_cache(ni) && !force) - return true; - - /* Check whether both two tables exist */ - if (!ni->backup_table_ba) { - main_table_limit = ni->mapping_blocks_top_ba; - goto write_main_table; - } - - /* - * Write backup info table in its current range. - * Note that limit is set to mapping_blocks_top_off to provide as many - * spare blocks as possible for the backup table. If at last - * unmapped blocks are used by backup table, mapping_blocks_off will - * be adjusted. - */ - success = nmbm_write_info_table(ni, ni->backup_table_ba, - ni->mapping_blocks_top_ba, - &table_start_ba, &table_end_ba); - if (!success) { - /* - * There is nothing to do if failed to write backup table. - * Write the main table now. - */ - nlog_err(ni, "No room for backup table\n"); - ni->mapping_blocks_ba = ni->backup_table_ba; - ni->backup_table_ba = 0; - main_table_limit = ni->mapping_blocks_top_ba; - goto write_main_table; - } - - /* Backup table is successfully written, record its offset */ - ni->backup_table_ba = table_start_ba; - - /* Adjust mapping_blocks_off */ - ni->mapping_blocks_ba = table_end_ba; - - nmbm_mark_tables_clean(ni); - - /* The normal limit of main table */ - main_table_limit = ni->backup_table_ba; - - nlog_table_update(ni, false, table_start_ba, table_end_ba); - -write_main_table: - if (!ni->main_table_ba) - goto rebuild_tables; - - /* Write main info table in its current range */ - success = nmbm_write_info_table(ni, ni->main_table_ba, - main_table_limit, &table_start_ba, - &table_end_ba); - if (!success) { - /* If failed to write main table, go rescue procedure */ - if (!ni->backup_table_ba) - goto rebuild_tables; - - return nmbm_rescue_main_info_table(ni); - } - - /* Main info table is successfully written, record its offset */ - ni->main_table_ba = table_start_ba; - - /* Adjust mapping_blocks_off */ - if (!ni->backup_table_ba) - ni->mapping_blocks_ba = table_end_ba; - - nmbm_mark_tables_clean(ni); - - nlog_table_update(ni, true, table_start_ba, table_end_ba); - - return true; - -rebuild_tables: - return nmbm_rebuild_info_table(ni); -} - -/* - * nmbm_update_info_table - Update info table - * @ni: NMBM instance structure - * - * Update both main and backup info table. Return true if at least one table - * has been successfully written. - * This function will try to update info table repeatedly until no new bad - * block found during updating. - */ -static bool nmbm_update_info_table(struct nmbm_instance *ni) -{ - bool success; - - if (ni->protected) - return true; - - while (ni->block_state_changed || ni->block_mapping_changed) { - success = nmbm_update_info_table_once(ni, false); - if (!success) { - nlog_err(ni, "Failed to update info table\n"); - return false; - } - } - - return true; -} - -/* - * nmbm_map_block - Map a bad block to a unused spare block - * @ni: NMBM instance structure - * @lb: logic block addr to map - */ -static bool nmbm_map_block(struct nmbm_instance *ni, uint32_t lb) -{ - uint32_t pb; - bool success; - - if (ni->mapping_blocks_ba == ni->mapping_blocks_top_ba) { - nlog_warn(ni, "No spare unmapped blocks.\n"); - return false; - } - - success = nmbm_block_walk(ni, false, ni->mapping_blocks_top_ba, &pb, 0, - ni->mapping_blocks_ba); - if (!success) { - nlog_warn(ni, "No spare unmapped blocks.\n"); - nmbm_update_info_table(ni); - ni->mapping_blocks_top_ba = ni->mapping_blocks_ba; - return false; - } - - ni->block_mapping[lb] = pb; - ni->mapping_blocks_top_ba--; - ni->block_mapping_changed++; - - nlog_info(ni, "Logic block %u mapped to physical block %u\n", lb, pb); - - return true; -} - -/* - * nmbm_create_info_table - Create info table(s) - * @ni: NMBM instance structure - * - * This function assumes that the chip has no existing info table(s) - */ -static bool nmbm_create_info_table(struct nmbm_instance *ni) -{ - uint32_t lb; - bool success; - - /* Set initial mapping_blocks_top_off */ - success = nmbm_block_walk(ni, false, ni->signature_ba, - &ni->mapping_blocks_top_ba, 1, - ni->mgmt_start_ba); - if (!success) { - nlog_err(ni, "No room for spare blocks\n"); - return false; - } - - /* Generate info table cache */ - nmbm_generate_info_table_cache(ni); - - /* Write info table */ - success = nmbm_rebuild_info_table(ni); - if (!success) { - nlog_err(ni, "Failed to build info tables\n"); - return false; - } - - /* Remap bad block(s) at end of data area */ - for (lb = ni->data_block_count; lb < ni->mgmt_start_ba; lb++) { - success = nmbm_map_block(ni, lb); - if (!success) - break; - - ni->data_block_count++; - } - - /* If state table and/or mapping table changed, update info table. */ - success = nmbm_update_info_table(ni); - if (!success) - return false; - - return true; -} - -/* - * nmbm_create_new - Create NMBM on a new chip - * @ni: NMBM instance structure - */ -static bool nmbm_create_new(struct nmbm_instance *ni) -{ - bool success; - - /* Determine the boundary of management blocks */ - ni->mgmt_start_ba = ni->block_count * (NMBM_MGMT_DIV - ni->max_ratio) / NMBM_MGMT_DIV; - - if (ni->max_reserved_blocks && ni->block_count - ni->mgmt_start_ba > ni->max_reserved_blocks) - ni->mgmt_start_ba = ni->block_count - ni->max_reserved_blocks; - - nlog_info(ni, "NMBM management region starts at block %u [0x%08llx]\n", - ni->mgmt_start_ba, ba2addr(ni, ni->mgmt_start_ba)); - - /* Fill block state table & mapping table */ - nmbm_scan_badblocks(ni); - nmbm_build_mapping_table(ni); - - /* Write signature */ - ni->signature.header.magic = NMBM_MAGIC_SIGNATURE; - ni->signature.header.version = NMBM_VER; - ni->signature.header.size = sizeof(ni->signature); - ni->signature.nand_size = bmtd.total_blks << bmtd.blk_shift; - ni->signature.block_size = bmtd.blk_size; - ni->signature.page_size = bmtd.pg_size; - ni->signature.spare_size = bmtd.mtd->oobsize; - ni->signature.mgmt_start_pb = ni->mgmt_start_ba; - ni->signature.max_try_count = NMBM_TRY_COUNT; - nmbm_update_checksum(&ni->signature.header); - - success = nmbm_write_signature(ni, ni->mgmt_start_ba, - &ni->signature, &ni->signature_ba); - if (!success) { - nlog_err(ni, "Failed to write signature to a proper offset\n"); - return false; - } - - nlog_info(ni, "Signature has been written to block %u [0x%08llx]\n", - ni->signature_ba, ba2addr(ni, ni->signature_ba)); - - /* Write info table(s) */ - success = nmbm_create_info_table(ni); - if (success) { - nlog_info(ni, "NMBM has been successfully created\n"); - return true; - } - - return false; -} - -/* - * nmbm_check_info_table_header - Check if a info table header is valid - * @ni: NMBM instance structure - * @data: pointer to the info table header - */ -static bool nmbm_check_info_table_header(struct nmbm_instance *ni, void *data) -{ - struct nmbm_info_table_header *ifthdr = data; - - if (ifthdr->header.magic != NMBM_MAGIC_INFO_TABLE) - return false; - - if (ifthdr->header.size != ni->info_table_size) - return false; - - if (ifthdr->mapping_table_off - ifthdr->state_table_off < ni->state_table_size) - return false; - - if (ni->info_table_size - ifthdr->mapping_table_off < ni->mapping_table_size) - return false; - - return true; -} - -/* - * nmbm_check_info_table - Check if a whole info table is valid - * @ni: NMBM instance structure - * @start_ba: start block address of this table - * @end_ba: end block address of this table - * @data: pointer to the info table header - * @mapping_blocks_top_ba: return the block address of top remapped block - */ -static bool nmbm_check_info_table(struct nmbm_instance *ni, uint32_t start_ba, - uint32_t end_ba, void *data, - uint32_t *mapping_blocks_top_ba) -{ - struct nmbm_info_table_header *ifthdr = data; - int32_t *block_mapping = (int32_t *)((uintptr_t)data + ifthdr->mapping_table_off); - u32 *block_state = (u32 *)((uintptr_t)data + ifthdr->state_table_off); - uint32_t minimum_mapping_pb = ni->signature_ba; - uint32_t ba; - - for (ba = 0; ba < ni->data_block_count; ba++) { - if ((block_mapping[ba] >= ni->data_block_count && block_mapping[ba] < end_ba) || - block_mapping[ba] == ni->signature_ba) - return false; - - if (block_mapping[ba] >= end_ba && block_mapping[ba] < minimum_mapping_pb) - minimum_mapping_pb = block_mapping[ba]; - } - - for (ba = start_ba; ba < end_ba; ba++) { - if (nmbm_get_block_state(ni, ba) != BLOCK_ST_GOOD) - continue; - - if (nmbm_get_block_state_raw(block_state, ba) != BLOCK_ST_GOOD) - return false; - } - - *mapping_blocks_top_ba = minimum_mapping_pb - 1; - - return true; -} - -/* - * nmbm_try_load_info_table - Try to load info table from a address - * @ni: NMBM instance structure - * @ba: start block address of the info table - * @eba: return the block address after end of the table - * @write_count: return the write count of this table - * @mapping_blocks_top_ba: return the block address of top remapped block - * @table_loaded: used to record whether ni->info_table has valid data - */ -static bool nmbm_try_load_info_table(struct nmbm_instance *ni, uint32_t ba, - uint32_t *eba, uint32_t *write_count, - uint32_t *mapping_blocks_top_ba, - bool table_loaded) -{ - struct nmbm_info_table_header *ifthdr = (void *)ni->info_table_cache; - uint8_t *off = ni->info_table_cache; - uint32_t limit = ba + size2blk(ni, ni->info_table_size); - uint32_t start_ba = 0, chunksize, sizeremain = ni->info_table_size; - bool success, checkhdr = true; - int ret; - - while (sizeremain && ba < limit) { - if (nmbm_get_block_state(ni, ba) != BLOCK_ST_GOOD) - goto next_block; - - if (nmbm_check_bad_phys_block(ni, ba)) { - nmbm_set_block_state(ni, ba, BLOCK_ST_BAD); - goto next_block; - } - - chunksize = sizeremain; - if (chunksize > bmtd.blk_size) - chunksize = bmtd.blk_size; - - /* Assume block with ECC error has no info table data */ - ret = nmbn_read_data(ni, ba2addr(ni, ba), off, chunksize); - if (ret < 0) - goto skip_bad_block; - else if (ret > 0) - return false; - - if (checkhdr) { - success = nmbm_check_info_table_header(ni, off); - if (!success) - return false; - - start_ba = ba; - checkhdr = false; - } - - off += chunksize; - sizeremain -= chunksize; - - goto next_block; - - skip_bad_block: - /* Only mark bad in memory */ - nmbm_set_block_state(ni, ba, BLOCK_ST_BAD); - - next_block: - ba++; - } - - if (sizeremain) - return false; - - success = nmbm_check_header(ni->info_table_cache, ni->info_table_size); - if (!success) - return false; - - *eba = ba; - *write_count = ifthdr->write_count; - - success = nmbm_check_info_table(ni, start_ba, ba, ni->info_table_cache, - mapping_blocks_top_ba); - if (!success) - return false; - - if (!table_loaded || ifthdr->write_count > ni->info_table.write_count) { - memcpy(&ni->info_table, ifthdr, sizeof(ni->info_table)); - memcpy(ni->block_state, - (uint8_t *)ifthdr + ifthdr->state_table_off, - ni->state_table_size); - memcpy(ni->block_mapping, - (uint8_t *)ifthdr + ifthdr->mapping_table_off, - ni->mapping_table_size); - ni->info_table.write_count = ifthdr->write_count; - } - - return true; -} - -/* - * nmbm_search_info_table - Search info table from specific address - * @ni: NMBM instance structure - * @ba: start block address to search - * @limit: highest block address allowed for searching - * @table_start_ba: return the start block address of this table - * @table_end_ba: return the block address after end of this table - * @write_count: return the write count of this table - * @mapping_blocks_top_ba: return the block address of top remapped block - * @table_loaded: used to record whether ni->info_table has valid data - */ -static bool nmbm_search_info_table(struct nmbm_instance *ni, uint32_t ba, - uint32_t limit, uint32_t *table_start_ba, - uint32_t *table_end_ba, - uint32_t *write_count, - uint32_t *mapping_blocks_top_ba, - bool table_loaded) -{ - bool success; - - while (ba < limit - size2blk(ni, ni->info_table_size)) { - success = nmbm_try_load_info_table(ni, ba, table_end_ba, - write_count, - mapping_blocks_top_ba, - table_loaded); - if (success) { - *table_start_ba = ba; - return true; - } - - ba++; - } - - return false; -} - -/* - * nmbm_load_info_table - Load info table(s) from a chip - * @ni: NMBM instance structure - * @ba: start block address to search info table - * @limit: highest block address allowed for searching - */ -static bool nmbm_load_info_table(struct nmbm_instance *ni, uint32_t ba, - uint32_t limit) -{ - uint32_t main_table_end_ba, backup_table_end_ba, table_end_ba; - uint32_t main_mapping_blocks_top_ba, backup_mapping_blocks_top_ba; - uint32_t main_table_write_count, backup_table_write_count; - uint32_t i; - bool success; - - /* Set initial value */ - ni->main_table_ba = 0; - ni->backup_table_ba = 0; - ni->info_table.write_count = 0; - ni->mapping_blocks_top_ba = ni->signature_ba - 1; - ni->data_block_count = ni->signature.mgmt_start_pb; - - /* Find first info table */ - success = nmbm_search_info_table(ni, ba, limit, &ni->main_table_ba, - &main_table_end_ba, &main_table_write_count, - &main_mapping_blocks_top_ba, false); - if (!success) { - nlog_warn(ni, "No valid info table found\n"); - return false; - } - - table_end_ba = main_table_end_ba; - - nlog_table_found(ni, true, main_table_write_count, ni->main_table_ba, - main_table_end_ba); - - /* Find second info table */ - success = nmbm_search_info_table(ni, main_table_end_ba, limit, - &ni->backup_table_ba, &backup_table_end_ba, - &backup_table_write_count, &backup_mapping_blocks_top_ba, true); - if (!success) { - nlog_warn(ni, "Second info table not found\n"); - } else { - table_end_ba = backup_table_end_ba; - - nlog_table_found(ni, false, backup_table_write_count, - ni->backup_table_ba, backup_table_end_ba); - } - - /* Pick mapping_blocks_top_ba */ - if (!ni->backup_table_ba) { - ni->mapping_blocks_top_ba= main_mapping_blocks_top_ba; - } else { - if (main_table_write_count >= backup_table_write_count) - ni->mapping_blocks_top_ba = main_mapping_blocks_top_ba; - else - ni->mapping_blocks_top_ba = backup_mapping_blocks_top_ba; - } - - /* Set final mapping_blocks_ba */ - ni->mapping_blocks_ba = table_end_ba; - - /* Set final data_block_count */ - for (i = ni->signature.mgmt_start_pb; i > 0; i--) { - if (ni->block_mapping[i - 1] >= 0) { - ni->data_block_count = i; - break; - } - } - - /* Regenerate the info table cache from the final selected info table */ - nmbm_generate_info_table_cache(ni); - - /* - * If only one table exists, try to write another table. - * If two tables have different write count, try to update info table - */ - if (!ni->backup_table_ba) { - success = nmbm_rescue_single_info_table(ni); - } else if (main_table_write_count != backup_table_write_count) { - /* Mark state & mapping tables changed */ - ni->block_state_changed = 1; - ni->block_mapping_changed = 1; - - success = nmbm_update_single_info_table(ni, - main_table_write_count < backup_table_write_count); - } else { - success = true; - } - - /* - * If there is no spare unmapped blocks, or still only one table - * exists, set the chip to read-only - */ - if (ni->mapping_blocks_ba == ni->mapping_blocks_top_ba) { - nlog_warn(ni, "No spare unmapped blocks. Device is now read-only\n"); - ni->protected = 1; - } else if (!success) { - nlog_warn(ni, "Only one info table found. Device is now read-only\n"); - ni->protected = 1; - } - - return true; -} - -/* - * nmbm_load_existing - Load NMBM from a new chip - * @ni: NMBM instance structure - */ -static bool nmbm_load_existing(struct nmbm_instance *ni) -{ - bool success; - - /* Calculate the boundary of management blocks */ - ni->mgmt_start_ba = ni->signature.mgmt_start_pb; - - nlog_debug(ni, "NMBM management region starts at block %u [0x%08llx]\n", - ni->mgmt_start_ba, ba2addr(ni, ni->mgmt_start_ba)); - - /* Look for info table(s) */ - success = nmbm_load_info_table(ni, ni->mgmt_start_ba, - ni->signature_ba); - if (success) { - nlog_info(ni, "NMBM has been successfully attached\n"); - return true; - } - - if (!ni->force_create) { - printk("not creating NMBM table\n"); - return false; - } - - /* Fill block state table & mapping table */ - nmbm_scan_badblocks(ni); - nmbm_build_mapping_table(ni); - - /* Write info table(s) */ - success = nmbm_create_info_table(ni); - if (success) { - nlog_info(ni, "NMBM has been successfully created\n"); - return true; - } - - return false; -} - -/* - * nmbm_find_signature - Find signature in the lower NAND chip - * @ni: NMBM instance structure - * @signature_ba: used for storing block address of the signature - * @signature_ba: return the actual block address of signature block - * - * Find a valid signature from a specific range in the lower NAND chip, - * from bottom (highest address) to top (lowest address) - * - * Return true if found. - */ -static bool nmbm_find_signature(struct nmbm_instance *ni, - struct nmbm_signature *signature, - uint32_t *signature_ba) -{ - struct nmbm_signature sig; - uint64_t off, addr; - uint32_t block_count, ba, limit; - bool success; - int ret; - - /* Calculate top and bottom block address */ - block_count = bmtd.total_blks; - ba = block_count; - limit = (block_count / NMBM_MGMT_DIV) * (NMBM_MGMT_DIV - ni->max_ratio); - if (ni->max_reserved_blocks && block_count - limit > ni->max_reserved_blocks) - limit = block_count - ni->max_reserved_blocks; - - while (ba >= limit) { - ba--; - addr = ba2addr(ni, ba); - - if (nmbm_check_bad_phys_block(ni, ba)) - continue; - - /* Check every page. - * As long as at leaset one page contains valid signature, - * the block is treated as a valid signature block. - */ - for (off = 0; off < bmtd.blk_size; - off += bmtd.pg_size) { - ret = nmbn_read_data(ni, addr + off, &sig, - sizeof(sig)); - if (ret) - continue; - - /* Check for header size and checksum */ - success = nmbm_check_header(&sig, sizeof(sig)); - if (!success) - continue; - - /* Check for header magic */ - if (sig.header.magic == NMBM_MAGIC_SIGNATURE) { - /* Found it */ - memcpy(signature, &sig, sizeof(sig)); - *signature_ba = ba; - return true; - } - } - }; - - return false; -} - -/* - * nmbm_calc_structure_size - Calculate the instance structure size - * @nld: NMBM lower device structure - */ -static size_t nmbm_calc_structure_size(void) -{ - uint32_t state_table_size, mapping_table_size, info_table_size; - uint32_t block_count; - - block_count = bmtd.total_blks; - - /* Calculate info table size */ - state_table_size = ((block_count + NMBM_BITMAP_BLOCKS_PER_UNIT - 1) / - NMBM_BITMAP_BLOCKS_PER_UNIT) * NMBM_BITMAP_UNIT_SIZE; - mapping_table_size = block_count * sizeof(int32_t); - - info_table_size = ALIGN(sizeof(struct nmbm_info_table_header), - bmtd.pg_size); - info_table_size += ALIGN(state_table_size, bmtd.pg_size); - info_table_size += ALIGN(mapping_table_size, bmtd.pg_size); - - return info_table_size + state_table_size + mapping_table_size + - sizeof(struct nmbm_instance); -} - -/* - * nmbm_init_structure - Initialize members of instance structure - * @ni: NMBM instance structure - */ -static void nmbm_init_structure(struct nmbm_instance *ni) -{ - uint32_t pages_per_block, blocks_per_chip; - uintptr_t ptr; - - pages_per_block = bmtd.blk_size / bmtd.pg_size; - blocks_per_chip = bmtd.total_blks; - - ni->rawpage_size = bmtd.pg_size + bmtd.mtd->oobsize; - ni->rawblock_size = pages_per_block * ni->rawpage_size; - ni->rawchip_size = blocks_per_chip * ni->rawblock_size; - - /* Calculate number of block this chip */ - ni->block_count = blocks_per_chip; - - /* Calculate info table size */ - ni->state_table_size = ((ni->block_count + NMBM_BITMAP_BLOCKS_PER_UNIT - 1) / - NMBM_BITMAP_BLOCKS_PER_UNIT) * NMBM_BITMAP_UNIT_SIZE; - ni->mapping_table_size = ni->block_count * sizeof(*ni->block_mapping); - - ni->info_table_size = ALIGN(sizeof(ni->info_table), - bmtd.pg_size); - ni->info_table.state_table_off = ni->info_table_size; - - ni->info_table_size += ALIGN(ni->state_table_size, - bmtd.pg_size); - ni->info_table.mapping_table_off = ni->info_table_size; - - ni->info_table_size += ALIGN(ni->mapping_table_size, - bmtd.pg_size); - - ni->info_table_spare_blocks = nmbm_get_spare_block_count( - size2blk(ni, ni->info_table_size)); - - /* Assign memory to members */ - ptr = (uintptr_t)ni + sizeof(*ni); - - ni->info_table_cache = (void *)ptr; - ptr += ni->info_table_size; - - ni->block_state = (void *)ptr; - ptr += ni->state_table_size; - - ni->block_mapping = (void *)ptr; - ptr += ni->mapping_table_size; - - ni->page_cache = bmtd.data_buf; - - /* Initialize block state table */ - ni->block_state_changed = 0; - memset(ni->block_state, 0xff, ni->state_table_size); - - /* Initialize block mapping table */ - ni->block_mapping_changed = 0; -} - -/* - * nmbm_attach - Attach to a lower device - * @ni: NMBM instance structure - */ -static int nmbm_attach(struct nmbm_instance *ni) -{ - bool success; - - if (!ni) - return -EINVAL; - - /* Initialize NMBM instance */ - nmbm_init_structure(ni); - - success = nmbm_find_signature(ni, &ni->signature, &ni->signature_ba); - if (!success) { - if (!ni->force_create) { - nlog_err(ni, "Signature not found\n"); - return -ENODEV; - } - - success = nmbm_create_new(ni); - if (!success) - return -ENODEV; - - return 0; - } - - nlog_info(ni, "Signature found at block %u [0x%08llx]\n", - ni->signature_ba, ba2addr(ni, ni->signature_ba)); - - if (ni->signature.header.version != NMBM_VER) { - nlog_err(ni, "NMBM version %u.%u is not supported\n", - NMBM_VERSION_MAJOR_GET(ni->signature.header.version), - NMBM_VERSION_MINOR_GET(ni->signature.header.version)); - return -EINVAL; - } - - if (ni->signature.nand_size != bmtd.total_blks << bmtd.blk_shift || - ni->signature.block_size != bmtd.blk_size || - ni->signature.page_size != bmtd.pg_size || - ni->signature.spare_size != bmtd.mtd->oobsize) { - nlog_err(ni, "NMBM configuration mismatch\n"); - return -EINVAL; - } - - success = nmbm_load_existing(ni); - if (!success) - return -ENODEV; - - return 0; -} - -static bool remap_block_nmbm(u16 block, u16 mapped_block, int copy_len) -{ - struct nmbm_instance *ni = bmtd.ni; - int new_block; - - if (block >= ni->data_block_count) - return false; - - nmbm_set_block_state(ni, mapped_block, BLOCK_ST_BAD); - if (!nmbm_map_block(ni, block)) - return false; - - new_block = ni->block_mapping[block]; - bbt_nand_erase(new_block); - if (copy_len > 0) - bbt_nand_copy(new_block, mapped_block, copy_len); - nmbm_update_info_table(ni); - - return true; -} - -static int get_mapping_block_index_nmbm(int block) -{ - struct nmbm_instance *ni = bmtd.ni; - - if (block >= ni->data_block_count) - return -1; - - return ni->block_mapping[block]; -} - -static int mtk_bmt_init_nmbm(struct device_node *np) -{ - struct nmbm_instance *ni; - int ret; - - ni = kzalloc(nmbm_calc_structure_size(), GFP_KERNEL); - if (!ni) - return -ENOMEM; - - bmtd.ni = ni; - - if (of_property_read_u32(np, "mediatek,bmt-max-ratio", &ni->max_ratio)) - ni->max_ratio = 1; - if (of_property_read_u32(np, "mediatek,bmt-max-reserved-blocks", - &ni->max_reserved_blocks)) - ni->max_reserved_blocks = 256; - if (of_property_read_bool(np, "mediatek,empty-page-ecc-protected")) - ni->empty_page_ecc_ok = true; - if (of_property_read_bool(np, "mediatek,bmt-force-create")) - ni->force_create = true; - - ret = nmbm_attach(ni); - if (ret) - goto out; - - bmtd.mtd->size = ni->data_block_count << bmtd.blk_shift; - - return 0; - -out: - kfree(ni); - bmtd.ni = NULL; - - return ret; -} - -static int mtk_bmt_debug_nmbm(void *data, u64 val) -{ - struct nmbm_instance *ni = bmtd.ni; - int i; - - switch (val) { - case 0: - for (i = 1; i < ni->data_block_count; i++) { - if (ni->block_mapping[i] < ni->mapping_blocks_ba) - continue; - - printk("remap [%x->%x]\n", i, ni->block_mapping[i]); - } - } - - return 0; -} - -static void unmap_block_nmbm(u16 block) -{ - struct nmbm_instance *ni = bmtd.ni; - int start, offset; - int new_block; - - if (block >= ni->data_block_count) - return; - - start = block; - offset = 0; - while (ni->block_mapping[start] >= ni->mapping_blocks_ba) { - start--; - offset++; - if (start < 0) - return; - } - - if (!offset) - return; - - new_block = ni->block_mapping[start] + offset; - nmbm_set_block_state(ni, new_block, BLOCK_ST_GOOD); - ni->block_mapping[block] = new_block; - ni->block_mapping_changed++; - - new_block = ni->signature_ba - 1; - for (block = 0; block < ni->data_block_count; block++) { - int cur = ni->block_mapping[block]; - - if (cur < ni->mapping_blocks_ba) - continue; - - if (cur <= new_block) - new_block = cur - 1; - } - - ni->mapping_blocks_top_ba = new_block; - - nmbm_update_info_table(ni); -} - -const struct mtk_bmt_ops mtk_bmt_nmbm_ops = { - .init = mtk_bmt_init_nmbm, - .remap_block = remap_block_nmbm, - .unmap_block = unmap_block_nmbm, - .get_mapping_block = get_mapping_block_index_nmbm, - .debug = mtk_bmt_debug_nmbm, -}; diff --git a/target/linux/generic/files-6.12/drivers/mtd/nand/mtk_bmt_v2.c b/target/linux/generic/files-6.12/drivers/mtd/nand/mtk_bmt_v2.c deleted file mode 100644 index 6b06948c0f45fa..00000000000000 --- a/target/linux/generic/files-6.12/drivers/mtd/nand/mtk_bmt_v2.c +++ /dev/null @@ -1,506 +0,0 @@ -/* - * Copyright (c) 2017 MediaTek Inc. - * Author: Xiangsheng Hou - * Copyright (c) 2020-2022 Felix Fietkau - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * 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. - */ - -#include -#include -#include "mtk_bmt.h" - -struct bbbt { - char signature[3]; - /* This version is used to distinguish the legacy and new algorithm */ -#define BBMT_VERSION 2 - unsigned char version; - /* Below 2 tables will be written in SLC */ - u16 bb_tbl[]; -}; - -struct bbmt { - u16 block; -#define NO_MAPPED 0 -#define NORMAL_MAPPED 1 -#define BMT_MAPPED 2 - u16 mapped; -}; - -/* Maximum 8k blocks */ -#define BBPOOL_RATIO 2 -#define BB_TABLE_MAX bmtd.table_size -#define BMT_TABLE_MAX (BB_TABLE_MAX * BBPOOL_RATIO / 100) -#define BMT_TBL_DEF_VAL 0x0 - -static inline struct bbmt *bmt_tbl(struct bbbt *bbbt) -{ - return (struct bbmt *)&bbbt->bb_tbl[bmtd.table_size]; -} - -static u16 find_valid_block(u16 block) -{ - u8 fdm[4]; - int ret; - int loop = 0; - -retry: - if (block >= bmtd.total_blks) - return 0; - - ret = bbt_nand_read(blk_pg(block), bmtd.data_buf, bmtd.pg_size, - fdm, sizeof(fdm)); - /* Read the 1st byte of FDM to judge whether it's a bad - * or not - */ - if (ret || fdm[0] != 0xff) { - pr_info("nand: found bad block 0x%x\n", block); - if (loop >= bmtd.bb_max) { - pr_info("nand: FATAL ERR: too many bad blocks!!\n"); - return 0; - } - - loop++; - block++; - goto retry; - } - - return block; -} - -/* Find out all bad blocks, and fill in the mapping table */ -static int scan_bad_blocks(struct bbbt *bbt) -{ - int i; - u16 block = 0; - - /* First time download, the block0 MUST NOT be a bad block, - * this is guaranteed by vendor - */ - bbt->bb_tbl[0] = 0; - - /* - * Construct the mapping table of Normal data area(non-PMT/BMTPOOL) - * G - Good block; B - Bad block - * --------------------------- - * physical |G|G|B|G|B|B|G|G|G|G|B|G|B| - * --------------------------- - * What bb_tbl[i] looks like: - * physical block(i): - * 0 1 2 3 4 5 6 7 8 9 a b c - * mapped block(bb_tbl[i]): - * 0 1 3 6 7 8 9 b ...... - * ATTENTION: - * If new bad block ocurred(n), search bmt_tbl to find - * a available block(x), and fill in the bb_tbl[n] = x; - */ - for (i = 1; i < bmtd.pool_lba; i++) { - bbt->bb_tbl[i] = find_valid_block(bbt->bb_tbl[i - 1] + 1); - BBT_LOG("bb_tbl[0x%x] = 0x%x", i, bbt->bb_tbl[i]); - if (bbt->bb_tbl[i] == 0) - return -1; - } - - /* Physical Block start Address of BMT pool */ - bmtd.pool_pba = bbt->bb_tbl[i - 1] + 1; - if (bmtd.pool_pba >= bmtd.total_blks - 2) { - pr_info("nand: FATAL ERR: Too many bad blocks!!\n"); - return -1; - } - - BBT_LOG("pool_pba=0x%x", bmtd.pool_pba); - i = 0; - block = bmtd.pool_pba; - /* - * The bmt table is used for runtime bad block mapping - * G - Good block; B - Bad block - * --------------------------- - * physical |G|G|B|G|B|B|G|G|G|G|B|G|B| - * --------------------------- - * block: 0 1 2 3 4 5 6 7 8 9 a b c - * What bmt_tbl[i] looks like in initial state: - * i: - * 0 1 2 3 4 5 6 7 - * bmt_tbl[i].block: - * 0 1 3 6 7 8 9 b - * bmt_tbl[i].mapped: - * N N N N N N N B - * N - Not mapped(Available) - * M - Mapped - * B - BMT - * ATTENTION: - * BMT always in the last valid block in pool - */ - while ((block = find_valid_block(block)) != 0) { - bmt_tbl(bbt)[i].block = block; - bmt_tbl(bbt)[i].mapped = NO_MAPPED; - BBT_LOG("bmt_tbl[%d].block = 0x%x", i, block); - block++; - i++; - } - - /* i - How many available blocks in pool, which is the length of bmt_tbl[] - * bmtd.bmt_blk_idx - bmt_tbl[bmtd.bmt_blk_idx].block => the BMT block - */ - bmtd.bmt_blk_idx = i - 1; - bmt_tbl(bbt)[bmtd.bmt_blk_idx].mapped = BMT_MAPPED; - - if (i < 1) { - pr_info("nand: FATAL ERR: no space to store BMT!!\n"); - return -1; - } - - pr_info("[BBT] %d available blocks in BMT pool\n", i); - - return 0; -} - -static bool is_valid_bmt(unsigned char *buf, unsigned char *fdm) -{ - struct bbbt *bbt = (struct bbbt *)buf; - u8 *sig = (u8*)bbt->signature + MAIN_SIGNATURE_OFFSET; - - - if (memcmp(bbt->signature + MAIN_SIGNATURE_OFFSET, "BMT", 3) == 0 && - memcmp(fdm + OOB_SIGNATURE_OFFSET, "bmt", 3) == 0) { - if (bbt->version == BBMT_VERSION) - return true; - } - BBT_LOG("[BBT] BMT Version not match,upgrage preloader and uboot please! sig=%02x%02x%02x, fdm=%02x%02x%02x", - sig[0], sig[1], sig[2], - fdm[1], fdm[2], fdm[3]); - return false; -} - -static u16 get_bmt_index(struct bbmt *bmt) -{ - int i = 0; - - while (bmt[i].block != BMT_TBL_DEF_VAL) { - if (bmt[i].mapped == BMT_MAPPED) - return i; - i++; - } - return 0; -} - -/* Write the Burner Bad Block Table to Nand Flash - * n - write BMT to bmt_tbl[n] - */ -static u16 upload_bmt(struct bbbt *bbt, int n) -{ - u16 block; - -retry: - if (n < 0 || bmt_tbl(bbt)[n].mapped == NORMAL_MAPPED) { - pr_info("nand: FATAL ERR: no space to store BMT!\n"); - return (u16)-1; - } - - block = bmt_tbl(bbt)[n].block; - BBT_LOG("n = 0x%x, block = 0x%x", n, block); - if (bbt_nand_erase(block)) { - bmt_tbl(bbt)[n].block = 0; - /* erase failed, try the previous block: bmt_tbl[n - 1].block */ - n--; - goto retry; - } - - /* The signature offset is fixed set to 0, - * oob signature offset is fixed set to 1 - */ - memcpy(bbt->signature + MAIN_SIGNATURE_OFFSET, "BMT", 3); - bbt->version = BBMT_VERSION; - - if (write_bmt(block, (unsigned char *)bbt)) { - bmt_tbl(bbt)[n].block = 0; - - /* write failed, try the previous block in bmt_tbl[n - 1] */ - n--; - goto retry; - } - - /* Return the current index(n) of BMT pool (bmt_tbl[n]) */ - return n; -} - -static u16 find_valid_block_in_pool(struct bbbt *bbt) -{ - int i; - - if (bmtd.bmt_blk_idx == 0) - goto error; - - for (i = 0; i < bmtd.bmt_blk_idx; i++) { - if (bmt_tbl(bbt)[i].block != 0 && bmt_tbl(bbt)[i].mapped == NO_MAPPED) { - bmt_tbl(bbt)[i].mapped = NORMAL_MAPPED; - return bmt_tbl(bbt)[i].block; - } - } - -error: - pr_info("nand: FATAL ERR: BMT pool is run out!\n"); - return 0; -} - -/* We met a bad block, mark it as bad and map it to a valid block in pool, - * if it's a write failure, we need to write the data to mapped block - */ -static bool remap_block_v2(u16 block, u16 mapped_block, int copy_len) -{ - u16 new_block; - struct bbbt *bbt; - - bbt = bmtd.bbt; - new_block = find_valid_block_in_pool(bbt); - if (new_block == 0) - return false; - - /* Map new bad block to available block in pool */ - bbt->bb_tbl[block] = new_block; - - /* Erase new block */ - bbt_nand_erase(new_block); - if (copy_len > 0) - bbt_nand_copy(new_block, mapped_block, copy_len); - - bmtd.bmt_blk_idx = upload_bmt(bbt, bmtd.bmt_blk_idx); - - return true; -} - -static int get_mapping_block_index_v2(int block) -{ - int start, end; - - if (block >= bmtd.pool_lba) - return block; - - if (!mapping_block_in_range(block, &start, &end)) - return block; - - return bmtd.bbt->bb_tbl[block]; -} - -static void -unmap_block_v2(u16 block) -{ - bmtd.bbt->bb_tbl[block] = block; - bmtd.bmt_blk_idx = upload_bmt(bmtd.bbt, bmtd.bmt_blk_idx); -} - -static unsigned long * -mtk_bmt_get_mapping_mask(void) -{ - struct bbmt *bbmt = bmt_tbl(bmtd.bbt); - int main_blocks = bmtd.mtd->size >> bmtd.blk_shift; - unsigned long *used; - int i, k; - - used = kcalloc(sizeof(unsigned long), BIT_WORD(bmtd.bmt_blk_idx) + 1, GFP_KERNEL); - if (!used) - return NULL; - - for (i = 1; i < main_blocks; i++) { - if (bmtd.bbt->bb_tbl[i] == i) - continue; - - for (k = 0; k < bmtd.bmt_blk_idx; k++) { - if (bmtd.bbt->bb_tbl[i] != bbmt[k].block) - continue; - - set_bit(k, used); - break; - } - } - - return used; -} - -static int mtk_bmt_debug_v2(void *data, u64 val) -{ - struct bbmt *bbmt = bmt_tbl(bmtd.bbt); - struct mtd_info *mtd = bmtd.mtd; - unsigned long *used; - int main_blocks = mtd->size >> bmtd.blk_shift; - int n_remap = 0; - int i; - - used = mtk_bmt_get_mapping_mask(); - if (!used) - return -ENOMEM; - - switch (val) { - case 0: - for (i = 1; i < main_blocks; i++) { - if (bmtd.bbt->bb_tbl[i] == i) - continue; - - printk("remap [%x->%x]\n", i, bmtd.bbt->bb_tbl[i]); - n_remap++; - } - for (i = 0; i <= bmtd.bmt_blk_idx; i++) { - char c; - - switch (bbmt[i].mapped) { - case NO_MAPPED: - continue; - case NORMAL_MAPPED: - c = 'm'; - if (test_bit(i, used)) - c = 'M'; - break; - case BMT_MAPPED: - c = 'B'; - break; - default: - c = 'X'; - break; - } - printk("[%x:%c] = 0x%x\n", i, c, bbmt[i].block); - } - break; - case 100: - for (i = 0; i <= bmtd.bmt_blk_idx; i++) { - if (bbmt[i].mapped != NORMAL_MAPPED) - continue; - - if (test_bit(i, used)) - continue; - - n_remap++; - bbmt[i].mapped = NO_MAPPED; - printk("free block [%d:%x]\n", i, bbmt[i].block); - } - if (n_remap) - bmtd.bmt_blk_idx = upload_bmt(bmtd.bbt, bmtd.bmt_blk_idx); - break; - } - - kfree(used); - - return 0; -} - -static int mtk_bmt_init_v2(struct device_node *np) -{ - u32 bmt_pool_size, bmt_table_size; - u32 bufsz, block; - u16 pmt_block; - - if (of_property_read_u32(np, "mediatek,bmt-pool-size", - &bmt_pool_size) != 0) - bmt_pool_size = 80; - - if (of_property_read_u8(np, "mediatek,bmt-oob-offset", - &bmtd.oob_offset) != 0) - bmtd.oob_offset = 0; - - if (of_property_read_u32(np, "mediatek,bmt-table-size", - &bmt_table_size) != 0) - bmt_table_size = 0x2000U; - - bmtd.table_size = bmt_table_size; - - pmt_block = bmtd.total_blks - bmt_pool_size - 2; - - bmtd.mtd->size = pmt_block << bmtd.blk_shift; - - /* - * --------------------------------------- - * | PMT(2blks) | BMT POOL(totalblks * 2%) | - * --------------------------------------- - * ^ ^ - * | | - * pmt_block pmt_block + 2blocks(pool_lba) - * - * ATTETION!!!!!! - * The blocks ahead of the boundary block are stored in bb_tbl - * and blocks behind are stored in bmt_tbl - */ - - bmtd.pool_lba = (u16)(pmt_block + 2); - bmtd.bb_max = bmtd.total_blks * BBPOOL_RATIO / 100; - - bufsz = round_up(sizeof(struct bbbt) + - bmt_table_size * sizeof(struct bbmt), bmtd.pg_size); - bmtd.bmt_pgs = bufsz >> bmtd.pg_shift; - - bmtd.bbt_buf = kzalloc(bufsz, GFP_KERNEL); - if (!bmtd.bbt_buf) - return -ENOMEM; - - memset(bmtd.bbt_buf, 0xff, bufsz); - - /* Scanning start from the first page of the last block - * of whole flash - */ - bmtd.bbt = NULL; - for (u16 block = bmtd.total_blks - 1; !bmtd.bbt && block >= bmtd.pool_lba; block--) { - u8 fdm[4]; - - if (bbt_nand_read(blk_pg(block), bmtd.bbt_buf, bufsz, fdm, sizeof(fdm))) { - /* Read failed, try the previous block */ - continue; - } - - if (!is_valid_bmt(bmtd.bbt_buf, fdm)) { - /* No valid BMT found, try the previous block */ - continue; - } - - bmtd.bmt_blk_idx = get_bmt_index(bmt_tbl((struct bbbt *)bmtd.bbt_buf)); - if (bmtd.bmt_blk_idx == 0) { - pr_info("[BBT] FATAL ERR: bmt block index is wrong!\n"); - break; - } - - pr_info("[BBT] BMT.v2 is found at 0x%x\n", block); - bmtd.bbt = (struct bbbt *)bmtd.bbt_buf; - } - - if (!bmtd.bbt) { - /* BMT not found */ - if (bmtd.total_blks > BB_TABLE_MAX + BMT_TABLE_MAX) { - pr_info("nand: FATAL: Too many blocks, can not support!\n"); - return -1; - } - - bmtd.bbt = (struct bbbt *)bmtd.bbt_buf; - memset(bmt_tbl(bmtd.bbt), BMT_TBL_DEF_VAL, - bmtd.table_size * sizeof(struct bbmt)); - - if (scan_bad_blocks(bmtd.bbt)) - return -1; - - /* BMT always in the last valid block in pool */ - bmtd.bmt_blk_idx = upload_bmt(bmtd.bbt, bmtd.bmt_blk_idx); - block = bmt_tbl(bmtd.bbt)[bmtd.bmt_blk_idx].block; - pr_notice("[BBT] BMT.v2 is written into PBA:0x%x\n", block); - - if (bmtd.bmt_blk_idx == 0) - pr_info("nand: Warning: no available block in BMT pool!\n"); - else if (bmtd.bmt_blk_idx == (u16)-1) - return -1; - } - - return 0; -} - - -const struct mtk_bmt_ops mtk_bmt_v2_ops = { - .sig = "bmt", - .sig_len = 3, - .init = mtk_bmt_init_v2, - .remap_block = remap_block_v2, - .unmap_block = unmap_block_v2, - .get_mapping_block = get_mapping_block_index_v2, - .debug = mtk_bmt_debug_v2, -}; diff --git a/target/linux/generic/files-6.12/drivers/mtd/parsers/routerbootpart.c b/target/linux/generic/files-6.12/drivers/mtd/parsers/routerbootpart.c deleted file mode 100644 index aa786cd895e512..00000000000000 --- a/target/linux/generic/files-6.12/drivers/mtd/parsers/routerbootpart.c +++ /dev/null @@ -1,365 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Parser for MikroTik RouterBoot partitions. - * - * Copyright (C) 2020 Thibaut VARÈNE - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published - * by the Free Software Foundation. - * - * This parser builds from the "fixed-partitions" one (see ofpart.c), but it can - * handle dynamic partitions as found on routerboot devices. - * - * DTS nodes are defined as follows: - * For fixed partitions: - * node-name@unit-address { - * reg = ; - * label = ; - * read-only; - * lock; - * }; - * - * reg property is mandatory; other properties are optional. - * reg format is
. length can be 0 if the next partition is - * another fixed partition or a "well-known" partition as defined below: in that - * case the partition will extend up to the next one. - * - * For dynamic partitions: - * node-name { - * size = ; - * label = ; - * read-only; - * lock; - * }; - * - * size property is normally mandatory. It can only be omitted (or set to 0) if: - * - the partition is a "well-known" one (as defined below), in which case - * the partition size will be automatically adjusted; or - * - the next partition is a fixed one or a "well-known" one, in which case - * the current partition will extend up to the next one. - * Other properties are optional. - * size format is . - * By default dynamic partitions are appended after the preceding one, except - * for "well-known" ones which are automatically located on flash. - * - * Well-known partitions (matched via label or node-name): - * - "hard_config" - * - "soft_config" - * - "dtb_config" - * - * Note: this parser will happily register 0-sized partitions if misused. - * - * This parser requires the DTS to list partitions in ascending order as - * expected on the MTD device. - * - * Since only the "hard_config" and "soft_config" partitions are used in OpenWRT, - * a minimal working DTS could define only these two partitions dynamically (in - * the right order, usually hard_config then soft_config). - * - * Note: some mips RB devices encode the hard_config offset and length in two - * consecutive u32 located at offset 0x14 (for ramips) or 0x24 (for ath79) on - * the SPI NOR flash. Unfortunately this seems inconsistent across machines and - * does not apply to e.g. ipq-based ones, so we ignore that information. - * - * Note: To find well-known partitions, this parser will go through the entire - * top mtd partition parsed, _before_ the DTS nodes are processed. This works - * well in the current state of affairs, and is a simpler implementation than - * searching for known partitions in the "holes" left between fixed-partition, - * _after_ processing DTS nodes. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#define RB_MAGIC_HARD (('H') | ('a' << 8) | ('r' << 16) | ('d' << 24)) -#define RB_MAGIC_SOFT (('S') | ('o' << 8) | ('f' << 16) | ('t' << 24)) -#define RB_BLOCK_SIZE 0x1000 - -struct routerboot_dynpart { - const char * const name; - const u32 magic; - int (* const size_fixup)(struct mtd_info *, struct routerboot_dynpart *); - size_t offset; - size_t size; - bool found; -}; - -static int routerboot_dtbsfixup(struct mtd_info *, struct routerboot_dynpart *); - -static struct routerboot_dynpart rb_dynparts[] = { - { - .name = "hard_config", - .magic = RB_MAGIC_HARD, // stored in CPU-endianness on flash - .size_fixup = NULL, - .offset = 0x0, - .size = RB_BLOCK_SIZE, - .found = false, - }, { - .name = "soft_config", - .magic = RB_MAGIC_SOFT, // stored in CPU-endianness on flash - .size_fixup = NULL, - .offset = 0x0, - .size = RB_BLOCK_SIZE, - .found = false, - }, { - .name = "dtb_config", - .magic = fdt32_to_cpu(OF_DT_HEADER), // stored BE on flash - .size_fixup = routerboot_dtbsfixup, - .offset = 0x0, - .size = 0x0, - .found = false, - } -}; - -static int routerboot_dtbsfixup(struct mtd_info *master, struct routerboot_dynpart *rbdpart) -{ - int err; - size_t bytes_read, psize; - struct { - fdt32_t magic; - fdt32_t totalsize; - fdt32_t off_dt_struct; - fdt32_t off_dt_strings; - fdt32_t off_mem_rsvmap; - fdt32_t version; - fdt32_t last_comp_version; - fdt32_t boot_cpuid_phys; - fdt32_t size_dt_strings; - fdt32_t size_dt_struct; - } fdt_header; - - err = mtd_read(master, rbdpart->offset, sizeof(fdt_header), - &bytes_read, (u8 *)&fdt_header); - if (err) - return err; - - if (bytes_read != sizeof(fdt_header)) - return -EIO; - - psize = fdt32_to_cpu(fdt_header.totalsize); - if (!psize) - return -EINVAL; - - rbdpart->size = psize; - return 0; -} - -static void routerboot_find_dynparts(struct mtd_info *master) -{ - size_t bytes_read, offset; - bool allfound; - int err, i; - u32 buf; - - /* - * Dynamic RouterBoot partitions offsets are aligned to RB_BLOCK_SIZE: - * read the whole partition at RB_BLOCK_SIZE intervals to find sigs. - * Skip partition content when possible. - */ - offset = 0; - while (offset < master->size) { - err = mtd_read(master, offset, sizeof(buf), &bytes_read, (u8 *)&buf); - if (err) { - pr_err("%s: mtd_read error while parsing (offset: 0x%zX): %d\n", - master->name, offset, err); - continue; - } - - allfound = true; - - for (i = 0; i < ARRAY_SIZE(rb_dynparts); i++) { - if (rb_dynparts[i].found) - continue; - - allfound = false; - - if (rb_dynparts[i].magic == buf) { - rb_dynparts[i].offset = offset; - - if (rb_dynparts[i].size_fixup) { - err = rb_dynparts[i].size_fixup(master, &rb_dynparts[i]); - if (err) { - pr_err("%s: size fixup error while parsing \"%s\": %d\n", - master->name, rb_dynparts[i].name, err); - continue; - } - } - - rb_dynparts[i].found = true; - - /* - * move offset to skip the whole partition on - * next iteration if size > RB_BLOCK_SIZE. - */ - if (rb_dynparts[i].size > RB_BLOCK_SIZE) - offset += ALIGN_DOWN((rb_dynparts[i].size - RB_BLOCK_SIZE), RB_BLOCK_SIZE); - - break; - } - } - - offset += RB_BLOCK_SIZE; - - if (allfound) - break; - } -} - -static int routerboot_partitions_parse(struct mtd_info *master, - const struct mtd_partition **pparts, - struct mtd_part_parser_data *data) -{ - struct device_node *rbpart_node, *pp; - struct mtd_partition *parts; - const char *partname; - size_t master_ofs; - int np; - - /* Pull of_node from the master device node */ - rbpart_node = mtd_get_of_node(master); - if (!rbpart_node) - return 0; - - /* First count the subnodes */ - np = 0; - for_each_child_of_node(rbpart_node, pp) - np++; - - if (!np) - return 0; - - parts = kcalloc(np, sizeof(*parts), GFP_KERNEL); - if (!parts) - return -ENOMEM; - - /* Preemptively look for known parts in flash */ - routerboot_find_dynparts(master); - - np = 0; - master_ofs = 0; - for_each_child_of_node(rbpart_node, pp) { - const __be32 *reg, *sz; - size_t offset, size; - int i, len, a_cells, s_cells; - - partname = of_get_property(pp, "label", &len); - /* Allow deprecated use of "name" instead of "label" */ - if (!partname) - partname = of_get_property(pp, "name", &len); - /* Fallback to node name per spec if all else fails: partname is always set */ - if (!partname) - partname = pp->name; - parts[np].name = partname; - - reg = of_get_property(pp, "reg", &len); - if (reg) { - /* Fixed partition */ - a_cells = of_n_addr_cells(pp); - s_cells = of_n_size_cells(pp); - - if ((len / 4) != (a_cells + s_cells)) { - pr_debug("%s: routerboot partition %pOF (%pOF) error parsing reg property.\n", - master->name, pp, rbpart_node); - goto rbpart_fail; - } - - offset = of_read_number(reg, a_cells); - size = of_read_number(reg + a_cells, s_cells); - } else { - /* Dynamic partition */ - /* Default: part starts at current offset, 0 size */ - offset = master_ofs; - size = 0; - - /* Check if well-known partition */ - for (i = 0; i < ARRAY_SIZE(rb_dynparts); i++) { - if (!strcmp(partname, rb_dynparts[i].name) && rb_dynparts[i].found) { - offset = rb_dynparts[i].offset; - size = rb_dynparts[i].size; - break; - } - } - - /* Standalone 'size' property? Override size */ - sz = of_get_property(pp, "size", &len); - if (sz) { - s_cells = of_n_size_cells(pp); - if ((len / 4) != s_cells) { - pr_debug("%s: routerboot partition %pOF (%pOF) error parsing size property.\n", - master->name, pp, rbpart_node); - goto rbpart_fail; - } - - size = of_read_number(sz, s_cells); - } - } - - if (np > 0) { - /* Minor sanity check for overlaps */ - if (offset < (parts[np-1].offset + parts[np-1].size)) { - pr_err("%s: routerboot partition %pOF (%pOF) \"%s\" overlaps with previous partition \"%s\".\n", - master->name, pp, rbpart_node, - partname, parts[np-1].name); - goto rbpart_fail; - } - - /* Fixup end of previous partition if necessary */ - if (!parts[np-1].size) - parts[np-1].size = (offset - parts[np-1].offset); - } - - if ((offset + size) > master->size) { - pr_err("%s: routerboot partition %pOF (%pOF) \"%s\" extends past end of segment.\n", - master->name, pp, rbpart_node, partname); - goto rbpart_fail; - } - - parts[np].offset = offset; - parts[np].size = size; - parts[np].of_node = pp; - - if (of_get_property(pp, "read-only", &len)) - parts[np].mask_flags |= MTD_WRITEABLE; - - if (of_get_property(pp, "lock", &len)) - parts[np].mask_flags |= MTD_POWERUP_LOCK; - - /* Keep master offset aligned to RB_BLOCK_SIZE */ - master_ofs = ALIGN(offset + size, RB_BLOCK_SIZE); - np++; - } - - *pparts = parts; - return np; - -rbpart_fail: - pr_err("%s: error parsing routerboot partition %pOF (%pOF)\n", - master->name, pp, rbpart_node); - of_node_put(pp); - kfree(parts); - return -EINVAL; -} - -static const struct of_device_id parse_routerbootpart_match_table[] = { - { .compatible = "mikrotik,routerboot-partitions" }, - {}, -}; -MODULE_DEVICE_TABLE(of, parse_routerbootpart_match_table); - -static struct mtd_part_parser routerbootpart_parser = { - .parse_fn = routerboot_partitions_parse, - .name = "routerbootpart", - .of_match_table = parse_routerbootpart_match_table, -}; -module_mtd_part_parser(routerbootpart_parser); - -MODULE_LICENSE("GPL v2"); -MODULE_DESCRIPTION("MTD partitioning for RouterBoot"); -MODULE_AUTHOR("Thibaut VARENE"); diff --git a/target/linux/generic/files-6.12/drivers/net/phy/adm6996.c b/target/linux/generic/files-6.12/drivers/net/phy/adm6996.c deleted file mode 100644 index 66013f273de77d..00000000000000 --- a/target/linux/generic/files-6.12/drivers/net/phy/adm6996.c +++ /dev/null @@ -1,1243 +0,0 @@ -/* - * ADM6996 switch driver - * - * swconfig interface based on ar8216.c - * - * Copyright (c) 2008 Felix Fietkau - * VLAN support Copyright (c) 2010, 2011 Peter Lebbing - * Copyright (c) 2013 Hauke Mehrtens - * Copyright (c) 2014 Matti Laakso - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License v2 as published by the - * Free Software Foundation - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -/*#define DEBUG 1*/ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include "adm6996.h" - -MODULE_DESCRIPTION("Infineon ADM6996 Switch"); -MODULE_AUTHOR("Felix Fietkau, Peter Lebbing "); -MODULE_LICENSE("GPL"); - -static const char * const adm6996_model_name[] = -{ - NULL, - "ADM6996FC", - "ADM6996M", - "ADM6996L" -}; - -struct adm6996_mib_desc { - unsigned int offset; - const char *name; -}; - -struct adm6996_priv { - struct switch_dev dev; - void *priv; - - u8 eecs; - u8 eesk; - u8 eedi; - - enum adm6996_model model; - - bool enable_vlan; - bool vlan_enabled; /* Current hardware state */ - -#ifdef DEBUG - u16 addr; /* Debugging: register address to operate on */ -#endif - - u16 pvid[ADM_NUM_PORTS]; /* Primary VLAN ID */ - u8 tagged_ports; - - u16 vlan_id[ADM_NUM_VLANS]; - u8 vlan_table[ADM_NUM_VLANS]; /* bitmap, 1 = port is member */ - u8 vlan_tagged[ADM_NUM_VLANS]; /* bitmap, 1 = tagged member */ - - struct mutex mib_lock; - char buf[2048]; - - struct mutex reg_mutex; - - /* use abstraction for regops, we want to add gpio support in the future */ - u16 (*read)(struct adm6996_priv *priv, enum admreg reg); - void (*write)(struct adm6996_priv *priv, enum admreg reg, u16 val); -}; - -#define to_adm(_dev) container_of(_dev, struct adm6996_priv, dev) -#define phy_to_adm(_phy) ((struct adm6996_priv *) (_phy)->priv) - -#define MIB_DESC(_o, _n) \ - { \ - .offset = (_o), \ - .name = (_n), \ - } - -static const struct adm6996_mib_desc adm6996_mibs[] = { - MIB_DESC(ADM_CL0, "RxPacket"), - MIB_DESC(ADM_CL6, "RxByte"), - MIB_DESC(ADM_CL12, "TxPacket"), - MIB_DESC(ADM_CL18, "TxByte"), - MIB_DESC(ADM_CL24, "Collision"), - MIB_DESC(ADM_CL30, "Error"), -}; - -#define ADM6996_MIB_RXB_ID 1 -#define ADM6996_MIB_TXB_ID 3 - -static inline u16 -r16(struct adm6996_priv *priv, enum admreg reg) -{ - return priv->read(priv, reg); -} - -static inline void -w16(struct adm6996_priv *priv, enum admreg reg, u16 val) -{ - priv->write(priv, reg, val); -} - -/* Minimum timing constants */ -#define EECK_EDGE_TIME 3 /* 3us - max(adm 2.5us, 93c 1us) */ -#define EEDI_SETUP_TIME 1 /* 1us - max(adm 10ns, 93c 400ns) */ -#define EECS_SETUP_TIME 1 /* 1us - max(adm no, 93c 200ns) */ - -static void adm6996_gpio_write(struct adm6996_priv *priv, int cs, char *buf, unsigned int bits) -{ - int i, len = (bits + 7) / 8; - u8 mask; - - gpio_set_value(priv->eecs, cs); - udelay(EECK_EDGE_TIME); - - /* Byte assemble from MSB to LSB */ - for (i = 0; i < len; i++) { - /* Bit bang from MSB to LSB */ - for (mask = 0x80; mask && bits > 0; mask >>= 1, bits --) { - /* Clock low */ - gpio_set_value(priv->eesk, 0); - udelay(EECK_EDGE_TIME); - - /* Output on rising edge */ - gpio_set_value(priv->eedi, (mask & buf[i])); - udelay(EEDI_SETUP_TIME); - - /* Clock high */ - gpio_set_value(priv->eesk, 1); - udelay(EECK_EDGE_TIME); - } - } - - /* Clock low */ - gpio_set_value(priv->eesk, 0); - udelay(EECK_EDGE_TIME); - - if (cs) - gpio_set_value(priv->eecs, 0); -} - -static void adm6996_gpio_read(struct adm6996_priv *priv, int cs, char *buf, unsigned int bits) -{ - int i, len = (bits + 7) / 8; - u8 mask; - - gpio_set_value(priv->eecs, cs); - udelay(EECK_EDGE_TIME); - - /* Byte assemble from MSB to LSB */ - for (i = 0; i < len; i++) { - u8 byte; - - /* Bit bang from MSB to LSB */ - for (mask = 0x80, byte = 0; mask && bits > 0; mask >>= 1, bits --) { - u8 gp; - - /* Clock low */ - gpio_set_value(priv->eesk, 0); - udelay(EECK_EDGE_TIME); - - /* Input on rising edge */ - gp = gpio_get_value(priv->eedi); - if (gp) - byte |= mask; - - /* Clock high */ - gpio_set_value(priv->eesk, 1); - udelay(EECK_EDGE_TIME); - } - - *buf++ = byte; - } - - /* Clock low */ - gpio_set_value(priv->eesk, 0); - udelay(EECK_EDGE_TIME); - - if (cs) - gpio_set_value(priv->eecs, 0); -} - -/* Advance clock(s) */ -static void adm6996_gpio_adclk(struct adm6996_priv *priv, int clocks) -{ - int i; - for (i = 0; i < clocks; i++) { - /* Clock high */ - gpio_set_value(priv->eesk, 1); - udelay(EECK_EDGE_TIME); - - /* Clock low */ - gpio_set_value(priv->eesk, 0); - udelay(EECK_EDGE_TIME); - } -} - -static u16 -adm6996_read_gpio_reg(struct adm6996_priv *priv, enum admreg reg) -{ - /* cmd: 01 10 T DD R RRRRRR */ - u8 bits[6] = { - 0xFF, 0xFF, 0xFF, 0xFF, - (0x06 << 4) | ((0 & 0x01) << 3 | (reg&64)>>6), - ((reg&63)<<2) - }; - - u8 rbits[4]; - - /* Enable GPIO outputs with all pins to 0 */ - gpio_direction_output(priv->eecs, 0); - gpio_direction_output(priv->eesk, 0); - gpio_direction_output(priv->eedi, 0); - - adm6996_gpio_write(priv, 0, bits, 46); - gpio_direction_input(priv->eedi); - adm6996_gpio_adclk(priv, 2); - adm6996_gpio_read(priv, 0, rbits, 32); - - /* Extra clock(s) required per datasheet */ - adm6996_gpio_adclk(priv, 2); - - /* Disable GPIO outputs */ - gpio_direction_input(priv->eecs); - gpio_direction_input(priv->eesk); - - /* EEPROM has 16-bit registers, but pumps out two registers in one request */ - return (reg & 0x01 ? (rbits[0]<<8) | rbits[1] : (rbits[2]<<8) | (rbits[3])); -} - -/* Write chip configuration register */ -/* Follow 93c66 timing and chip's min EEPROM timing requirement */ -static void -adm6996_write_gpio_reg(struct adm6996_priv *priv, enum admreg reg, u16 val) -{ - /* cmd(27bits): sb(1) + opc(01) + addr(bbbbbbbb) + data(bbbbbbbbbbbbbbbb) */ - u8 bits[4] = { - (0x05 << 5) | (reg >> 3), - (reg << 5) | (u8)(val >> 11), - (u8)(val >> 3), - (u8)(val << 5) - }; - - /* Enable GPIO outputs with all pins to 0 */ - gpio_direction_output(priv->eecs, 0); - gpio_direction_output(priv->eesk, 0); - gpio_direction_output(priv->eedi, 0); - - /* Write cmd. Total 27 bits */ - adm6996_gpio_write(priv, 1, bits, 27); - - /* Extra clock(s) required per datasheet */ - adm6996_gpio_adclk(priv, 2); - - /* Disable GPIO outputs */ - gpio_direction_input(priv->eecs); - gpio_direction_input(priv->eesk); - gpio_direction_input(priv->eedi); -} - -static u16 -adm6996_read_mii_reg(struct adm6996_priv *priv, enum admreg reg) -{ - struct phy_device *phydev = priv->priv; - struct mii_bus *bus = phydev->mdio.bus; - - return bus->read(bus, PHYADDR(reg)); -} - -static void -adm6996_write_mii_reg(struct adm6996_priv *priv, enum admreg reg, u16 val) -{ - struct phy_device *phydev = priv->priv; - struct mii_bus *bus = phydev->mdio.bus; - - bus->write(bus, PHYADDR(reg), val); -} - -static int -adm6996_set_enable_vlan(struct switch_dev *dev, const struct switch_attr *attr, - struct switch_val *val) -{ - struct adm6996_priv *priv = to_adm(dev); - - if (val->value.i > 1) - return -EINVAL; - - priv->enable_vlan = val->value.i; - - return 0; -}; - -static int -adm6996_get_enable_vlan(struct switch_dev *dev, const struct switch_attr *attr, - struct switch_val *val) -{ - struct adm6996_priv *priv = to_adm(dev); - - val->value.i = priv->enable_vlan; - - return 0; -}; - -#ifdef DEBUG - -static int -adm6996_set_addr(struct switch_dev *dev, const struct switch_attr *attr, - struct switch_val *val) -{ - struct adm6996_priv *priv = to_adm(dev); - - if (val->value.i > 1023) - return -EINVAL; - - priv->addr = val->value.i; - - return 0; -}; - -static int -adm6996_get_addr(struct switch_dev *dev, const struct switch_attr *attr, - struct switch_val *val) -{ - struct adm6996_priv *priv = to_adm(dev); - - val->value.i = priv->addr; - - return 0; -}; - -static int -adm6996_set_data(struct switch_dev *dev, const struct switch_attr *attr, - struct switch_val *val) -{ - struct adm6996_priv *priv = to_adm(dev); - - if (val->value.i > 65535) - return -EINVAL; - - w16(priv, priv->addr, val->value.i); - - return 0; -}; - -static int -adm6996_get_data(struct switch_dev *dev, const struct switch_attr *attr, - struct switch_val *val) -{ - struct adm6996_priv *priv = to_adm(dev); - - val->value.i = r16(priv, priv->addr); - - return 0; -}; - -#endif /* def DEBUG */ - -static int -adm6996_set_pvid(struct switch_dev *dev, int port, int vlan) -{ - struct adm6996_priv *priv = to_adm(dev); - - pr_devel("set_pvid port %d vlan %d\n", port, vlan); - - if (vlan > ADM_VLAN_MAX_ID) - return -EINVAL; - - priv->pvid[port] = vlan; - - return 0; -} - -static int -adm6996_get_pvid(struct switch_dev *dev, int port, int *vlan) -{ - struct adm6996_priv *priv = to_adm(dev); - - pr_devel("get_pvid port %d\n", port); - *vlan = priv->pvid[port]; - - return 0; -} - -static int -adm6996_set_vid(struct switch_dev *dev, const struct switch_attr *attr, - struct switch_val *val) -{ - struct adm6996_priv *priv = to_adm(dev); - - pr_devel("set_vid port %d vid %d\n", val->port_vlan, val->value.i); - - if (val->value.i > ADM_VLAN_MAX_ID) - return -EINVAL; - - priv->vlan_id[val->port_vlan] = val->value.i; - - return 0; -}; - -static int -adm6996_get_vid(struct switch_dev *dev, const struct switch_attr *attr, - struct switch_val *val) -{ - struct adm6996_priv *priv = to_adm(dev); - - pr_devel("get_vid port %d\n", val->port_vlan); - - val->value.i = priv->vlan_id[val->port_vlan]; - - return 0; -}; - -static int -adm6996_get_ports(struct switch_dev *dev, struct switch_val *val) -{ - struct adm6996_priv *priv = to_adm(dev); - u8 ports = priv->vlan_table[val->port_vlan]; - u8 tagged = priv->vlan_tagged[val->port_vlan]; - int i; - - pr_devel("get_ports port_vlan %d\n", val->port_vlan); - - val->len = 0; - - for (i = 0; i < ADM_NUM_PORTS; i++) { - struct switch_port *p; - - if (!(ports & (1 << i))) - continue; - - p = &val->value.ports[val->len++]; - p->id = i; - if (tagged & (1 << i)) - p->flags = (1 << SWITCH_PORT_FLAG_TAGGED); - else - p->flags = 0; - } - - return 0; -}; - -static int -adm6996_set_ports(struct switch_dev *dev, struct switch_val *val) -{ - struct adm6996_priv *priv = to_adm(dev); - u8 *ports = &priv->vlan_table[val->port_vlan]; - u8 *tagged = &priv->vlan_tagged[val->port_vlan]; - int i; - - pr_devel("set_ports port_vlan %d ports", val->port_vlan); - - *ports = 0; - *tagged = 0; - - for (i = 0; i < val->len; i++) { - struct switch_port *p = &val->value.ports[i]; - -#ifdef DEBUG - pr_cont(" %d%s", p->id, - ((p->flags & (1 << SWITCH_PORT_FLAG_TAGGED)) ? "T" : - "")); -#endif - - if (p->flags & (1 << SWITCH_PORT_FLAG_TAGGED)) { - *tagged |= (1 << p->id); - priv->tagged_ports |= (1 << p->id); - } - - *ports |= (1 << p->id); - } - -#ifdef DEBUG - pr_cont("\n"); -#endif - - return 0; -}; - -/* - * Precondition: reg_mutex must be held - */ -static void -adm6996_enable_vlan(struct adm6996_priv *priv) -{ - u16 reg; - - reg = r16(priv, ADM_OTBE_P2_PVID); - reg &= ~(ADM_OTBE_MASK); - w16(priv, ADM_OTBE_P2_PVID, reg); - reg = r16(priv, ADM_IFNTE); - reg &= ~(ADM_IFNTE_MASK); - w16(priv, ADM_IFNTE, reg); - reg = r16(priv, ADM_VID_CHECK); - reg |= ADM_VID_CHECK_MASK; - w16(priv, ADM_VID_CHECK, reg); - reg = r16(priv, ADM_SYSC0); - reg |= ADM_NTTE; - reg &= ~(ADM_RVID1); - w16(priv, ADM_SYSC0, reg); - reg = r16(priv, ADM_SYSC3); - reg |= ADM_TBV; - w16(priv, ADM_SYSC3, reg); -} - -static void -adm6996_enable_vlan_6996l(struct adm6996_priv *priv) -{ - u16 reg; - - reg = r16(priv, ADM_SYSC3); - reg |= ADM_TBV; - reg |= ADM_MAC_CLONE; - w16(priv, ADM_SYSC3, reg); -} - -/* - * Disable VLANs - * - * Sets VLAN mapping for port-based VLAN with all ports connected to - * eachother (this is also the power-on default). - * - * Precondition: reg_mutex must be held - */ -static void -adm6996_disable_vlan(struct adm6996_priv *priv) -{ - u16 reg; - int i; - - for (i = 0; i < ADM_NUM_VLANS; i++) { - reg = ADM_VLAN_FILT_MEMBER_MASK; - w16(priv, ADM_VLAN_FILT_L(i), reg); - reg = ADM_VLAN_FILT_VALID | ADM_VLAN_FILT_VID(1); - w16(priv, ADM_VLAN_FILT_H(i), reg); - } - - reg = r16(priv, ADM_OTBE_P2_PVID); - reg |= ADM_OTBE_MASK; - w16(priv, ADM_OTBE_P2_PVID, reg); - reg = r16(priv, ADM_IFNTE); - reg |= ADM_IFNTE_MASK; - w16(priv, ADM_IFNTE, reg); - reg = r16(priv, ADM_VID_CHECK); - reg &= ~(ADM_VID_CHECK_MASK); - w16(priv, ADM_VID_CHECK, reg); - reg = r16(priv, ADM_SYSC0); - reg &= ~(ADM_NTTE); - reg |= ADM_RVID1; - w16(priv, ADM_SYSC0, reg); - reg = r16(priv, ADM_SYSC3); - reg &= ~(ADM_TBV); - w16(priv, ADM_SYSC3, reg); -} - -/* - * Disable VLANs - * - * Sets VLAN mapping for port-based VLAN with all ports connected to - * eachother (this is also the power-on default). - * - * Precondition: reg_mutex must be held - */ -static void -adm6996_disable_vlan_6996l(struct adm6996_priv *priv) -{ - u16 reg; - int i; - - for (i = 0; i < ADM_NUM_VLANS; i++) { - w16(priv, ADM_VLAN_MAP(i), 0); - } - - reg = r16(priv, ADM_SYSC3); - reg &= ~(ADM_TBV); - reg &= ~(ADM_MAC_CLONE); - w16(priv, ADM_SYSC3, reg); -} - -/* - * Precondition: reg_mutex must be held - */ -static void -adm6996_apply_port_pvids(struct adm6996_priv *priv) -{ - u16 reg; - int i; - - for (i = 0; i < ADM_NUM_PORTS; i++) { - reg = r16(priv, adm_portcfg[i]); - reg &= ~(ADM_PORTCFG_PVID_MASK); - reg |= ADM_PORTCFG_PVID(priv->pvid[i]); - if (priv->model == ADM6996L) { - if (priv->tagged_ports & (1 << i)) - reg |= (1 << 4); - else - reg &= ~(1 << 4); - } - w16(priv, adm_portcfg[i], reg); - } - - w16(priv, ADM_P0_PVID, ADM_P0_PVID_VAL(priv->pvid[0])); - w16(priv, ADM_P1_PVID, ADM_P1_PVID_VAL(priv->pvid[1])); - reg = r16(priv, ADM_OTBE_P2_PVID); - reg &= ~(ADM_P2_PVID_MASK); - reg |= ADM_P2_PVID_VAL(priv->pvid[2]); - w16(priv, ADM_OTBE_P2_PVID, reg); - reg = ADM_P3_PVID_VAL(priv->pvid[3]); - reg |= ADM_P4_PVID_VAL(priv->pvid[4]); - w16(priv, ADM_P3_P4_PVID, reg); - reg = r16(priv, ADM_P5_PVID); - reg &= ~(ADM_P2_PVID_MASK); - reg |= ADM_P5_PVID_VAL(priv->pvid[5]); - w16(priv, ADM_P5_PVID, reg); -} - -/* - * Precondition: reg_mutex must be held - */ -static void -adm6996_apply_vlan_filters(struct adm6996_priv *priv) -{ - u8 ports, tagged; - u16 vid, reg; - int i; - - for (i = 0; i < ADM_NUM_VLANS; i++) { - vid = priv->vlan_id[i]; - ports = priv->vlan_table[i]; - tagged = priv->vlan_tagged[i]; - - if (ports == 0) { - /* Disable VLAN entry */ - w16(priv, ADM_VLAN_FILT_H(i), 0); - w16(priv, ADM_VLAN_FILT_L(i), 0); - continue; - } - - reg = ADM_VLAN_FILT_MEMBER(ports); - reg |= ADM_VLAN_FILT_TAGGED(tagged); - w16(priv, ADM_VLAN_FILT_L(i), reg); - reg = ADM_VLAN_FILT_VALID | ADM_VLAN_FILT_VID(vid); - w16(priv, ADM_VLAN_FILT_H(i), reg); - } -} - -static void -adm6996_apply_vlan_filters_6996l(struct adm6996_priv *priv) -{ - u8 ports; - u16 reg; - int i; - - for (i = 0; i < ADM_NUM_VLANS; i++) { - ports = priv->vlan_table[i]; - - if (ports == 0) { - /* Disable VLAN entry */ - w16(priv, ADM_VLAN_MAP(i), 0); - continue; - } else { - reg = ADM_VLAN_FILT(ports); - w16(priv, ADM_VLAN_MAP(i), reg); - } - } -} - -static int -adm6996_hw_apply(struct switch_dev *dev) -{ - struct adm6996_priv *priv = to_adm(dev); - - pr_devel("hw_apply\n"); - - mutex_lock(&priv->reg_mutex); - - if (!priv->enable_vlan) { - if (priv->vlan_enabled) { - if (priv->model == ADM6996L) - adm6996_disable_vlan_6996l(priv); - else - adm6996_disable_vlan(priv); - priv->vlan_enabled = 0; - } - goto out; - } - - if (!priv->vlan_enabled) { - if (priv->model == ADM6996L) - adm6996_enable_vlan_6996l(priv); - else - adm6996_enable_vlan(priv); - priv->vlan_enabled = 1; - } - - adm6996_apply_port_pvids(priv); - if (priv->model == ADM6996L) - adm6996_apply_vlan_filters_6996l(priv); - else - adm6996_apply_vlan_filters(priv); - -out: - mutex_unlock(&priv->reg_mutex); - - return 0; -} - -/* - * Reset the switch - * - * The ADM6996 can't do a software-initiated reset, so we just initialise the - * registers we support in this driver. - * - * Precondition: reg_mutex must be held - */ -static void -adm6996_perform_reset (struct adm6996_priv *priv) -{ - int i; - - /* initialize port and vlan settings */ - for (i = 0; i < ADM_NUM_PORTS - 1; i++) { - w16(priv, adm_portcfg[i], ADM_PORTCFG_INIT | - ADM_PORTCFG_PVID(0)); - } - w16(priv, adm_portcfg[5], ADM_PORTCFG_CPU); - - if (priv->model == ADM6996M || priv->model == ADM6996FC) { - /* reset all PHY ports */ - for (i = 0; i < ADM_PHY_PORTS; i++) { - w16(priv, ADM_PHY_PORT(i), ADM_PHYCFG_INIT); - } - } - - priv->enable_vlan = 0; - priv->vlan_enabled = 0; - - for (i = 0; i < ADM_NUM_PORTS; i++) { - priv->pvid[i] = 0; - } - - for (i = 0; i < ADM_NUM_VLANS; i++) { - priv->vlan_id[i] = i; - priv->vlan_table[i] = 0; - priv->vlan_tagged[i] = 0; - } - - if (priv->model == ADM6996M) { - /* Clear VLAN priority map so prio's are unused */ - w16 (priv, ADM_VLAN_PRIOMAP, 0); - - adm6996_disable_vlan(priv); - adm6996_apply_port_pvids(priv); - } else if (priv->model == ADM6996L) { - /* Clear VLAN priority map so prio's are unused */ - w16 (priv, ADM_VLAN_PRIOMAP, 0); - - adm6996_disable_vlan_6996l(priv); - adm6996_apply_port_pvids(priv); - } -} - -static int -adm6996_reset_switch(struct switch_dev *dev) -{ - struct adm6996_priv *priv = to_adm(dev); - - pr_devel("reset\n"); - - mutex_lock(&priv->reg_mutex); - adm6996_perform_reset (priv); - mutex_unlock(&priv->reg_mutex); - return 0; -} - -static int -adm6996_get_port_link(struct switch_dev *dev, int port, - struct switch_port_link *link) -{ - struct adm6996_priv *priv = to_adm(dev); - - u16 reg = 0; - - if (port >= ADM_NUM_PORTS) - return -EINVAL; - - switch (port) { - case 0: - reg = r16(priv, ADM_PS0); - break; - case 1: - reg = r16(priv, ADM_PS0); - reg = reg >> 8; - break; - case 2: - reg = r16(priv, ADM_PS1); - break; - case 3: - reg = r16(priv, ADM_PS1); - reg = reg >> 8; - break; - case 4: - reg = r16(priv, ADM_PS1); - reg = reg >> 12; - break; - case 5: - reg = r16(priv, ADM_PS2); - /* Bits 0, 1, 3 and 4. */ - reg = (reg & 3) | ((reg & 24) >> 1); - break; - default: - return -EINVAL; - } - - link->link = reg & ADM_PS_LS; - if (!link->link) - return 0; - link->aneg = true; - link->duplex = reg & ADM_PS_DS; - link->tx_flow = reg & ADM_PS_FCS; - link->rx_flow = reg & ADM_PS_FCS; - if (reg & ADM_PS_SS) - link->speed = SWITCH_PORT_SPEED_100; - else - link->speed = SWITCH_PORT_SPEED_10; - - return 0; -} - -static int -adm6996_sw_get_port_mib(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val) -{ - struct adm6996_priv *priv = to_adm(dev); - int port; - char *buf = priv->buf; - int i, len = 0; - u32 reg = 0; - - port = val->port_vlan; - if (port >= ADM_NUM_PORTS) - return -EINVAL; - - mutex_lock(&priv->mib_lock); - - len += snprintf(buf + len, sizeof(priv->buf) - len, - "Port %d MIB counters\n", - port); - - for (i = 0; i < ARRAY_SIZE(adm6996_mibs); i++) { - reg = r16(priv, adm6996_mibs[i].offset + ADM_OFFSET_PORT(port)); - reg += r16(priv, adm6996_mibs[i].offset + ADM_OFFSET_PORT(port) + 1) << 16; - len += snprintf(buf + len, sizeof(priv->buf) - len, - "%-12s: %u\n", - adm6996_mibs[i].name, - reg); - } - - mutex_unlock(&priv->mib_lock); - - val->value.s = buf; - val->len = len; - - return 0; -} - -static int -adm6996_get_port_stats(struct switch_dev *dev, int port, - struct switch_port_stats *stats) -{ - struct adm6996_priv *priv = to_adm(dev); - int id; - u32 reg = 0; - - if (port >= ADM_NUM_PORTS) - return -EINVAL; - - mutex_lock(&priv->mib_lock); - - id = ADM6996_MIB_TXB_ID; - reg = r16(priv, adm6996_mibs[id].offset + ADM_OFFSET_PORT(port)); - reg += r16(priv, adm6996_mibs[id].offset + ADM_OFFSET_PORT(port) + 1) << 16; - stats->tx_bytes = reg; - - id = ADM6996_MIB_RXB_ID; - reg = r16(priv, adm6996_mibs[id].offset + ADM_OFFSET_PORT(port)); - reg += r16(priv, adm6996_mibs[id].offset + ADM_OFFSET_PORT(port) + 1) << 16; - stats->rx_bytes = reg; - - mutex_unlock(&priv->mib_lock); - - return 0; -} - -static struct switch_attr adm6996_globals[] = { - { - .type = SWITCH_TYPE_INT, - .name = "enable_vlan", - .description = "Enable VLANs", - .set = adm6996_set_enable_vlan, - .get = adm6996_get_enable_vlan, - }, -#ifdef DEBUG - { - .type = SWITCH_TYPE_INT, - .name = "addr", - .description = - "Direct register access: set register address (0 - 1023)", - .set = adm6996_set_addr, - .get = adm6996_get_addr, - }, - { - .type = SWITCH_TYPE_INT, - .name = "data", - .description = - "Direct register access: read/write to register (0 - 65535)", - .set = adm6996_set_data, - .get = adm6996_get_data, - }, -#endif /* def DEBUG */ -}; - -static struct switch_attr adm6996_port[] = { - { - .type = SWITCH_TYPE_STRING, - .name = "mib", - .description = "Get port's MIB counters", - .set = NULL, - .get = adm6996_sw_get_port_mib, - }, -}; - -static struct switch_attr adm6996_vlan[] = { - { - .type = SWITCH_TYPE_INT, - .name = "vid", - .description = "VLAN ID", - .set = adm6996_set_vid, - .get = adm6996_get_vid, - }, -}; - -static struct switch_dev_ops adm6996_ops = { - .attr_global = { - .attr = adm6996_globals, - .n_attr = ARRAY_SIZE(adm6996_globals), - }, - .attr_port = { - .attr = adm6996_port, - .n_attr = ARRAY_SIZE(adm6996_port), - }, - .attr_vlan = { - .attr = adm6996_vlan, - .n_attr = ARRAY_SIZE(adm6996_vlan), - }, - .get_port_pvid = adm6996_get_pvid, - .set_port_pvid = adm6996_set_pvid, - .get_vlan_ports = adm6996_get_ports, - .set_vlan_ports = adm6996_set_ports, - .apply_config = adm6996_hw_apply, - .reset_switch = adm6996_reset_switch, - .get_port_link = adm6996_get_port_link, - .get_port_stats = adm6996_get_port_stats, -}; - -static int adm6996_switch_init(struct adm6996_priv *priv, const char *alias, struct net_device *netdev) -{ - struct switch_dev *swdev; - u16 test, old; - - if (!priv->model) { - /* Detect type of chip */ - old = r16(priv, ADM_VID_CHECK); - test = old ^ (1 << 12); - w16(priv, ADM_VID_CHECK, test); - test ^= r16(priv, ADM_VID_CHECK); - if (test & (1 << 12)) { - /* - * Bit 12 of this register is read-only. - * This is the FC model. - */ - priv->model = ADM6996FC; - } else { - /* Bit 12 is read-write. This is the M model. */ - priv->model = ADM6996M; - w16(priv, ADM_VID_CHECK, old); - } - } - - swdev = &priv->dev; - swdev->name = (adm6996_model_name[priv->model]); - swdev->cpu_port = ADM_CPU_PORT; - swdev->ports = ADM_NUM_PORTS; - swdev->vlans = ADM_NUM_VLANS; - swdev->ops = &adm6996_ops; - swdev->alias = alias; - - /* The ADM6996L connected through GPIOs does not support any switch - status calls */ - if (priv->model == ADM6996L) { - adm6996_ops.attr_port.n_attr = 0; - adm6996_ops.get_port_link = NULL; - } - - pr_info ("%s: %s model PHY found.\n", alias, swdev->name); - - mutex_lock(&priv->reg_mutex); - adm6996_perform_reset (priv); - mutex_unlock(&priv->reg_mutex); - - if (priv->model == ADM6996M || priv->model == ADM6996L) { - return register_switch(swdev, netdev); - } - - return -ENODEV; -} - -static int adm6996_config_init(struct phy_device *pdev) -{ - struct adm6996_priv *priv; - int ret; - - linkmode_zero(pdev->supported); - linkmode_set_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT, pdev->supported); - linkmode_copy(pdev->advertising, pdev->supported); - - if (pdev->mdio.addr != 0) { - pr_info ("%s: PHY overlaps ADM6996, providing fixed PHY 0x%x.\n" - , pdev->attached_dev->name, pdev->mdio.addr); - return 0; - } - - priv = devm_kzalloc(&pdev->mdio.dev, sizeof(struct adm6996_priv), GFP_KERNEL); - if (!priv) - return -ENOMEM; - - mutex_init(&priv->reg_mutex); - mutex_init(&priv->mib_lock); - priv->priv = pdev; - priv->read = adm6996_read_mii_reg; - priv->write = adm6996_write_mii_reg; - - ret = adm6996_switch_init(priv, pdev->attached_dev->name, pdev->attached_dev); - if (ret < 0) - return ret; - - pdev->priv = priv; - - return 0; -} - -/* - * Warning: phydev->priv is NULL if phydev->mdio.addr != 0 - */ -static int adm6996_read_status(struct phy_device *phydev) -{ - phydev->speed = SPEED_100; - phydev->duplex = DUPLEX_FULL; - phydev->link = 1; - - phydev->state = PHY_RUNNING; - netif_carrier_on(phydev->attached_dev); - phydev->adjust_link(phydev->attached_dev); - - return 0; -} - -/* - * Warning: phydev->priv is NULL if phydev->mdio.addr != 0 - */ -static int adm6996_config_aneg(struct phy_device *phydev) -{ - return 0; -} - -static int adm6996_fixup(struct phy_device *dev) -{ - struct mii_bus *bus = dev->mdio.bus; - u16 reg; - - /* Our custom registers are at PHY addresses 0-10. Claim those. */ - if (dev->mdio.addr > 10) - return 0; - - /* look for the switch on the bus */ - reg = bus->read(bus, PHYADDR(ADM_SIG0)) & ADM_SIG0_MASK; - if (reg != ADM_SIG0_VAL) - return 0; - - reg = bus->read(bus, PHYADDR(ADM_SIG1)) & ADM_SIG1_MASK; - if (reg != ADM_SIG1_VAL) - return 0; - - dev->phy_id = (ADM_SIG0_VAL << 16) | ADM_SIG1_VAL; - - return 0; -} - -static int adm6996_probe(struct phy_device *pdev) -{ - return 0; -} - -static void adm6996_remove(struct phy_device *pdev) -{ - struct adm6996_priv *priv = phy_to_adm(pdev); - - if (priv && (priv->model == ADM6996M || priv->model == ADM6996L)) - unregister_switch(&priv->dev); -} - -static int adm6996_soft_reset(struct phy_device *phydev) -{ - /* we don't need an extra reset */ - return 0; -} - -static struct phy_driver adm6996_phy_driver = { - .name = "Infineon ADM6996", - .phy_id = (ADM_SIG0_VAL << 16) | ADM_SIG1_VAL, - .phy_id_mask = 0xffffffff, - .features = PHY_BASIC_FEATURES, - .probe = adm6996_probe, - .remove = adm6996_remove, - .config_init = &adm6996_config_init, - .config_aneg = &adm6996_config_aneg, - .read_status = &adm6996_read_status, - .soft_reset = adm6996_soft_reset, -}; - -static int adm6996_gpio_probe(struct platform_device *pdev) -{ - struct adm6996_gpio_platform_data *pdata = pdev->dev.platform_data; - struct adm6996_priv *priv; - int ret; - - if (!pdata) - return -EINVAL; - - priv = devm_kzalloc(&pdev->dev, sizeof(struct adm6996_priv), GFP_KERNEL); - if (!priv) - return -ENOMEM; - - mutex_init(&priv->reg_mutex); - mutex_init(&priv->mib_lock); - - priv->eecs = pdata->eecs; - priv->eedi = pdata->eedi; - priv->eesk = pdata->eesk; - - priv->model = pdata->model; - priv->read = adm6996_read_gpio_reg; - priv->write = adm6996_write_gpio_reg; - - ret = devm_gpio_request(&pdev->dev, priv->eecs, "adm_eecs"); - if (ret) - return ret; - ret = devm_gpio_request(&pdev->dev, priv->eedi, "adm_eedi"); - if (ret) - return ret; - ret = devm_gpio_request(&pdev->dev, priv->eesk, "adm_eesk"); - if (ret) - return ret; - - ret = adm6996_switch_init(priv, dev_name(&pdev->dev), NULL); - if (ret < 0) - return ret; - - platform_set_drvdata(pdev, priv); - - return 0; -} - -static int adm6996_gpio_remove(struct platform_device *pdev) -{ - struct adm6996_priv *priv = platform_get_drvdata(pdev); - - if (priv && (priv->model == ADM6996M || priv->model == ADM6996L)) - unregister_switch(&priv->dev); - - return 0; -} - -static struct platform_driver adm6996_gpio_driver = { - .probe = adm6996_gpio_probe, - .remove = adm6996_gpio_remove, - .driver = { - .name = "adm6996_gpio", - }, -}; - -static int __init adm6996_init(void) -{ - int err; - - phy_register_fixup_for_id(PHY_ANY_ID, adm6996_fixup); - err = phy_driver_register(&adm6996_phy_driver, THIS_MODULE); - if (err) - return err; - - err = platform_driver_register(&adm6996_gpio_driver); - if (err) - phy_driver_unregister(&adm6996_phy_driver); - - return err; -} - -static void __exit adm6996_exit(void) -{ - platform_driver_unregister(&adm6996_gpio_driver); - phy_driver_unregister(&adm6996_phy_driver); -} - -module_init(adm6996_init); -module_exit(adm6996_exit); diff --git a/target/linux/generic/files-6.12/drivers/net/phy/adm6996.h b/target/linux/generic/files-6.12/drivers/net/phy/adm6996.h deleted file mode 100644 index 6fd460a465940f..00000000000000 --- a/target/linux/generic/files-6.12/drivers/net/phy/adm6996.h +++ /dev/null @@ -1,186 +0,0 @@ -/* - * ADM6996 switch driver - * - * Copyright (c) 2008 Felix Fietkau - * Copyright (c) 2010,2011 Peter Lebbing - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License v2 as published by the - * Free Software Foundation - */ -#ifndef __ADM6996_H -#define __ADM6996_H - -/* - * ADM_PHY_PORTS: Number of ports with a PHY. - * We only control ports 0 to 3, because if 4 is connected, it is most likely - * not connected to the switch but to a separate MII and MAC for the WAN port. - */ -#define ADM_PHY_PORTS 4 -#define ADM_NUM_PORTS 6 -#define ADM_CPU_PORT 5 - -#define ADM_NUM_VLANS 16 -#define ADM_VLAN_MAX_ID 4094 - -enum admreg { - ADM_EEPROM_BASE = 0x0, - ADM_P0_CFG = ADM_EEPROM_BASE + 1, - ADM_P1_CFG = ADM_EEPROM_BASE + 3, - ADM_P2_CFG = ADM_EEPROM_BASE + 5, - ADM_P3_CFG = ADM_EEPROM_BASE + 7, - ADM_P4_CFG = ADM_EEPROM_BASE + 8, - ADM_P5_CFG = ADM_EEPROM_BASE + 9, - ADM_SYSC0 = ADM_EEPROM_BASE + 0xa, - ADM_VLAN_PRIOMAP = ADM_EEPROM_BASE + 0xe, - ADM_SYSC3 = ADM_EEPROM_BASE + 0x11, - /* Input Force No Tag Enable */ - ADM_IFNTE = ADM_EEPROM_BASE + 0x20, - ADM_VID_CHECK = ADM_EEPROM_BASE + 0x26, - ADM_P0_PVID = ADM_EEPROM_BASE + 0x28, - ADM_P1_PVID = ADM_EEPROM_BASE + 0x29, - /* Output Tag Bypass Enable and P2 PVID */ - ADM_OTBE_P2_PVID = ADM_EEPROM_BASE + 0x2a, - ADM_P3_P4_PVID = ADM_EEPROM_BASE + 0x2b, - ADM_P5_PVID = ADM_EEPROM_BASE + 0x2c, - ADM_EEPROM_EXT_BASE = 0x40, -#define ADM_VLAN_FILT_L(n) (ADM_EEPROM_EXT_BASE + 2 * (n)) -#define ADM_VLAN_FILT_H(n) (ADM_EEPROM_EXT_BASE + 1 + 2 * (n)) -#define ADM_VLAN_MAP(n) (ADM_EEPROM_BASE + 0x13 + n) - ADM_COUNTER_BASE = 0xa0, - ADM_SIG0 = ADM_COUNTER_BASE + 0, - ADM_SIG1 = ADM_COUNTER_BASE + 1, - ADM_PS0 = ADM_COUNTER_BASE + 2, - ADM_PS1 = ADM_COUNTER_BASE + 3, - ADM_PS2 = ADM_COUNTER_BASE + 4, - ADM_CL0 = ADM_COUNTER_BASE + 8, /* RxPacket */ - ADM_CL6 = ADM_COUNTER_BASE + 0x1a, /* RxByte */ - ADM_CL12 = ADM_COUNTER_BASE + 0x2c, /* TxPacket */ - ADM_CL18 = ADM_COUNTER_BASE + 0x3e, /* TxByte */ - ADM_CL24 = ADM_COUNTER_BASE + 0x50, /* Coll */ - ADM_CL30 = ADM_COUNTER_BASE + 0x62, /* Err */ -#define ADM_OFFSET_PORT(n) ((n * 4) - (n / 4) * 2 - (n / 5) * 2) - ADM_PHY_BASE = 0x200, -#define ADM_PHY_PORT(n) (ADM_PHY_BASE + (0x20 * n)) -}; - -/* Chip identification patterns */ -#define ADM_SIG0_MASK 0xffff -#define ADM_SIG0_VAL 0x1023 -#define ADM_SIG1_MASK 0xffff -#define ADM_SIG1_VAL 0x0007 - -enum { - ADM_PHYCFG_COLTST = (1 << 7), /* Enable collision test */ - ADM_PHYCFG_DPLX = (1 << 8), /* Enable full duplex */ - ADM_PHYCFG_ANEN_RST = (1 << 9), /* Restart auto negotiation (self clear) */ - ADM_PHYCFG_ISO = (1 << 10), /* Isolate PHY */ - ADM_PHYCFG_PDN = (1 << 11), /* Power down PHY */ - ADM_PHYCFG_ANEN = (1 << 12), /* Enable auto negotiation */ - ADM_PHYCFG_SPEED_100 = (1 << 13), /* Enable 100 Mbit/s */ - ADM_PHYCFG_LPBK = (1 << 14), /* Enable loopback operation */ - ADM_PHYCFG_RST = (1 << 15), /* Reset the port (self clear) */ - ADM_PHYCFG_INIT = ( - ADM_PHYCFG_RST | - ADM_PHYCFG_SPEED_100 | - ADM_PHYCFG_ANEN | - ADM_PHYCFG_ANEN_RST - ) -}; - -enum { - ADM_PORTCFG_FC = (1 << 0), /* Enable 802.x flow control */ - ADM_PORTCFG_AN = (1 << 1), /* Enable auto-negotiation */ - ADM_PORTCFG_SPEED_100 = (1 << 2), /* Enable 100 Mbit/s */ - ADM_PORTCFG_DPLX = (1 << 3), /* Enable full duplex */ - ADM_PORTCFG_OT = (1 << 4), /* Output tagged packets */ - ADM_PORTCFG_PD = (1 << 5), /* Port disable */ - ADM_PORTCFG_TV_PRIO = (1 << 6), /* 0 = VLAN based priority - * 1 = TOS based priority */ - ADM_PORTCFG_PPE = (1 << 7), /* Port based priority enable */ - ADM_PORTCFG_PP_S = (1 << 8), /* Port based priority, 2 bits */ - ADM_PORTCFG_PVID_BASE = (1 << 10), /* Primary VLAN id, 4 bits */ - ADM_PORTCFG_FSE = (1 << 14), /* Fx select enable */ - ADM_PORTCFG_CAM = (1 << 15), /* Crossover Auto MDIX */ - - ADM_PORTCFG_INIT = ( - ADM_PORTCFG_FC | - ADM_PORTCFG_AN | - ADM_PORTCFG_SPEED_100 | - ADM_PORTCFG_DPLX | - ADM_PORTCFG_CAM - ), - ADM_PORTCFG_CPU = ( - ADM_PORTCFG_FC | - ADM_PORTCFG_SPEED_100 | - ADM_PORTCFG_OT | - ADM_PORTCFG_DPLX - ), -}; - -#define ADM_PORTCFG_PPID(n) ((n & 0x3) << 8) -#define ADM_PORTCFG_PVID(n) ((n & 0xf) << 10) -#define ADM_PORTCFG_PVID_MASK (0xf << 10) - -#define ADM_IFNTE_MASK (0x3f << 9) -#define ADM_VID_CHECK_MASK (0x3f << 6) - -#define ADM_P0_PVID_VAL(n) ((((n) & 0xff0) >> 4) << 0) -#define ADM_P1_PVID_VAL(n) ((((n) & 0xff0) >> 4) << 0) -#define ADM_P2_PVID_VAL(n) ((((n) & 0xff0) >> 4) << 0) -#define ADM_P3_PVID_VAL(n) ((((n) & 0xff0) >> 4) << 0) -#define ADM_P4_PVID_VAL(n) ((((n) & 0xff0) >> 4) << 8) -#define ADM_P5_PVID_VAL(n) ((((n) & 0xff0) >> 4) << 0) -#define ADM_P2_PVID_MASK 0xff - -#define ADM_OTBE(n) (((n) & 0x3f) << 8) -#define ADM_OTBE_MASK (0x3f << 8) - -/* ADM_SYSC0 */ -enum { - ADM_NTTE = (1 << 2), /* New Tag Transmit Enable */ - ADM_RVID1 = (1 << 8) /* Replace VLAN ID 1 */ -}; - -/* Tag Based VLAN in ADM_SYSC3 */ -#define ADM_MAC_CLONE BIT(4) -#define ADM_TBV BIT(5) - -static const u8 adm_portcfg[] = { - [0] = ADM_P0_CFG, - [1] = ADM_P1_CFG, - [2] = ADM_P2_CFG, - [3] = ADM_P3_CFG, - [4] = ADM_P4_CFG, - [5] = ADM_P5_CFG, -}; - -/* Fields in ADM_VLAN_FILT_L(x) */ -#define ADM_VLAN_FILT_FID(n) (((n) & 0xf) << 12) -#define ADM_VLAN_FILT_TAGGED(n) (((n) & 0x3f) << 6) -#define ADM_VLAN_FILT_MEMBER(n) (((n) & 0x3f) << 0) -#define ADM_VLAN_FILT_MEMBER_MASK 0x3f -/* Fields in ADM_VLAN_FILT_H(x) */ -#define ADM_VLAN_FILT_VALID (1 << 15) -#define ADM_VLAN_FILT_VID(n) (((n) & 0xfff) << 0) - -/* Convert ports to a form for ADM6996L VLAN map */ -#define ADM_VLAN_FILT(ports) ((ports & 0x01) | ((ports & 0x02) << 1) | \ - ((ports & 0x04) << 2) | ((ports & 0x08) << 3) | \ - ((ports & 0x10) << 3) | ((ports & 0x20) << 3)) - -/* Port status register */ -enum { - ADM_PS_LS = (1 << 0), /* Link status */ - ADM_PS_SS = (1 << 1), /* Speed status */ - ADM_PS_DS = (1 << 2), /* Duplex status */ - ADM_PS_FCS = (1 << 3) /* Flow control status */ -}; - -/* - * Split the register address in phy id and register - * it will get combined again by the mdio bus op - */ -#define PHYADDR(_reg) ((_reg >> 5) & 0xff), (_reg & 0x1f) - -#endif diff --git a/target/linux/generic/files-6.12/drivers/net/phy/ar8216.c b/target/linux/generic/files-6.12/drivers/net/phy/ar8216.c deleted file mode 100644 index 84b923ffc12518..00000000000000 --- a/target/linux/generic/files-6.12/drivers/net/phy/ar8216.c +++ /dev/null @@ -1,2909 +0,0 @@ -/* - * ar8216.c: AR8216 switch driver - * - * Copyright (C) 2009 Felix Fietkau - * Copyright (C) 2011-2012 Gabor Juhos - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "ar8216.h" - -extern const struct ar8xxx_chip ar8327_chip; -extern const struct ar8xxx_chip ar8337_chip; - -#define MIB_DESC_BASIC(_s , _o, _n) \ - { \ - .size = (_s), \ - .offset = (_o), \ - .name = (_n), \ - .type = AR8XXX_MIB_BASIC, \ - } - -#define MIB_DESC_EXT(_s , _o, _n) \ - { \ - .size = (_s), \ - .offset = (_o), \ - .name = (_n), \ - .type = AR8XXX_MIB_EXTENDED, \ - } - -static const struct ar8xxx_mib_desc ar8216_mibs[] = { - MIB_DESC_EXT(1, AR8216_STATS_RXBROAD, "RxBroad"), - MIB_DESC_EXT(1, AR8216_STATS_RXPAUSE, "RxPause"), - MIB_DESC_EXT(1, AR8216_STATS_RXMULTI, "RxMulti"), - MIB_DESC_EXT(1, AR8216_STATS_RXFCSERR, "RxFcsErr"), - MIB_DESC_EXT(1, AR8216_STATS_RXALIGNERR, "RxAlignErr"), - MIB_DESC_EXT(1, AR8216_STATS_RXRUNT, "RxRunt"), - MIB_DESC_EXT(1, AR8216_STATS_RXFRAGMENT, "RxFragment"), - MIB_DESC_EXT(1, AR8216_STATS_RX64BYTE, "Rx64Byte"), - MIB_DESC_EXT(1, AR8216_STATS_RX128BYTE, "Rx128Byte"), - MIB_DESC_EXT(1, AR8216_STATS_RX256BYTE, "Rx256Byte"), - MIB_DESC_EXT(1, AR8216_STATS_RX512BYTE, "Rx512Byte"), - MIB_DESC_EXT(1, AR8216_STATS_RX1024BYTE, "Rx1024Byte"), - MIB_DESC_EXT(1, AR8216_STATS_RXMAXBYTE, "RxMaxByte"), - MIB_DESC_EXT(1, AR8216_STATS_RXTOOLONG, "RxTooLong"), - MIB_DESC_BASIC(2, AR8216_STATS_RXGOODBYTE, "RxGoodByte"), - MIB_DESC_EXT(2, AR8216_STATS_RXBADBYTE, "RxBadByte"), - MIB_DESC_EXT(1, AR8216_STATS_RXOVERFLOW, "RxOverFlow"), - MIB_DESC_EXT(1, AR8216_STATS_FILTERED, "Filtered"), - MIB_DESC_EXT(1, AR8216_STATS_TXBROAD, "TxBroad"), - MIB_DESC_EXT(1, AR8216_STATS_TXPAUSE, "TxPause"), - MIB_DESC_EXT(1, AR8216_STATS_TXMULTI, "TxMulti"), - MIB_DESC_EXT(1, AR8216_STATS_TXUNDERRUN, "TxUnderRun"), - MIB_DESC_EXT(1, AR8216_STATS_TX64BYTE, "Tx64Byte"), - MIB_DESC_EXT(1, AR8216_STATS_TX128BYTE, "Tx128Byte"), - MIB_DESC_EXT(1, AR8216_STATS_TX256BYTE, "Tx256Byte"), - MIB_DESC_EXT(1, AR8216_STATS_TX512BYTE, "Tx512Byte"), - MIB_DESC_EXT(1, AR8216_STATS_TX1024BYTE, "Tx1024Byte"), - MIB_DESC_EXT(1, AR8216_STATS_TXMAXBYTE, "TxMaxByte"), - MIB_DESC_EXT(1, AR8216_STATS_TXOVERSIZE, "TxOverSize"), - MIB_DESC_BASIC(2, AR8216_STATS_TXBYTE, "TxByte"), - MIB_DESC_EXT(1, AR8216_STATS_TXCOLLISION, "TxCollision"), - MIB_DESC_EXT(1, AR8216_STATS_TXABORTCOL, "TxAbortCol"), - MIB_DESC_EXT(1, AR8216_STATS_TXMULTICOL, "TxMultiCol"), - MIB_DESC_EXT(1, AR8216_STATS_TXSINGLECOL, "TxSingleCol"), - MIB_DESC_EXT(1, AR8216_STATS_TXEXCDEFER, "TxExcDefer"), - MIB_DESC_EXT(1, AR8216_STATS_TXDEFER, "TxDefer"), - MIB_DESC_EXT(1, AR8216_STATS_TXLATECOL, "TxLateCol"), -}; - -const struct ar8xxx_mib_desc ar8236_mibs[39] = { - MIB_DESC_EXT(1, AR8236_STATS_RXBROAD, "RxBroad"), - MIB_DESC_EXT(1, AR8236_STATS_RXPAUSE, "RxPause"), - MIB_DESC_EXT(1, AR8236_STATS_RXMULTI, "RxMulti"), - MIB_DESC_EXT(1, AR8236_STATS_RXFCSERR, "RxFcsErr"), - MIB_DESC_EXT(1, AR8236_STATS_RXALIGNERR, "RxAlignErr"), - MIB_DESC_EXT(1, AR8236_STATS_RXRUNT, "RxRunt"), - MIB_DESC_EXT(1, AR8236_STATS_RXFRAGMENT, "RxFragment"), - MIB_DESC_EXT(1, AR8236_STATS_RX64BYTE, "Rx64Byte"), - MIB_DESC_EXT(1, AR8236_STATS_RX128BYTE, "Rx128Byte"), - MIB_DESC_EXT(1, AR8236_STATS_RX256BYTE, "Rx256Byte"), - MIB_DESC_EXT(1, AR8236_STATS_RX512BYTE, "Rx512Byte"), - MIB_DESC_EXT(1, AR8236_STATS_RX1024BYTE, "Rx1024Byte"), - MIB_DESC_EXT(1, AR8236_STATS_RX1518BYTE, "Rx1518Byte"), - MIB_DESC_EXT(1, AR8236_STATS_RXMAXBYTE, "RxMaxByte"), - MIB_DESC_EXT(1, AR8236_STATS_RXTOOLONG, "RxTooLong"), - MIB_DESC_BASIC(2, AR8236_STATS_RXGOODBYTE, "RxGoodByte"), - MIB_DESC_EXT(2, AR8236_STATS_RXBADBYTE, "RxBadByte"), - MIB_DESC_EXT(1, AR8236_STATS_RXOVERFLOW, "RxOverFlow"), - MIB_DESC_EXT(1, AR8236_STATS_FILTERED, "Filtered"), - MIB_DESC_EXT(1, AR8236_STATS_TXBROAD, "TxBroad"), - MIB_DESC_EXT(1, AR8236_STATS_TXPAUSE, "TxPause"), - MIB_DESC_EXT(1, AR8236_STATS_TXMULTI, "TxMulti"), - MIB_DESC_EXT(1, AR8236_STATS_TXUNDERRUN, "TxUnderRun"), - MIB_DESC_EXT(1, AR8236_STATS_TX64BYTE, "Tx64Byte"), - MIB_DESC_EXT(1, AR8236_STATS_TX128BYTE, "Tx128Byte"), - MIB_DESC_EXT(1, AR8236_STATS_TX256BYTE, "Tx256Byte"), - MIB_DESC_EXT(1, AR8236_STATS_TX512BYTE, "Tx512Byte"), - MIB_DESC_EXT(1, AR8236_STATS_TX1024BYTE, "Tx1024Byte"), - MIB_DESC_EXT(1, AR8236_STATS_TX1518BYTE, "Tx1518Byte"), - MIB_DESC_EXT(1, AR8236_STATS_TXMAXBYTE, "TxMaxByte"), - MIB_DESC_EXT(1, AR8236_STATS_TXOVERSIZE, "TxOverSize"), - MIB_DESC_BASIC(2, AR8236_STATS_TXBYTE, "TxByte"), - MIB_DESC_EXT(1, AR8236_STATS_TXCOLLISION, "TxCollision"), - MIB_DESC_EXT(1, AR8236_STATS_TXABORTCOL, "TxAbortCol"), - MIB_DESC_EXT(1, AR8236_STATS_TXMULTICOL, "TxMultiCol"), - MIB_DESC_EXT(1, AR8236_STATS_TXSINGLECOL, "TxSingleCol"), - MIB_DESC_EXT(1, AR8236_STATS_TXEXCDEFER, "TxExcDefer"), - MIB_DESC_EXT(1, AR8236_STATS_TXDEFER, "TxDefer"), - MIB_DESC_EXT(1, AR8236_STATS_TXLATECOL, "TxLateCol"), -}; - -static DEFINE_MUTEX(ar8xxx_dev_list_lock); -static LIST_HEAD(ar8xxx_dev_list); - -static void -ar8xxx_mib_start(struct ar8xxx_priv *priv); -static void -ar8xxx_mib_stop(struct ar8xxx_priv *priv); - -/* inspired by phy_poll_reset in drivers/net/phy/phy_device.c */ -static int -ar8xxx_phy_poll_reset(struct mii_bus *bus) -{ - unsigned int sleep_msecs = 20; - int ret, elapsed, i; - - for (elapsed = sleep_msecs; elapsed <= 600; - elapsed += sleep_msecs) { - msleep(sleep_msecs); - for (i = 0; i < AR8XXX_NUM_PHYS; i++) { - ret = mdiobus_read(bus, i, MII_BMCR); - if (ret < 0) - return ret; - if (ret & BMCR_RESET) - break; - if (i == AR8XXX_NUM_PHYS - 1) { - usleep_range(1000, 2000); - return 0; - } - } - } - return -ETIMEDOUT; -} - -static int -ar8xxx_phy_check_aneg(struct phy_device *phydev) -{ - int ret; - - if (phydev->autoneg != AUTONEG_ENABLE) - return 0; - /* - * BMCR_ANENABLE might have been cleared - * by phy_init_hw in certain kernel versions - * therefore check for it - */ - ret = phy_read(phydev, MII_BMCR); - if (ret < 0) - return ret; - if (ret & BMCR_ANENABLE) - return 0; - - dev_info(&phydev->mdio.dev, "ANEG disabled, re-enabling ...\n"); - ret |= BMCR_ANENABLE | BMCR_ANRESTART; - return phy_write(phydev, MII_BMCR, ret); -} - -void -ar8xxx_phy_init(struct ar8xxx_priv *priv) -{ - int i; - struct mii_bus *bus; - - bus = priv->sw_mii_bus ?: priv->mii_bus; - for (i = 0; i < AR8XXX_NUM_PHYS; i++) { - if (priv->chip->phy_fixup) - priv->chip->phy_fixup(priv, i); - - /* initialize the port itself */ - mdiobus_write(bus, i, MII_ADVERTISE, - ADVERTISE_ALL | ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM); - if (ar8xxx_has_gige(priv)) - mdiobus_write(bus, i, MII_CTRL1000, ADVERTISE_1000FULL); - mdiobus_write(bus, i, MII_BMCR, BMCR_RESET | BMCR_ANENABLE); - } - - ar8xxx_phy_poll_reset(bus); -} - -u32 -ar8xxx_mii_read32(struct ar8xxx_priv *priv, int phy_id, int regnum) -{ - struct mii_bus *bus = priv->mii_bus; - u16 lo, hi; - - lo = bus->read(bus, phy_id, regnum); - hi = bus->read(bus, phy_id, regnum + 1); - - return (hi << 16) | lo; -} - -void -ar8xxx_mii_write32(struct ar8xxx_priv *priv, int phy_id, int regnum, u32 val) -{ - struct mii_bus *bus = priv->mii_bus; - u16 lo, hi; - - lo = val & 0xffff; - hi = (u16) (val >> 16); - - if (priv->chip->mii_lo_first) - { - bus->write(bus, phy_id, regnum, lo); - bus->write(bus, phy_id, regnum + 1, hi); - } else { - bus->write(bus, phy_id, regnum + 1, hi); - bus->write(bus, phy_id, regnum, lo); - } -} - -u32 -ar8xxx_read(struct ar8xxx_priv *priv, int reg) -{ - struct mii_bus *bus = priv->mii_bus; - u16 r1, r2, page; - u32 val; - - split_addr((u32) reg, &r1, &r2, &page); - - mutex_lock(&bus->mdio_lock); - - bus->write(bus, 0x18, 0, page); - wait_for_page_switch(); - val = ar8xxx_mii_read32(priv, 0x10 | r2, r1); - - mutex_unlock(&bus->mdio_lock); - - return val; -} - -void -ar8xxx_write(struct ar8xxx_priv *priv, int reg, u32 val) -{ - struct mii_bus *bus = priv->mii_bus; - u16 r1, r2, page; - - split_addr((u32) reg, &r1, &r2, &page); - - mutex_lock(&bus->mdio_lock); - - bus->write(bus, 0x18, 0, page); - wait_for_page_switch(); - ar8xxx_mii_write32(priv, 0x10 | r2, r1, val); - - mutex_unlock(&bus->mdio_lock); -} - -u32 -ar8xxx_rmw(struct ar8xxx_priv *priv, int reg, u32 mask, u32 val) -{ - struct mii_bus *bus = priv->mii_bus; - u16 r1, r2, page; - u32 ret; - - split_addr((u32) reg, &r1, &r2, &page); - - mutex_lock(&bus->mdio_lock); - - bus->write(bus, 0x18, 0, page); - wait_for_page_switch(); - - ret = ar8xxx_mii_read32(priv, 0x10 | r2, r1); - ret &= ~mask; - ret |= val; - ar8xxx_mii_write32(priv, 0x10 | r2, r1, ret); - - mutex_unlock(&bus->mdio_lock); - - return ret; -} -void -ar8xxx_phy_dbg_read(struct ar8xxx_priv *priv, int phy_addr, - u16 dbg_addr, u16 *dbg_data) -{ - struct mii_bus *bus = priv->mii_bus; - - mutex_lock(&bus->mdio_lock); - bus->write(bus, phy_addr, MII_ATH_DBG_ADDR, dbg_addr); - *dbg_data = bus->read(bus, phy_addr, MII_ATH_DBG_DATA); - mutex_unlock(&bus->mdio_lock); -} - -void -ar8xxx_phy_dbg_write(struct ar8xxx_priv *priv, int phy_addr, - u16 dbg_addr, u16 dbg_data) -{ - struct mii_bus *bus = priv->mii_bus; - - mutex_lock(&bus->mdio_lock); - bus->write(bus, phy_addr, MII_ATH_DBG_ADDR, dbg_addr); - bus->write(bus, phy_addr, MII_ATH_DBG_DATA, dbg_data); - mutex_unlock(&bus->mdio_lock); -} - -static inline void -ar8xxx_phy_mmd_prep(struct mii_bus *bus, int phy_addr, u16 addr, u16 reg) -{ - bus->write(bus, phy_addr, MII_ATH_MMD_ADDR, addr); - bus->write(bus, phy_addr, MII_ATH_MMD_DATA, reg); - bus->write(bus, phy_addr, MII_ATH_MMD_ADDR, addr | 0x4000); -} - -void -ar8xxx_phy_mmd_write(struct ar8xxx_priv *priv, int phy_addr, u16 addr, u16 reg, u16 data) -{ - struct mii_bus *bus = priv->mii_bus; - - mutex_lock(&bus->mdio_lock); - ar8xxx_phy_mmd_prep(bus, phy_addr, addr, reg); - bus->write(bus, phy_addr, MII_ATH_MMD_DATA, data); - mutex_unlock(&bus->mdio_lock); -} - -u16 -ar8xxx_phy_mmd_read(struct ar8xxx_priv *priv, int phy_addr, u16 addr, u16 reg) -{ - struct mii_bus *bus = priv->mii_bus; - u16 data; - - mutex_lock(&bus->mdio_lock); - ar8xxx_phy_mmd_prep(bus, phy_addr, addr, reg); - data = bus->read(bus, phy_addr, MII_ATH_MMD_DATA); - mutex_unlock(&bus->mdio_lock); - - return data; -} - -static int -ar8xxx_reg_wait(struct ar8xxx_priv *priv, u32 reg, u32 mask, u32 val, - unsigned timeout) -{ - int i; - - for (i = 0; i < timeout; i++) { - u32 t; - - t = ar8xxx_read(priv, reg); - if ((t & mask) == val) - return 0; - - usleep_range(1000, 2000); - cond_resched(); - } - - return -ETIMEDOUT; -} - -static int -ar8xxx_mib_op(struct ar8xxx_priv *priv, u32 op) -{ - unsigned mib_func = priv->chip->mib_func; - int ret; - - lockdep_assert_held(&priv->mib_lock); - - /* Capture the hardware statistics for all ports */ - ar8xxx_rmw(priv, mib_func, AR8216_MIB_FUNC, (op << AR8216_MIB_FUNC_S)); - - /* Wait for the capturing to complete. */ - ret = ar8xxx_reg_wait(priv, mib_func, AR8216_MIB_BUSY, 0, 10); - if (ret) - goto out; - - ret = 0; - -out: - return ret; -} - -static int -ar8xxx_mib_capture(struct ar8xxx_priv *priv) -{ - return ar8xxx_mib_op(priv, AR8216_MIB_FUNC_CAPTURE); -} - -static int -ar8xxx_mib_flush(struct ar8xxx_priv *priv) -{ - return ar8xxx_mib_op(priv, AR8216_MIB_FUNC_FLUSH); -} - -static void -ar8xxx_mib_fetch_port_stat(struct ar8xxx_priv *priv, int port, bool flush) -{ - unsigned int base; - u64 *mib_stats; - int i; - - WARN_ON(port >= priv->dev.ports); - - lockdep_assert_held(&priv->mib_lock); - - base = priv->chip->reg_port_stats_start + - priv->chip->reg_port_stats_length * port; - - mib_stats = &priv->mib_stats[port * priv->chip->num_mibs]; - for (i = 0; i < priv->chip->num_mibs; i++) { - const struct ar8xxx_mib_desc *mib; - u64 t; - - mib = &priv->chip->mib_decs[i]; - if (mib->type > priv->mib_type) - continue; - t = ar8xxx_read(priv, base + mib->offset); - if (mib->size == 2) { - u64 hi; - - hi = ar8xxx_read(priv, base + mib->offset + 4); - t |= hi << 32; - } - - if (flush) - mib_stats[i] = 0; - else - mib_stats[i] += t; - cond_resched(); - } -} - -static void -ar8216_read_port_link(struct ar8xxx_priv *priv, int port, - struct switch_port_link *link) -{ - u32 status; - u32 speed; - - memset(link, '\0', sizeof(*link)); - - status = priv->chip->read_port_status(priv, port); - - link->aneg = !!(status & AR8216_PORT_STATUS_LINK_AUTO); - if (link->aneg) { - link->link = !!(status & AR8216_PORT_STATUS_LINK_UP); - } else { - link->link = true; - - if (priv->get_port_link) { - int err; - - err = priv->get_port_link(port); - if (err >= 0) - link->link = !!err; - } - } - - if (!link->link) - return; - - link->duplex = !!(status & AR8216_PORT_STATUS_DUPLEX); - link->tx_flow = !!(status & AR8216_PORT_STATUS_TXFLOW); - link->rx_flow = !!(status & AR8216_PORT_STATUS_RXFLOW); - - if (link->aneg && link->duplex && priv->chip->read_port_eee_status) - link->eee = priv->chip->read_port_eee_status(priv, port); - - speed = (status & AR8216_PORT_STATUS_SPEED) >> - AR8216_PORT_STATUS_SPEED_S; - - switch (speed) { - case AR8216_PORT_SPEED_10M: - link->speed = SWITCH_PORT_SPEED_10; - break; - case AR8216_PORT_SPEED_100M: - link->speed = SWITCH_PORT_SPEED_100; - break; - case AR8216_PORT_SPEED_1000M: - link->speed = SWITCH_PORT_SPEED_1000; - break; - default: - link->speed = SWITCH_PORT_SPEED_UNKNOWN; - break; - } -} - -#ifdef CONFIG_ETHERNET_PACKET_MANGLE - -static struct sk_buff * -ar8216_mangle_tx(struct net_device *dev, struct sk_buff *skb) -{ - struct ar8xxx_priv *priv = dev->phy_ptr; - unsigned char *buf; - - if (unlikely(!priv)) - goto error; - - if (!priv->vlan) - goto send; - - if (unlikely(skb_headroom(skb) < 2)) { - if (pskb_expand_head(skb, 2, 0, GFP_ATOMIC) < 0) - goto error; - } - - buf = skb_push(skb, 2); - buf[0] = 0x10; - buf[1] = 0x80; - -send: - return skb; - -error: - dev_kfree_skb_any(skb); - return NULL; -} - -static void -ar8216_mangle_rx(struct net_device *dev, struct sk_buff *skb) -{ - struct ar8xxx_priv *priv; - unsigned char *buf; - int port, vlan; - - priv = dev->phy_ptr; - if (!priv) - return; - - /* don't strip the header if vlan mode is disabled */ - if (!priv->vlan) - return; - - /* strip header, get vlan id */ - buf = skb->data; - skb_pull(skb, 2); - - /* check for vlan header presence */ - if ((buf[12 + 2] != 0x81) || (buf[13 + 2] != 0x00)) - return; - - port = buf[0] & 0x7; - - /* no need to fix up packets coming from a tagged source */ - if (priv->vlan_tagged & (1 << port)) - return; - - /* lookup port vid from local table, the switch passes an invalid vlan id */ - vlan = priv->vlan_id[priv->pvid[port]]; - - buf[14 + 2] &= 0xf0; - buf[14 + 2] |= vlan >> 8; - buf[15 + 2] = vlan & 0xff; -} - -#endif - -int -ar8216_wait_bit(struct ar8xxx_priv *priv, int reg, u32 mask, u32 val) -{ - int timeout = 20; - u32 t = 0; - - while (1) { - t = ar8xxx_read(priv, reg); - if ((t & mask) == val) - return 0; - - if (timeout-- <= 0) - break; - - udelay(10); - cond_resched(); - } - - pr_err("ar8216: timeout on reg %08x: %08x & %08x != %08x\n", - (unsigned int) reg, t, mask, val); - return -ETIMEDOUT; -} - -static void -ar8216_vtu_op(struct ar8xxx_priv *priv, u32 op, u32 val) -{ - if (ar8216_wait_bit(priv, AR8216_REG_VTU, AR8216_VTU_ACTIVE, 0)) - return; - if ((op & AR8216_VTU_OP) == AR8216_VTU_OP_LOAD) { - val &= AR8216_VTUDATA_MEMBER; - val |= AR8216_VTUDATA_VALID; - ar8xxx_write(priv, AR8216_REG_VTU_DATA, val); - } - op |= AR8216_VTU_ACTIVE; - ar8xxx_write(priv, AR8216_REG_VTU, op); -} - -static void -ar8216_vtu_flush(struct ar8xxx_priv *priv) -{ - ar8216_vtu_op(priv, AR8216_VTU_OP_FLUSH, 0); -} - -static void -ar8216_vtu_load_vlan(struct ar8xxx_priv *priv, u32 vid, u32 port_mask) -{ - u32 op; - - op = AR8216_VTU_OP_LOAD | (vid << AR8216_VTU_VID_S); - ar8216_vtu_op(priv, op, port_mask); -} - -static int -ar8216_atu_flush(struct ar8xxx_priv *priv) -{ - int ret; - - ret = ar8216_wait_bit(priv, AR8216_REG_ATU_FUNC0, AR8216_ATU_ACTIVE, 0); - if (!ret) - ar8xxx_write(priv, AR8216_REG_ATU_FUNC0, AR8216_ATU_OP_FLUSH | - AR8216_ATU_ACTIVE); - - return ret; -} - -static int -ar8216_atu_flush_port(struct ar8xxx_priv *priv, int port) -{ - u32 t; - int ret; - - ret = ar8216_wait_bit(priv, AR8216_REG_ATU_FUNC0, AR8216_ATU_ACTIVE, 0); - if (!ret) { - t = (port << AR8216_ATU_PORT_NUM_S) | AR8216_ATU_OP_FLUSH_PORT; - t |= AR8216_ATU_ACTIVE; - ar8xxx_write(priv, AR8216_REG_ATU_FUNC0, t); - } - - return ret; -} - -static u32 -ar8216_read_port_status(struct ar8xxx_priv *priv, int port) -{ - return ar8xxx_read(priv, AR8216_REG_PORT_STATUS(port)); -} - -static void -__ar8216_setup_port(struct ar8xxx_priv *priv, int port, u32 members, - bool ath_hdr_en) -{ - u32 header; - u32 egress, ingress; - u32 pvid; - - if (priv->vlan) { - pvid = priv->vlan_id[priv->pvid[port]]; - if (priv->vlan_tagged & (1 << port)) - egress = AR8216_OUT_ADD_VLAN; - else - egress = AR8216_OUT_STRIP_VLAN; - ingress = AR8216_IN_SECURE; - } else { - pvid = port; - egress = AR8216_OUT_KEEP; - ingress = AR8216_IN_PORT_ONLY; - } - - header = ath_hdr_en ? AR8216_PORT_CTRL_HEADER : 0; - - ar8xxx_rmw(priv, AR8216_REG_PORT_CTRL(port), - AR8216_PORT_CTRL_LEARN | AR8216_PORT_CTRL_VLAN_MODE | - AR8216_PORT_CTRL_SINGLE_VLAN | AR8216_PORT_CTRL_STATE | - AR8216_PORT_CTRL_HEADER | AR8216_PORT_CTRL_LEARN_LOCK, - AR8216_PORT_CTRL_LEARN | header | - (egress << AR8216_PORT_CTRL_VLAN_MODE_S) | - (AR8216_PORT_STATE_FORWARD << AR8216_PORT_CTRL_STATE_S)); - - ar8xxx_rmw(priv, AR8216_REG_PORT_VLAN(port), - AR8216_PORT_VLAN_DEST_PORTS | AR8216_PORT_VLAN_MODE | - AR8216_PORT_VLAN_DEFAULT_ID, - (members << AR8216_PORT_VLAN_DEST_PORTS_S) | - (ingress << AR8216_PORT_VLAN_MODE_S) | - (pvid << AR8216_PORT_VLAN_DEFAULT_ID_S)); -} - -static void -ar8216_setup_port(struct ar8xxx_priv *priv, int port, u32 members) -{ - return __ar8216_setup_port(priv, port, members, - chip_is_ar8216(priv) && priv->vlan && - port == AR8216_PORT_CPU); -} - -static int -ar8216_hw_init(struct ar8xxx_priv *priv) -{ - if (priv->initialized) - return 0; - - ar8xxx_write(priv, AR8216_REG_CTRL, AR8216_CTRL_RESET); - ar8xxx_reg_wait(priv, AR8216_REG_CTRL, AR8216_CTRL_RESET, 0, 1000); - - ar8xxx_phy_init(priv); - - priv->initialized = true; - return 0; -} - -static void -ar8216_init_globals(struct ar8xxx_priv *priv) -{ - /* standard atheros magic */ - ar8xxx_write(priv, 0x38, 0xc000050e); - - ar8xxx_rmw(priv, AR8216_REG_GLOBAL_CTRL, - AR8216_GCTRL_MTU, 1518 + 8 + 2); -} - -static void -__ar8216_init_port(struct ar8xxx_priv *priv, int port, - bool cpu_ge, bool flow_en) -{ - /* Enable port learning and tx */ - ar8xxx_write(priv, AR8216_REG_PORT_CTRL(port), - AR8216_PORT_CTRL_LEARN | - (4 << AR8216_PORT_CTRL_STATE_S)); - - ar8xxx_write(priv, AR8216_REG_PORT_VLAN(port), 0); - - if (port == AR8216_PORT_CPU) { - ar8xxx_write(priv, AR8216_REG_PORT_STATUS(port), - AR8216_PORT_STATUS_LINK_UP | - (cpu_ge ? AR8216_PORT_SPEED_1000M : AR8216_PORT_SPEED_100M) | - AR8216_PORT_STATUS_TXMAC | - AR8216_PORT_STATUS_RXMAC | - (flow_en ? AR8216_PORT_STATUS_RXFLOW : 0) | - (flow_en ? AR8216_PORT_STATUS_TXFLOW : 0) | - AR8216_PORT_STATUS_DUPLEX); - } else { - ar8xxx_write(priv, AR8216_REG_PORT_STATUS(port), - AR8216_PORT_STATUS_LINK_AUTO); - } -} - -static void -ar8216_init_port(struct ar8xxx_priv *priv, int port) -{ - __ar8216_init_port(priv, port, ar8xxx_has_gige(priv), - chip_is_ar8316(priv)); -} - -static void -ar8216_wait_atu_ready(struct ar8xxx_priv *priv, u16 r2, u16 r1) -{ - int timeout = 20; - - while (ar8xxx_mii_read32(priv, r2, r1) & AR8216_ATU_ACTIVE && --timeout) { - udelay(10); - cond_resched(); - } - - if (!timeout) - pr_err("ar8216: timeout waiting for atu to become ready\n"); -} - -static void ar8216_get_arl_entry(struct ar8xxx_priv *priv, - struct arl_entry *a, u32 *status, enum arl_op op) -{ - struct mii_bus *bus = priv->mii_bus; - u16 r2, page; - u16 r1_func0, r1_func1, r1_func2; - u32 t, val0, val1, val2; - - split_addr(AR8216_REG_ATU_FUNC0, &r1_func0, &r2, &page); - r2 |= 0x10; - - r1_func1 = (AR8216_REG_ATU_FUNC1 >> 1) & 0x1e; - r1_func2 = (AR8216_REG_ATU_FUNC2 >> 1) & 0x1e; - - switch (op) { - case AR8XXX_ARL_INITIALIZE: - /* all ATU registers are on the same page - * therefore set page only once - */ - bus->write(bus, 0x18, 0, page); - wait_for_page_switch(); - - ar8216_wait_atu_ready(priv, r2, r1_func0); - - ar8xxx_mii_write32(priv, r2, r1_func0, AR8216_ATU_OP_GET_NEXT); - ar8xxx_mii_write32(priv, r2, r1_func1, 0); - ar8xxx_mii_write32(priv, r2, r1_func2, 0); - break; - case AR8XXX_ARL_GET_NEXT: - t = ar8xxx_mii_read32(priv, r2, r1_func0); - t |= AR8216_ATU_ACTIVE; - ar8xxx_mii_write32(priv, r2, r1_func0, t); - ar8216_wait_atu_ready(priv, r2, r1_func0); - - val0 = ar8xxx_mii_read32(priv, r2, r1_func0); - val1 = ar8xxx_mii_read32(priv, r2, r1_func1); - val2 = ar8xxx_mii_read32(priv, r2, r1_func2); - - *status = (val2 & AR8216_ATU_STATUS) >> AR8216_ATU_STATUS_S; - if (!*status) - break; - - a->portmap = (val2 & AR8216_ATU_PORTS) >> AR8216_ATU_PORTS_S; - a->mac[0] = (val0 & AR8216_ATU_ADDR5) >> AR8216_ATU_ADDR5_S; - a->mac[1] = (val0 & AR8216_ATU_ADDR4) >> AR8216_ATU_ADDR4_S; - a->mac[2] = (val1 & AR8216_ATU_ADDR3) >> AR8216_ATU_ADDR3_S; - a->mac[3] = (val1 & AR8216_ATU_ADDR2) >> AR8216_ATU_ADDR2_S; - a->mac[4] = (val1 & AR8216_ATU_ADDR1) >> AR8216_ATU_ADDR1_S; - a->mac[5] = (val1 & AR8216_ATU_ADDR0) >> AR8216_ATU_ADDR0_S; - break; - } -} - -static int -ar8216_phy_read(struct ar8xxx_priv *priv, int addr, int regnum) -{ - u32 t, val = 0xffff; - int err; - - if (addr >= AR8216_NUM_PORTS) - return 0xffff; - t = (regnum << AR8216_MDIO_CTRL_REG_ADDR_S) | - (addr << AR8216_MDIO_CTRL_PHY_ADDR_S) | - AR8216_MDIO_CTRL_MASTER_EN | - AR8216_MDIO_CTRL_BUSY | - AR8216_MDIO_CTRL_CMD_READ; - - ar8xxx_write(priv, AR8216_REG_MDIO_CTRL, t); - err = ar8xxx_reg_wait(priv, AR8216_REG_MDIO_CTRL, - AR8216_MDIO_CTRL_BUSY, 0, 5); - if (!err) - val = ar8xxx_read(priv, AR8216_REG_MDIO_CTRL); - - return val & AR8216_MDIO_CTRL_DATA_M; -} - -static int -ar8216_phy_write(struct ar8xxx_priv *priv, int addr, int regnum, u16 val) -{ - u32 t; - int ret; - - if (addr >= AR8216_NUM_PORTS) - return -EINVAL; - - t = (addr << AR8216_MDIO_CTRL_PHY_ADDR_S) | - (regnum << AR8216_MDIO_CTRL_REG_ADDR_S) | - AR8216_MDIO_CTRL_MASTER_EN | - AR8216_MDIO_CTRL_BUSY | - AR8216_MDIO_CTRL_CMD_WRITE | - val; - - ar8xxx_write(priv, AR8216_REG_MDIO_CTRL, t); - ret = ar8xxx_reg_wait(priv, AR8216_REG_MDIO_CTRL, - AR8216_MDIO_CTRL_BUSY, 0, 5); - - return ret; -} - -static int -ar8229_hw_init(struct ar8xxx_priv *priv) -{ - phy_interface_t phy_if_mode; - - if (priv->initialized) - return 0; - - ar8xxx_write(priv, AR8216_REG_CTRL, AR8216_CTRL_RESET); - ar8xxx_reg_wait(priv, AR8216_REG_CTRL, AR8216_CTRL_RESET, 0, 1000); - - of_get_phy_mode(priv->pdev->of_node, &phy_if_mode); - - if (phy_if_mode == PHY_INTERFACE_MODE_GMII) { - ar8xxx_write(priv, AR8229_REG_OPER_MODE0, - AR8229_OPER_MODE0_MAC_GMII_EN); - } else if (phy_if_mode == PHY_INTERFACE_MODE_MII) { - ar8xxx_write(priv, AR8229_REG_OPER_MODE0, - AR8229_OPER_MODE0_PHY_MII_EN); - } else { - pr_err("ar8229: unsupported mii mode\n"); - return -EINVAL; - } - - if (priv->port4_phy) { - ar8xxx_write(priv, AR8229_REG_OPER_MODE1, - AR8229_REG_OPER_MODE1_PHY4_MII_EN); - /* disable port5 to prevent mii conflict */ - ar8xxx_write(priv, AR8216_REG_PORT_STATUS(5), 0); - } - - ar8xxx_phy_init(priv); - - priv->initialized = true; - return 0; -} - -static void -ar8229_init_globals(struct ar8xxx_priv *priv) -{ - - /* Enable CPU port, and disable mirror port */ - ar8xxx_write(priv, AR8216_REG_GLOBAL_CPUPORT, - AR8216_GLOBAL_CPUPORT_EN | - (15 << AR8216_GLOBAL_CPUPORT_MIRROR_PORT_S)); - - /* Setup TAG priority mapping */ - ar8xxx_write(priv, AR8216_REG_TAG_PRIORITY, 0xfa50); - - /* Enable aging, MAC replacing */ - ar8xxx_write(priv, AR8216_REG_ATU_CTRL, - 0x2b /* 5 min age time */ | - AR8216_ATU_CTRL_AGE_EN | - AR8216_ATU_CTRL_LEARN_CHANGE); - - /* Enable ARP frame acknowledge */ - ar8xxx_reg_set(priv, AR8229_REG_QM_CTRL, - AR8229_QM_CTRL_ARP_EN); - - /* - * Enable Broadcast/unknown multicast and unicast frames - * transmitted to the CPU port. - */ - ar8xxx_reg_set(priv, AR8216_REG_FLOOD_MASK, - AR8229_FLOOD_MASK_BC_DP(0) | - AR8229_FLOOD_MASK_MC_DP(0) | - AR8229_FLOOD_MASK_UC_DP(0)); - - /* setup MTU */ - ar8xxx_rmw(priv, AR8216_REG_GLOBAL_CTRL, - AR8236_GCTRL_MTU, AR8236_GCTRL_MTU); - - /* Enable MIB counters */ - ar8xxx_reg_set(priv, AR8216_REG_MIB_FUNC, - AR8236_MIB_EN); - - /* setup Service TAG */ - ar8xxx_rmw(priv, AR8216_REG_SERVICE_TAG, AR8216_SERVICE_TAG_M, 0); -} - -static void -ar8229_init_port(struct ar8xxx_priv *priv, int port) -{ - __ar8216_init_port(priv, port, true, true); -} - - -static int -ar7240sw_hw_init(struct ar8xxx_priv *priv) -{ - if (priv->initialized) - return 0; - - ar8xxx_write(priv, AR8216_REG_CTRL, AR8216_CTRL_RESET); - ar8xxx_reg_wait(priv, AR8216_REG_CTRL, AR8216_CTRL_RESET, 0, 1000); - - priv->port4_phy = 1; - /* disable port5 to prevent mii conflict */ - ar8xxx_write(priv, AR8216_REG_PORT_STATUS(5), 0); - - ar8xxx_phy_init(priv); - - priv->initialized = true; - return 0; -} - -static void -ar7240sw_init_globals(struct ar8xxx_priv *priv) -{ - - /* Enable CPU port, and disable mirror port */ - ar8xxx_write(priv, AR8216_REG_GLOBAL_CPUPORT, - AR8216_GLOBAL_CPUPORT_EN | - (15 << AR8216_GLOBAL_CPUPORT_MIRROR_PORT_S)); - - /* Setup TAG priority mapping */ - ar8xxx_write(priv, AR8216_REG_TAG_PRIORITY, 0xfa50); - - /* Enable ARP frame acknowledge, aging, MAC replacing */ - ar8xxx_write(priv, AR8216_REG_ATU_CTRL, - AR8216_ATU_CTRL_RESERVED | - 0x2b /* 5 min age time */ | - AR8216_ATU_CTRL_AGE_EN | - AR8216_ATU_CTRL_ARP_EN | - AR8216_ATU_CTRL_LEARN_CHANGE); - - /* Enable Broadcast frames transmitted to the CPU */ - ar8xxx_reg_set(priv, AR8216_REG_FLOOD_MASK, - AR8216_FM_CPU_BROADCAST_EN); - - /* setup MTU */ - ar8xxx_rmw(priv, AR8216_REG_GLOBAL_CTRL, - AR8216_GCTRL_MTU, - AR8216_GCTRL_MTU); - - /* setup Service TAG */ - ar8xxx_rmw(priv, AR8216_REG_SERVICE_TAG, AR8216_SERVICE_TAG_M, 0); -} - -static void -ar7240sw_setup_port(struct ar8xxx_priv *priv, int port, u32 members) -{ - return __ar8216_setup_port(priv, port, members, false); -} - -static void -ar8236_setup_port(struct ar8xxx_priv *priv, int port, u32 members) -{ - u32 egress, ingress; - u32 pvid; - - if (priv->vlan) { - pvid = priv->vlan_id[priv->pvid[port]]; - if (priv->vlan_tagged & (1 << port)) - egress = AR8216_OUT_ADD_VLAN; - else - egress = AR8216_OUT_STRIP_VLAN; - ingress = AR8216_IN_SECURE; - } else { - pvid = port; - egress = AR8216_OUT_KEEP; - ingress = AR8216_IN_PORT_ONLY; - } - - ar8xxx_rmw(priv, AR8216_REG_PORT_CTRL(port), - AR8216_PORT_CTRL_LEARN | AR8216_PORT_CTRL_VLAN_MODE | - AR8216_PORT_CTRL_SINGLE_VLAN | AR8216_PORT_CTRL_STATE | - AR8216_PORT_CTRL_HEADER | AR8216_PORT_CTRL_LEARN_LOCK, - AR8216_PORT_CTRL_LEARN | - (egress << AR8216_PORT_CTRL_VLAN_MODE_S) | - (AR8216_PORT_STATE_FORWARD << AR8216_PORT_CTRL_STATE_S)); - - ar8xxx_rmw(priv, AR8236_REG_PORT_VLAN(port), - AR8236_PORT_VLAN_DEFAULT_ID, - (pvid << AR8236_PORT_VLAN_DEFAULT_ID_S)); - - ar8xxx_rmw(priv, AR8236_REG_PORT_VLAN2(port), - AR8236_PORT_VLAN2_VLAN_MODE | - AR8236_PORT_VLAN2_MEMBER, - (ingress << AR8236_PORT_VLAN2_VLAN_MODE_S) | - (members << AR8236_PORT_VLAN2_MEMBER_S)); -} - -static void -ar8236_init_globals(struct ar8xxx_priv *priv) -{ - /* enable jumbo frames */ - ar8xxx_rmw(priv, AR8216_REG_GLOBAL_CTRL, - AR8316_GCTRL_MTU, 9018 + 8 + 2); - - /* enable cpu port to receive arp frames */ - ar8xxx_reg_set(priv, AR8216_REG_ATU_CTRL, - AR8236_ATU_CTRL_RES); - - /* - * Enable Broadcast/unknown multicast and unicast frames - * transmitted to the CPU port. - */ - ar8xxx_reg_set(priv, AR8216_REG_FLOOD_MASK, - AR8229_FLOOD_MASK_BC_DP(0) | - AR8229_FLOOD_MASK_MC_DP(0) | - AR8229_FLOOD_MASK_UC_DP(0)); - - /* Enable MIB counters */ - ar8xxx_rmw(priv, AR8216_REG_MIB_FUNC, AR8216_MIB_FUNC | AR8236_MIB_EN, - (AR8216_MIB_FUNC_NO_OP << AR8216_MIB_FUNC_S) | - AR8236_MIB_EN); -} - -static int -ar8316_hw_init(struct ar8xxx_priv *priv) -{ - u32 val, newval; - - val = ar8xxx_read(priv, AR8316_REG_POSTRIP); - - if (priv->phy->interface == PHY_INTERFACE_MODE_RGMII) { - if (priv->port4_phy) { - /* value taken from Ubiquiti RouterStation Pro */ - newval = 0x81461bea; - pr_info("ar8316: Using port 4 as PHY\n"); - } else { - newval = 0x01261be2; - pr_info("ar8316: Using port 4 as switch port\n"); - } - } else if (priv->phy->interface == PHY_INTERFACE_MODE_GMII) { - /* value taken from AVM Fritz!Box 7390 sources */ - newval = 0x010e5b71; - } else { - /* no known value for phy interface */ - pr_err("ar8316: unsupported mii mode: %d.\n", - priv->phy->interface); - return -EINVAL; - } - - if (val == newval) - goto out; - - ar8xxx_write(priv, AR8316_REG_POSTRIP, newval); - - if (priv->port4_phy && - priv->phy->interface == PHY_INTERFACE_MODE_RGMII) { - /* work around for phy4 rgmii mode */ - ar8xxx_phy_dbg_write(priv, 4, 0x12, 0x480c); - /* rx delay */ - ar8xxx_phy_dbg_write(priv, 4, 0x0, 0x824e); - /* tx delay */ - ar8xxx_phy_dbg_write(priv, 4, 0x5, 0x3d47); - msleep(1000); - } - - ar8xxx_phy_init(priv); - -out: - priv->initialized = true; - return 0; -} - -static void -ar8316_init_globals(struct ar8xxx_priv *priv) -{ - /* standard atheros magic */ - ar8xxx_write(priv, 0x38, 0xc000050e); - - /* enable cpu port to receive multicast and broadcast frames */ - ar8xxx_write(priv, AR8216_REG_FLOOD_MASK, 0x003f003f); - - /* enable jumbo frames */ - ar8xxx_rmw(priv, AR8216_REG_GLOBAL_CTRL, - AR8316_GCTRL_MTU, 9018 + 8 + 2); - - /* Enable MIB counters */ - ar8xxx_rmw(priv, AR8216_REG_MIB_FUNC, AR8216_MIB_FUNC | AR8236_MIB_EN, - (AR8216_MIB_FUNC_NO_OP << AR8216_MIB_FUNC_S) | - AR8236_MIB_EN); -} - -int -ar8xxx_sw_set_vlan(struct switch_dev *dev, const struct switch_attr *attr, - struct switch_val *val) -{ - struct ar8xxx_priv *priv = swdev_to_ar8xxx(dev); - priv->vlan = !!val->value.i; - return 0; -} - -int -ar8xxx_sw_get_vlan(struct switch_dev *dev, const struct switch_attr *attr, - struct switch_val *val) -{ - struct ar8xxx_priv *priv = swdev_to_ar8xxx(dev); - val->value.i = priv->vlan; - return 0; -} - - -int -ar8xxx_sw_set_pvid(struct switch_dev *dev, int port, int vlan) -{ - struct ar8xxx_priv *priv = swdev_to_ar8xxx(dev); - - /* make sure no invalid PVIDs get set */ - - if (vlan < 0 || vlan >= dev->vlans || - port < 0 || port >= AR8X16_MAX_PORTS) - return -EINVAL; - - priv->pvid[port] = vlan; - return 0; -} - -int -ar8xxx_sw_get_pvid(struct switch_dev *dev, int port, int *vlan) -{ - struct ar8xxx_priv *priv = swdev_to_ar8xxx(dev); - - if (port < 0 || port >= AR8X16_MAX_PORTS) - return -EINVAL; - - *vlan = priv->pvid[port]; - return 0; -} - -static int -ar8xxx_sw_set_vid(struct switch_dev *dev, const struct switch_attr *attr, - struct switch_val *val) -{ - struct ar8xxx_priv *priv = swdev_to_ar8xxx(dev); - - if (val->port_vlan >= dev->vlans) - return -EINVAL; - - priv->vlan_id[val->port_vlan] = val->value.i; - return 0; -} - -static int -ar8xxx_sw_get_vid(struct switch_dev *dev, const struct switch_attr *attr, - struct switch_val *val) -{ - struct ar8xxx_priv *priv = swdev_to_ar8xxx(dev); - val->value.i = priv->vlan_id[val->port_vlan]; - return 0; -} - -int -ar8xxx_sw_get_port_link(struct switch_dev *dev, int port, - struct switch_port_link *link) -{ - struct ar8xxx_priv *priv = swdev_to_ar8xxx(dev); - - ar8216_read_port_link(priv, port, link); - return 0; -} - -static int -ar8xxx_sw_get_ports(struct switch_dev *dev, struct switch_val *val) -{ - struct ar8xxx_priv *priv = swdev_to_ar8xxx(dev); - u8 ports; - int i; - - if (val->port_vlan >= dev->vlans) - return -EINVAL; - - ports = priv->vlan_table[val->port_vlan]; - val->len = 0; - for (i = 0; i < dev->ports; i++) { - struct switch_port *p; - - if (!(ports & (1 << i))) - continue; - - p = &val->value.ports[val->len++]; - p->id = i; - if (priv->vlan_tagged & (1 << i)) - p->flags = (1 << SWITCH_PORT_FLAG_TAGGED); - else - p->flags = 0; - } - return 0; -} - -static int -ar8xxx_sw_set_ports(struct switch_dev *dev, struct switch_val *val) -{ - struct ar8xxx_priv *priv = swdev_to_ar8xxx(dev); - u8 *vt = &priv->vlan_table[val->port_vlan]; - int i, j; - - *vt = 0; - for (i = 0; i < val->len; i++) { - struct switch_port *p = &val->value.ports[i]; - - if (p->flags & (1 << SWITCH_PORT_FLAG_TAGGED)) { - priv->vlan_tagged |= (1 << p->id); - } else { - priv->vlan_tagged &= ~(1 << p->id); - priv->pvid[p->id] = val->port_vlan; - - /* make sure that an untagged port does not - * appear in other vlans */ - for (j = 0; j < dev->vlans; j++) { - if (j == val->port_vlan) - continue; - priv->vlan_table[j] &= ~(1 << p->id); - } - } - - *vt |= 1 << p->id; - } - return 0; -} - -static void -ar8216_set_mirror_regs(struct ar8xxx_priv *priv) -{ - int port; - - /* reset all mirror registers */ - ar8xxx_rmw(priv, AR8216_REG_GLOBAL_CPUPORT, - AR8216_GLOBAL_CPUPORT_MIRROR_PORT, - (0xF << AR8216_GLOBAL_CPUPORT_MIRROR_PORT_S)); - for (port = 0; port < AR8216_NUM_PORTS; port++) { - ar8xxx_reg_clear(priv, AR8216_REG_PORT_CTRL(port), - AR8216_PORT_CTRL_MIRROR_RX); - - ar8xxx_reg_clear(priv, AR8216_REG_PORT_CTRL(port), - AR8216_PORT_CTRL_MIRROR_TX); - } - - /* now enable mirroring if necessary */ - if (priv->source_port >= AR8216_NUM_PORTS || - priv->monitor_port >= AR8216_NUM_PORTS || - priv->source_port == priv->monitor_port) { - return; - } - - ar8xxx_rmw(priv, AR8216_REG_GLOBAL_CPUPORT, - AR8216_GLOBAL_CPUPORT_MIRROR_PORT, - (priv->monitor_port << AR8216_GLOBAL_CPUPORT_MIRROR_PORT_S)); - - if (priv->mirror_rx) - ar8xxx_reg_set(priv, AR8216_REG_PORT_CTRL(priv->source_port), - AR8216_PORT_CTRL_MIRROR_RX); - - if (priv->mirror_tx) - ar8xxx_reg_set(priv, AR8216_REG_PORT_CTRL(priv->source_port), - AR8216_PORT_CTRL_MIRROR_TX); -} - -static inline u32 -ar8xxx_age_time_val(int age_time) -{ - return (age_time + AR8XXX_REG_ARL_CTRL_AGE_TIME_SECS / 2) / - AR8XXX_REG_ARL_CTRL_AGE_TIME_SECS; -} - -static inline void -ar8xxx_set_age_time(struct ar8xxx_priv *priv, int reg) -{ - u32 age_time = ar8xxx_age_time_val(priv->arl_age_time); - ar8xxx_rmw(priv, reg, AR8216_ATU_CTRL_AGE_TIME, age_time << AR8216_ATU_CTRL_AGE_TIME_S); -} - -int -ar8xxx_sw_hw_apply(struct switch_dev *dev) -{ - struct ar8xxx_priv *priv = swdev_to_ar8xxx(dev); - const struct ar8xxx_chip *chip = priv->chip; - u8 portmask[AR8X16_MAX_PORTS]; - int i, j; - - mutex_lock(&priv->reg_mutex); - /* flush all vlan translation unit entries */ - priv->chip->vtu_flush(priv); - - memset(portmask, 0, sizeof(portmask)); - if (!priv->init) { - /* calculate the port destination masks and load vlans - * into the vlan translation unit */ - for (j = 0; j < dev->vlans; j++) { - u8 vp = priv->vlan_table[j]; - - if (!vp) - continue; - - for (i = 0; i < dev->ports; i++) { - u8 mask = (1 << i); - if (vp & mask) - portmask[i] |= vp & ~mask; - } - - chip->vtu_load_vlan(priv, priv->vlan_id[j], - priv->vlan_table[j]); - } - } else { - /* vlan disabled: - * isolate all ports, but connect them to the cpu port */ - for (i = 0; i < dev->ports; i++) { - if (i == AR8216_PORT_CPU) - continue; - - portmask[i] = 1 << AR8216_PORT_CPU; - portmask[AR8216_PORT_CPU] |= (1 << i); - } - } - - /* update the port destination mask registers and tag settings */ - for (i = 0; i < dev->ports; i++) { - chip->setup_port(priv, i, portmask[i]); - } - - chip->set_mirror_regs(priv); - - /* set age time */ - if (chip->reg_arl_ctrl) - ar8xxx_set_age_time(priv, chip->reg_arl_ctrl); - - mutex_unlock(&priv->reg_mutex); - return 0; -} - -int -ar8xxx_sw_reset_switch(struct switch_dev *dev) -{ - struct ar8xxx_priv *priv = swdev_to_ar8xxx(dev); - const struct ar8xxx_chip *chip = priv->chip; - int i; - - mutex_lock(&priv->reg_mutex); - memset(&priv->ar8xxx_priv_volatile, 0, sizeof(priv->ar8xxx_priv_volatile)); - - for (i = 0; i < dev->vlans; i++) - priv->vlan_id[i] = i; - - /* Configure all ports */ - for (i = 0; i < dev->ports; i++) - chip->init_port(priv, i); - - priv->mirror_rx = false; - priv->mirror_tx = false; - priv->source_port = 0; - priv->monitor_port = 0; - priv->arl_age_time = AR8XXX_DEFAULT_ARL_AGE_TIME; - - chip->init_globals(priv); - chip->atu_flush(priv); - - mutex_unlock(&priv->reg_mutex); - - return chip->sw_hw_apply(dev); -} - -int -ar8xxx_sw_set_reset_mibs(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val) -{ - struct ar8xxx_priv *priv = swdev_to_ar8xxx(dev); - unsigned int len; - int ret; - - if (!ar8xxx_has_mib_counters(priv)) - return -EOPNOTSUPP; - - mutex_lock(&priv->mib_lock); - - len = priv->dev.ports * priv->chip->num_mibs * - sizeof(*priv->mib_stats); - memset(priv->mib_stats, '\0', len); - ret = ar8xxx_mib_flush(priv); - if (ret) - goto unlock; - - ret = 0; - -unlock: - mutex_unlock(&priv->mib_lock); - return ret; -} - -int -ar8xxx_sw_set_mib_poll_interval(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val) -{ - struct ar8xxx_priv *priv = swdev_to_ar8xxx(dev); - - if (!ar8xxx_has_mib_counters(priv)) - return -EOPNOTSUPP; - - ar8xxx_mib_stop(priv); - priv->mib_poll_interval = val->value.i; - ar8xxx_mib_start(priv); - - return 0; -} - -int -ar8xxx_sw_get_mib_poll_interval(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val) -{ - struct ar8xxx_priv *priv = swdev_to_ar8xxx(dev); - - if (!ar8xxx_has_mib_counters(priv)) - return -EOPNOTSUPP; - val->value.i = priv->mib_poll_interval; - return 0; -} - -int -ar8xxx_sw_set_mib_type(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val) -{ - struct ar8xxx_priv *priv = swdev_to_ar8xxx(dev); - - if (!ar8xxx_has_mib_counters(priv)) - return -EOPNOTSUPP; - priv->mib_type = val->value.i; - return 0; -} - -int -ar8xxx_sw_get_mib_type(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val) -{ - struct ar8xxx_priv *priv = swdev_to_ar8xxx(dev); - - if (!ar8xxx_has_mib_counters(priv)) - return -EOPNOTSUPP; - val->value.i = priv->mib_type; - return 0; -} - -int -ar8xxx_sw_set_mirror_rx_enable(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val) -{ - struct ar8xxx_priv *priv = swdev_to_ar8xxx(dev); - - mutex_lock(&priv->reg_mutex); - priv->mirror_rx = !!val->value.i; - priv->chip->set_mirror_regs(priv); - mutex_unlock(&priv->reg_mutex); - - return 0; -} - -int -ar8xxx_sw_get_mirror_rx_enable(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val) -{ - struct ar8xxx_priv *priv = swdev_to_ar8xxx(dev); - val->value.i = priv->mirror_rx; - return 0; -} - -int -ar8xxx_sw_set_mirror_tx_enable(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val) -{ - struct ar8xxx_priv *priv = swdev_to_ar8xxx(dev); - - mutex_lock(&priv->reg_mutex); - priv->mirror_tx = !!val->value.i; - priv->chip->set_mirror_regs(priv); - mutex_unlock(&priv->reg_mutex); - - return 0; -} - -int -ar8xxx_sw_get_mirror_tx_enable(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val) -{ - struct ar8xxx_priv *priv = swdev_to_ar8xxx(dev); - val->value.i = priv->mirror_tx; - return 0; -} - -int -ar8xxx_sw_set_mirror_monitor_port(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val) -{ - struct ar8xxx_priv *priv = swdev_to_ar8xxx(dev); - - mutex_lock(&priv->reg_mutex); - priv->monitor_port = val->value.i; - priv->chip->set_mirror_regs(priv); - mutex_unlock(&priv->reg_mutex); - - return 0; -} - -int -ar8xxx_sw_get_mirror_monitor_port(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val) -{ - struct ar8xxx_priv *priv = swdev_to_ar8xxx(dev); - val->value.i = priv->monitor_port; - return 0; -} - -int -ar8xxx_sw_set_mirror_source_port(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val) -{ - struct ar8xxx_priv *priv = swdev_to_ar8xxx(dev); - - mutex_lock(&priv->reg_mutex); - priv->source_port = val->value.i; - priv->chip->set_mirror_regs(priv); - mutex_unlock(&priv->reg_mutex); - - return 0; -} - -int -ar8xxx_sw_get_mirror_source_port(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val) -{ - struct ar8xxx_priv *priv = swdev_to_ar8xxx(dev); - val->value.i = priv->source_port; - return 0; -} - -int -ar8xxx_sw_set_port_reset_mib(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val) -{ - struct ar8xxx_priv *priv = swdev_to_ar8xxx(dev); - int port; - int ret; - - if (!ar8xxx_has_mib_counters(priv)) - return -EOPNOTSUPP; - - port = val->port_vlan; - if (port >= dev->ports) - return -EINVAL; - - mutex_lock(&priv->mib_lock); - ret = ar8xxx_mib_capture(priv); - if (ret) - goto unlock; - - ar8xxx_mib_fetch_port_stat(priv, port, true); - - ret = 0; - -unlock: - mutex_unlock(&priv->mib_lock); - return ret; -} - -static void -ar8xxx_byte_to_str(char *buf, int len, u64 byte) -{ - unsigned long b; - const char *unit; - - if (byte >= 0x40000000) { /* 1 GiB */ - b = byte * 10 / 0x40000000; - unit = "GiB"; - } else if (byte >= 0x100000) { /* 1 MiB */ - b = byte * 10 / 0x100000; - unit = "MiB"; - } else if (byte >= 0x400) { /* 1 KiB */ - b = byte * 10 / 0x400; - unit = "KiB"; - } else { - b = byte; - unit = "Byte"; - } - if (strcmp(unit, "Byte")) - snprintf(buf, len, "%lu.%lu %s", b / 10, b % 10, unit); - else - snprintf(buf, len, "%lu %s", b, unit); -} - -int -ar8xxx_sw_get_port_mib(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val) -{ - struct ar8xxx_priv *priv = swdev_to_ar8xxx(dev); - const struct ar8xxx_chip *chip = priv->chip; - u64 *mib_stats, mib_data; - unsigned int port; - int ret; - char *buf = priv->buf; - char buf1[64]; - const char *mib_name; - int i, len = 0; - bool mib_stats_empty = true; - - if (!ar8xxx_has_mib_counters(priv) || !priv->mib_poll_interval) - return -EOPNOTSUPP; - - port = val->port_vlan; - if (port >= dev->ports) - return -EINVAL; - - mutex_lock(&priv->mib_lock); - ret = ar8xxx_mib_capture(priv); - if (ret) - goto unlock; - - ar8xxx_mib_fetch_port_stat(priv, port, false); - - len += snprintf(buf + len, sizeof(priv->buf) - len, - "MIB counters\n"); - - mib_stats = &priv->mib_stats[port * chip->num_mibs]; - for (i = 0; i < chip->num_mibs; i++) { - if (chip->mib_decs[i].type > priv->mib_type) - continue; - mib_name = chip->mib_decs[i].name; - mib_data = mib_stats[i]; - len += snprintf(buf + len, sizeof(priv->buf) - len, - "%-12s: %llu\n", mib_name, mib_data); - if ((!strcmp(mib_name, "TxByte") || - !strcmp(mib_name, "RxGoodByte")) && - mib_data >= 1024) { - ar8xxx_byte_to_str(buf1, sizeof(buf1), mib_data); - --len; /* discard newline at the end of buf */ - len += snprintf(buf + len, sizeof(priv->buf) - len, - " (%s)\n", buf1); - } - if (mib_stats_empty && mib_data) - mib_stats_empty = false; - } - - if (mib_stats_empty) - len = snprintf(buf, sizeof(priv->buf), "No MIB data"); - - val->value.s = buf; - val->len = len; - - ret = 0; - -unlock: - mutex_unlock(&priv->mib_lock); - return ret; -} - -int -ar8xxx_sw_set_arl_age_time(struct switch_dev *dev, const struct switch_attr *attr, - struct switch_val *val) -{ - struct ar8xxx_priv *priv = swdev_to_ar8xxx(dev); - int age_time = val->value.i; - u32 age_time_val; - - if (age_time < 0) - return -EINVAL; - - age_time_val = ar8xxx_age_time_val(age_time); - if (age_time_val == 0 || age_time_val > 0xffff) - return -EINVAL; - - priv->arl_age_time = age_time; - return 0; -} - -int -ar8xxx_sw_get_arl_age_time(struct switch_dev *dev, const struct switch_attr *attr, - struct switch_val *val) -{ - struct ar8xxx_priv *priv = swdev_to_ar8xxx(dev); - val->value.i = priv->arl_age_time; - return 0; -} - -int -ar8xxx_sw_get_arl_table(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val) -{ - struct ar8xxx_priv *priv = swdev_to_ar8xxx(dev); - struct mii_bus *bus = priv->mii_bus; - const struct ar8xxx_chip *chip = priv->chip; - char *buf = priv->arl_buf; - int i, j, k, len = 0; - struct arl_entry *a, *a1; - u32 status; - - if (!chip->get_arl_entry) - return -EOPNOTSUPP; - - mutex_lock(&priv->reg_mutex); - mutex_lock(&bus->mdio_lock); - - chip->get_arl_entry(priv, NULL, NULL, AR8XXX_ARL_INITIALIZE); - - for(i = 0; i < AR8XXX_NUM_ARL_RECORDS; ++i) { - a = &priv->arl_table[i]; - duplicate: - chip->get_arl_entry(priv, a, &status, AR8XXX_ARL_GET_NEXT); - - if (!status) - break; - - /* avoid duplicates - * ARL table can include multiple valid entries - * per MAC, just with differing status codes - */ - for (j = 0; j < i; ++j) { - a1 = &priv->arl_table[j]; - if (!memcmp(a->mac, a1->mac, sizeof(a->mac))) { - /* ignore ports already seen in former entry */ - a->portmap &= ~a1->portmap; - if (!a->portmap) - goto duplicate; - } - } - } - - mutex_unlock(&bus->mdio_lock); - - len += snprintf(buf + len, sizeof(priv->arl_buf) - len, - "address resolution table\n"); - - if (i == AR8XXX_NUM_ARL_RECORDS) - len += snprintf(buf + len, sizeof(priv->arl_buf) - len, - "Too many entries found, displaying the first %d only!\n", - AR8XXX_NUM_ARL_RECORDS); - - for (j = 0; j < priv->dev.ports; ++j) { - for (k = 0; k < i; ++k) { - a = &priv->arl_table[k]; - if (!(a->portmap & BIT(j))) - continue; - len += snprintf(buf + len, sizeof(priv->arl_buf) - len, - "Port %d: MAC %02x:%02x:%02x:%02x:%02x:%02x\n", - j, - a->mac[5], a->mac[4], a->mac[3], - a->mac[2], a->mac[1], a->mac[0]); - } - } - - val->value.s = buf; - val->len = len; - - mutex_unlock(&priv->reg_mutex); - - return 0; -} - -int -ar8xxx_sw_set_flush_arl_table(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val) -{ - struct ar8xxx_priv *priv = swdev_to_ar8xxx(dev); - int ret; - - mutex_lock(&priv->reg_mutex); - ret = priv->chip->atu_flush(priv); - mutex_unlock(&priv->reg_mutex); - - return ret; -} - -int -ar8xxx_sw_set_flush_port_arl_table(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val) -{ - struct ar8xxx_priv *priv = swdev_to_ar8xxx(dev); - int port, ret; - - port = val->port_vlan; - if (port >= dev->ports) - return -EINVAL; - - mutex_lock(&priv->reg_mutex); - ret = priv->chip->atu_flush_port(priv, port); - mutex_unlock(&priv->reg_mutex); - - return ret; -} - -int -ar8xxx_sw_get_port_stats(struct switch_dev *dev, int port, - struct switch_port_stats *stats) -{ - struct ar8xxx_priv *priv = swdev_to_ar8xxx(dev); - u64 *mib_stats; - - if (!ar8xxx_has_mib_counters(priv) || !priv->mib_poll_interval) - return -EOPNOTSUPP; - - if (!(priv->chip->mib_rxb_id || priv->chip->mib_txb_id)) - return -EOPNOTSUPP; - - if (port >= dev->ports) - return -EINVAL; - - mutex_lock(&priv->mib_lock); - - mib_stats = &priv->mib_stats[port * priv->chip->num_mibs]; - - stats->tx_bytes = mib_stats[priv->chip->mib_txb_id]; - stats->rx_bytes = mib_stats[priv->chip->mib_rxb_id]; - - mutex_unlock(&priv->mib_lock); - return 0; -} - -static int -ar8xxx_phy_read(struct mii_bus *bus, int phy_addr, int reg_addr) -{ - struct ar8xxx_priv *priv = bus->priv; - return priv->chip->phy_read(priv, phy_addr, reg_addr); -} - -static int -ar8xxx_phy_write(struct mii_bus *bus, int phy_addr, int reg_addr, - u16 reg_val) -{ - struct ar8xxx_priv *priv = bus->priv; - return priv->chip->phy_write(priv, phy_addr, reg_addr, reg_val); -} - -static const struct switch_attr ar8xxx_sw_attr_globals[] = { - { - .type = SWITCH_TYPE_INT, - .name = "enable_vlan", - .description = "Enable VLAN mode", - .set = ar8xxx_sw_set_vlan, - .get = ar8xxx_sw_get_vlan, - .max = 1 - }, - { - .type = SWITCH_TYPE_NOVAL, - .name = "reset_mibs", - .description = "Reset all MIB counters", - .set = ar8xxx_sw_set_reset_mibs, - }, - { - .type = SWITCH_TYPE_INT, - .name = "ar8xxx_mib_poll_interval", - .description = "MIB polling interval in msecs (0 to disable)", - .set = ar8xxx_sw_set_mib_poll_interval, - .get = ar8xxx_sw_get_mib_poll_interval - }, - { - .type = SWITCH_TYPE_INT, - .name = "ar8xxx_mib_type", - .description = "MIB type (0=basic 1=extended)", - .set = ar8xxx_sw_set_mib_type, - .get = ar8xxx_sw_get_mib_type - }, - { - .type = SWITCH_TYPE_INT, - .name = "enable_mirror_rx", - .description = "Enable mirroring of RX packets", - .set = ar8xxx_sw_set_mirror_rx_enable, - .get = ar8xxx_sw_get_mirror_rx_enable, - .max = 1 - }, - { - .type = SWITCH_TYPE_INT, - .name = "enable_mirror_tx", - .description = "Enable mirroring of TX packets", - .set = ar8xxx_sw_set_mirror_tx_enable, - .get = ar8xxx_sw_get_mirror_tx_enable, - .max = 1 - }, - { - .type = SWITCH_TYPE_INT, - .name = "mirror_monitor_port", - .description = "Mirror monitor port", - .set = ar8xxx_sw_set_mirror_monitor_port, - .get = ar8xxx_sw_get_mirror_monitor_port, - .max = AR8216_NUM_PORTS - 1 - }, - { - .type = SWITCH_TYPE_INT, - .name = "mirror_source_port", - .description = "Mirror source port", - .set = ar8xxx_sw_set_mirror_source_port, - .get = ar8xxx_sw_get_mirror_source_port, - .max = AR8216_NUM_PORTS - 1 - }, - { - .type = SWITCH_TYPE_STRING, - .name = "arl_table", - .description = "Get ARL table", - .set = NULL, - .get = ar8xxx_sw_get_arl_table, - }, - { - .type = SWITCH_TYPE_NOVAL, - .name = "flush_arl_table", - .description = "Flush ARL table", - .set = ar8xxx_sw_set_flush_arl_table, - }, -}; - -const struct switch_attr ar8xxx_sw_attr_port[] = { - { - .type = SWITCH_TYPE_NOVAL, - .name = "reset_mib", - .description = "Reset single port MIB counters", - .set = ar8xxx_sw_set_port_reset_mib, - }, - { - .type = SWITCH_TYPE_STRING, - .name = "mib", - .description = "Get port's MIB counters", - .set = NULL, - .get = ar8xxx_sw_get_port_mib, - }, - { - .type = SWITCH_TYPE_NOVAL, - .name = "flush_arl_table", - .description = "Flush port's ARL table entries", - .set = ar8xxx_sw_set_flush_port_arl_table, - }, -}; - -const struct switch_attr ar8xxx_sw_attr_vlan[1] = { - { - .type = SWITCH_TYPE_INT, - .name = "vid", - .description = "VLAN ID (0-4094)", - .set = ar8xxx_sw_set_vid, - .get = ar8xxx_sw_get_vid, - .max = 4094, - }, -}; - -static const struct switch_dev_ops ar8xxx_sw_ops = { - .attr_global = { - .attr = ar8xxx_sw_attr_globals, - .n_attr = ARRAY_SIZE(ar8xxx_sw_attr_globals), - }, - .attr_port = { - .attr = ar8xxx_sw_attr_port, - .n_attr = ARRAY_SIZE(ar8xxx_sw_attr_port), - }, - .attr_vlan = { - .attr = ar8xxx_sw_attr_vlan, - .n_attr = ARRAY_SIZE(ar8xxx_sw_attr_vlan), - }, - .get_port_pvid = ar8xxx_sw_get_pvid, - .set_port_pvid = ar8xxx_sw_set_pvid, - .get_vlan_ports = ar8xxx_sw_get_ports, - .set_vlan_ports = ar8xxx_sw_set_ports, - .apply_config = ar8xxx_sw_hw_apply, - .reset_switch = ar8xxx_sw_reset_switch, - .get_port_link = ar8xxx_sw_get_port_link, - .get_port_stats = ar8xxx_sw_get_port_stats, -}; - -static const struct ar8xxx_chip ar7240sw_chip = { - .caps = AR8XXX_CAP_MIB_COUNTERS, - - .reg_port_stats_start = 0x20000, - .reg_port_stats_length = 0x100, - .reg_arl_ctrl = AR8216_REG_ATU_CTRL, - - .name = "Atheros AR724X/AR933X built-in", - .ports = AR7240SW_NUM_PORTS, - .vlans = AR8216_NUM_VLANS, - .swops = &ar8xxx_sw_ops, - - .hw_init = ar7240sw_hw_init, - .init_globals = ar7240sw_init_globals, - .init_port = ar8229_init_port, - .phy_read = ar8216_phy_read, - .phy_write = ar8216_phy_write, - .setup_port = ar7240sw_setup_port, - .read_port_status = ar8216_read_port_status, - .atu_flush = ar8216_atu_flush, - .atu_flush_port = ar8216_atu_flush_port, - .vtu_flush = ar8216_vtu_flush, - .vtu_load_vlan = ar8216_vtu_load_vlan, - .set_mirror_regs = ar8216_set_mirror_regs, - .get_arl_entry = ar8216_get_arl_entry, - .sw_hw_apply = ar8xxx_sw_hw_apply, - - .num_mibs = ARRAY_SIZE(ar8236_mibs), - .mib_decs = ar8236_mibs, - .mib_func = AR8216_REG_MIB_FUNC, - .mib_rxb_id = AR8236_MIB_RXB_ID, - .mib_txb_id = AR8236_MIB_TXB_ID, -}; - -static const struct ar8xxx_chip ar8216_chip = { - .caps = AR8XXX_CAP_MIB_COUNTERS, - - .reg_port_stats_start = 0x19000, - .reg_port_stats_length = 0xa0, - .reg_arl_ctrl = AR8216_REG_ATU_CTRL, - - .name = "Atheros AR8216", - .ports = AR8216_NUM_PORTS, - .vlans = AR8216_NUM_VLANS, - .swops = &ar8xxx_sw_ops, - - .hw_init = ar8216_hw_init, - .init_globals = ar8216_init_globals, - .init_port = ar8216_init_port, - .setup_port = ar8216_setup_port, - .read_port_status = ar8216_read_port_status, - .atu_flush = ar8216_atu_flush, - .atu_flush_port = ar8216_atu_flush_port, - .vtu_flush = ar8216_vtu_flush, - .vtu_load_vlan = ar8216_vtu_load_vlan, - .set_mirror_regs = ar8216_set_mirror_regs, - .get_arl_entry = ar8216_get_arl_entry, - .sw_hw_apply = ar8xxx_sw_hw_apply, - - .num_mibs = ARRAY_SIZE(ar8216_mibs), - .mib_decs = ar8216_mibs, - .mib_func = AR8216_REG_MIB_FUNC, - .mib_rxb_id = AR8216_MIB_RXB_ID, - .mib_txb_id = AR8216_MIB_TXB_ID, -}; - -static const struct ar8xxx_chip ar8229_chip = { - .caps = AR8XXX_CAP_MIB_COUNTERS, - - .reg_port_stats_start = 0x20000, - .reg_port_stats_length = 0x100, - .reg_arl_ctrl = AR8216_REG_ATU_CTRL, - - .name = "Atheros AR8229", - .ports = AR8216_NUM_PORTS, - .vlans = AR8216_NUM_VLANS, - .swops = &ar8xxx_sw_ops, - - .hw_init = ar8229_hw_init, - .init_globals = ar8229_init_globals, - .init_port = ar8229_init_port, - .phy_read = ar8216_phy_read, - .phy_write = ar8216_phy_write, - .setup_port = ar8236_setup_port, - .read_port_status = ar8216_read_port_status, - .atu_flush = ar8216_atu_flush, - .atu_flush_port = ar8216_atu_flush_port, - .vtu_flush = ar8216_vtu_flush, - .vtu_load_vlan = ar8216_vtu_load_vlan, - .set_mirror_regs = ar8216_set_mirror_regs, - .get_arl_entry = ar8216_get_arl_entry, - .sw_hw_apply = ar8xxx_sw_hw_apply, - - .num_mibs = ARRAY_SIZE(ar8236_mibs), - .mib_decs = ar8236_mibs, - .mib_func = AR8216_REG_MIB_FUNC, - .mib_rxb_id = AR8236_MIB_RXB_ID, - .mib_txb_id = AR8236_MIB_TXB_ID, -}; - -static const struct ar8xxx_chip ar8236_chip = { - .caps = AR8XXX_CAP_MIB_COUNTERS, - - .reg_port_stats_start = 0x20000, - .reg_port_stats_length = 0x100, - .reg_arl_ctrl = AR8216_REG_ATU_CTRL, - - .name = "Atheros AR8236", - .ports = AR8216_NUM_PORTS, - .vlans = AR8216_NUM_VLANS, - .swops = &ar8xxx_sw_ops, - - .hw_init = ar8216_hw_init, - .init_globals = ar8236_init_globals, - .init_port = ar8216_init_port, - .setup_port = ar8236_setup_port, - .read_port_status = ar8216_read_port_status, - .atu_flush = ar8216_atu_flush, - .atu_flush_port = ar8216_atu_flush_port, - .vtu_flush = ar8216_vtu_flush, - .vtu_load_vlan = ar8216_vtu_load_vlan, - .set_mirror_regs = ar8216_set_mirror_regs, - .get_arl_entry = ar8216_get_arl_entry, - .sw_hw_apply = ar8xxx_sw_hw_apply, - - .num_mibs = ARRAY_SIZE(ar8236_mibs), - .mib_decs = ar8236_mibs, - .mib_func = AR8216_REG_MIB_FUNC, - .mib_rxb_id = AR8236_MIB_RXB_ID, - .mib_txb_id = AR8236_MIB_TXB_ID, -}; - -static const struct ar8xxx_chip ar8316_chip = { - .caps = AR8XXX_CAP_GIGE | AR8XXX_CAP_MIB_COUNTERS, - - .reg_port_stats_start = 0x20000, - .reg_port_stats_length = 0x100, - .reg_arl_ctrl = AR8216_REG_ATU_CTRL, - - .name = "Atheros AR8316", - .ports = AR8216_NUM_PORTS, - .vlans = AR8X16_MAX_VLANS, - .swops = &ar8xxx_sw_ops, - - .hw_init = ar8316_hw_init, - .init_globals = ar8316_init_globals, - .init_port = ar8216_init_port, - .setup_port = ar8216_setup_port, - .read_port_status = ar8216_read_port_status, - .atu_flush = ar8216_atu_flush, - .atu_flush_port = ar8216_atu_flush_port, - .vtu_flush = ar8216_vtu_flush, - .vtu_load_vlan = ar8216_vtu_load_vlan, - .set_mirror_regs = ar8216_set_mirror_regs, - .get_arl_entry = ar8216_get_arl_entry, - .sw_hw_apply = ar8xxx_sw_hw_apply, - - .num_mibs = ARRAY_SIZE(ar8236_mibs), - .mib_decs = ar8236_mibs, - .mib_func = AR8216_REG_MIB_FUNC, - .mib_rxb_id = AR8236_MIB_RXB_ID, - .mib_txb_id = AR8236_MIB_TXB_ID, -}; - -static int -ar8xxx_read_id(struct ar8xxx_priv *priv) -{ - u32 val; - u16 id; - int i; - - val = ar8xxx_read(priv, AR8216_REG_CTRL); - if (val == ~0) - return -ENODEV; - - id = val & (AR8216_CTRL_REVISION | AR8216_CTRL_VERSION); - for (i = 0; i < AR8X16_PROBE_RETRIES; i++) { - u16 t; - - val = ar8xxx_read(priv, AR8216_REG_CTRL); - if (val == ~0) - return -ENODEV; - - t = val & (AR8216_CTRL_REVISION | AR8216_CTRL_VERSION); - if (t != id) - return -ENODEV; - } - - priv->chip_ver = (id & AR8216_CTRL_VERSION) >> AR8216_CTRL_VERSION_S; - priv->chip_rev = (id & AR8216_CTRL_REVISION); - return 0; -} - -static int -ar8xxx_id_chip(struct ar8xxx_priv *priv) -{ - int ret; - - ret = ar8xxx_read_id(priv); - if(ret) - return ret; - - switch (priv->chip_ver) { - case AR8XXX_VER_AR8216: - priv->chip = &ar8216_chip; - break; - case AR8XXX_VER_AR8236: - priv->chip = &ar8236_chip; - break; - case AR8XXX_VER_AR8316: - priv->chip = &ar8316_chip; - break; - case AR8XXX_VER_AR8327: - priv->chip = &ar8327_chip; - break; - case AR8XXX_VER_AR8337: - priv->chip = &ar8337_chip; - break; - default: - pr_err("ar8216: Unknown Atheros device [ver=%d, rev=%d]\n", - priv->chip_ver, priv->chip_rev); - - return -ENODEV; - } - - return 0; -} - -static void -ar8xxx_mib_work_func(struct work_struct *work) -{ - struct ar8xxx_priv *priv; - int err, i; - - priv = container_of(work, struct ar8xxx_priv, mib_work.work); - - mutex_lock(&priv->mib_lock); - - err = ar8xxx_mib_capture(priv); - if (err) - goto next_attempt; - - for (i = 0; i < priv->dev.ports; i++) - ar8xxx_mib_fetch_port_stat(priv, i, false); - -next_attempt: - mutex_unlock(&priv->mib_lock); - schedule_delayed_work(&priv->mib_work, - msecs_to_jiffies(priv->mib_poll_interval)); -} - -static int -ar8xxx_mib_init(struct ar8xxx_priv *priv) -{ - unsigned int len; - - if (!ar8xxx_has_mib_counters(priv)) - return 0; - - BUG_ON(!priv->chip->mib_decs || !priv->chip->num_mibs); - - len = priv->dev.ports * priv->chip->num_mibs * - sizeof(*priv->mib_stats); - priv->mib_stats = kzalloc(len, GFP_KERNEL); - - if (!priv->mib_stats) - return -ENOMEM; - - return 0; -} - -static void -ar8xxx_mib_start(struct ar8xxx_priv *priv) -{ - if (!ar8xxx_has_mib_counters(priv) || !priv->mib_poll_interval) - return; - - schedule_delayed_work(&priv->mib_work, - msecs_to_jiffies(priv->mib_poll_interval)); -} - -static void -ar8xxx_mib_stop(struct ar8xxx_priv *priv) -{ - if (!ar8xxx_has_mib_counters(priv) || !priv->mib_poll_interval) - return; - - cancel_delayed_work_sync(&priv->mib_work); -} - -static struct ar8xxx_priv * -ar8xxx_create(void) -{ - struct ar8xxx_priv *priv; - - priv = kzalloc(sizeof(struct ar8xxx_priv), GFP_KERNEL); - if (priv == NULL) - return NULL; - - mutex_init(&priv->reg_mutex); - mutex_init(&priv->mib_lock); - INIT_DELAYED_WORK(&priv->mib_work, ar8xxx_mib_work_func); - - return priv; -} - -static void -ar8xxx_free(struct ar8xxx_priv *priv) -{ - if (priv->chip && priv->chip->cleanup) - priv->chip->cleanup(priv); - - kfree(priv->chip_data); - kfree(priv->mib_stats); - kfree(priv); -} - -static int -ar8xxx_probe_switch(struct ar8xxx_priv *priv) -{ - const struct ar8xxx_chip *chip; - struct switch_dev *swdev; - int ret; - - chip = priv->chip; - - swdev = &priv->dev; - swdev->cpu_port = AR8216_PORT_CPU; - swdev->name = chip->name; - swdev->vlans = chip->vlans; - swdev->ports = chip->ports; - swdev->ops = chip->swops; - - ret = ar8xxx_mib_init(priv); - if (ret) - return ret; - - return 0; -} - -static int -ar8xxx_start(struct ar8xxx_priv *priv) -{ - int ret; - - priv->init = true; - - ret = priv->chip->hw_init(priv); - if (ret) - return ret; - - ret = ar8xxx_sw_reset_switch(&priv->dev); - if (ret) - return ret; - - priv->init = false; - - ar8xxx_mib_start(priv); - - return 0; -} - -static int -ar8xxx_phy_config_init(struct phy_device *phydev) -{ - struct ar8xxx_priv *priv = phydev->priv; -#ifdef CONFIG_ETHERNET_PACKET_MANGLE - struct net_device *dev = phydev->attached_dev; -#endif - int ret; - - if (WARN_ON(!priv)) - return -ENODEV; - - if (priv->chip->config_at_probe) - return ar8xxx_phy_check_aneg(phydev); - - priv->phy = phydev; - - if (phydev->mdio.addr != 0) { - if (chip_is_ar8316(priv)) { - /* switch device has been initialized, reinit */ - priv->dev.ports = (AR8216_NUM_PORTS - 1); - priv->initialized = false; - priv->port4_phy = true; - ar8316_hw_init(priv); - return 0; - } - - return 0; - } - - ret = ar8xxx_start(priv); - if (ret) - return ret; - -#ifdef CONFIG_ETHERNET_PACKET_MANGLE - /* VID fixup only needed on ar8216 */ - if (chip_is_ar8216(priv)) { - dev->phy_ptr = priv; - dev->priv_flags |= IFF_NO_IP_ALIGN; - dev->eth_mangle_rx = ar8216_mangle_rx; - dev->eth_mangle_tx = ar8216_mangle_tx; - } -#endif - - return 0; -} - -static bool -ar8xxx_check_link_states(struct ar8xxx_priv *priv) -{ - bool link_new, changed = false; - u32 status; - int i; - - mutex_lock(&priv->reg_mutex); - - for (i = 0; i < priv->dev.ports; i++) { - status = priv->chip->read_port_status(priv, i); - link_new = !!(status & AR8216_PORT_STATUS_LINK_UP); - if (link_new == priv->link_up[i]) - continue; - - priv->link_up[i] = link_new; - changed = true; - /* flush ARL entries for this port if it went down*/ - if (!link_new) - priv->chip->atu_flush_port(priv, i); - dev_info(&priv->phy->mdio.dev, "Port %d is %s\n", - i, link_new ? "up" : "down"); - } - - mutex_unlock(&priv->reg_mutex); - - return changed; -} - -static int -ar8xxx_phy_read_status(struct phy_device *phydev) -{ - struct ar8xxx_priv *priv = phydev->priv; - struct switch_port_link link; - - /* check for switch port link changes */ - ar8xxx_check_link_states(priv); - - if (phydev->mdio.addr != 0) - return genphy_read_status(phydev); - - ar8216_read_port_link(priv, phydev->mdio.addr, &link); - phydev->link = !!link.link; - if (!phydev->link) - return 0; - - switch (link.speed) { - case SWITCH_PORT_SPEED_10: - phydev->speed = SPEED_10; - break; - case SWITCH_PORT_SPEED_100: - phydev->speed = SPEED_100; - break; - case SWITCH_PORT_SPEED_1000: - phydev->speed = SPEED_1000; - break; - default: - phydev->speed = 0; - } - phydev->duplex = link.duplex ? DUPLEX_FULL : DUPLEX_HALF; - - phydev->state = PHY_RUNNING; - netif_carrier_on(phydev->attached_dev); - if (phydev->adjust_link) - phydev->adjust_link(phydev->attached_dev); - - return 0; -} - -static int -ar8xxx_phy_config_aneg(struct phy_device *phydev) -{ - if (phydev->mdio.addr == 0) - return 0; - - return genphy_config_aneg(phydev); -} - -static int -ar8xxx_get_features(struct phy_device *phydev) -{ - struct ar8xxx_priv *priv = phydev->priv; - - linkmode_copy(phydev->supported, PHY_BASIC_FEATURES); - if (ar8xxx_has_gige(priv)) - linkmode_set_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT, phydev->supported); - - return 0; -} - -static const u32 ar8xxx_phy_ids[] = { - 0x004dd033, - 0x004dd034, /* AR8327 */ - 0x004dd036, /* AR8337 */ - 0x004dd041, - 0x004dd042, - 0x004dd043, /* AR8236 */ -}; - -static bool -ar8xxx_phy_match(u32 phy_id) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(ar8xxx_phy_ids); i++) - if (phy_id == ar8xxx_phy_ids[i]) - return true; - - return false; -} - -static bool -ar8xxx_is_possible(struct mii_bus *bus) -{ - unsigned int i, found_phys = 0; - - for (i = 0; i < 5; i++) { - u32 phy_id; - - phy_id = mdiobus_read(bus, i, MII_PHYSID1) << 16; - phy_id |= mdiobus_read(bus, i, MII_PHYSID2); - if (ar8xxx_phy_match(phy_id)) { - found_phys++; - } else if (phy_id) { - pr_debug("ar8xxx: unknown PHY at %s:%02x id:%08x\n", - dev_name(&bus->dev), i, phy_id); - } - } - return !!found_phys; -} - -static int -ar8xxx_phy_probe(struct phy_device *phydev) -{ - struct ar8xxx_priv *priv; - struct switch_dev *swdev; - int ret; - - /* skip PHYs at unused adresses */ - if (phydev->mdio.addr != 0 && phydev->mdio.addr != 3 && phydev->mdio.addr != 4) - return -ENODEV; - - if (!ar8xxx_is_possible(phydev->mdio.bus)) - return -ENODEV; - - mutex_lock(&ar8xxx_dev_list_lock); - list_for_each_entry(priv, &ar8xxx_dev_list, list) - if (priv->mii_bus == phydev->mdio.bus) - goto found; - - priv = ar8xxx_create(); - if (priv == NULL) { - ret = -ENOMEM; - goto unlock; - } - - priv->mii_bus = phydev->mdio.bus; - priv->pdev = &phydev->mdio.dev; - - ret = of_property_read_u32(priv->pdev->of_node, "qca,mib-poll-interval", - &priv->mib_poll_interval); - if (ret) - priv->mib_poll_interval = 0; - - ret = ar8xxx_id_chip(priv); - if (ret) - goto free_priv; - - ret = ar8xxx_probe_switch(priv); - if (ret) - goto free_priv; - - swdev = &priv->dev; - swdev->alias = dev_name(&priv->mii_bus->dev); - ret = register_switch(swdev, NULL); - if (ret) - goto free_priv; - - pr_info("%s: %s rev. %u switch registered on %s\n", - swdev->devname, swdev->name, priv->chip_rev, - dev_name(&priv->mii_bus->dev)); - - list_add(&priv->list, &ar8xxx_dev_list); - -found: - priv->use_count++; - - if (phydev->mdio.addr == 0 && priv->chip->config_at_probe) { - priv->phy = phydev; - - ret = ar8xxx_start(priv); - if (ret) - goto err_unregister_switch; - } else if (priv->chip->phy_rgmii_set) { - priv->chip->phy_rgmii_set(priv, phydev); - } - - phydev->priv = priv; - - mutex_unlock(&ar8xxx_dev_list_lock); - - return 0; - -err_unregister_switch: - if (--priv->use_count) - goto unlock; - - unregister_switch(&priv->dev); - -free_priv: - ar8xxx_free(priv); -unlock: - mutex_unlock(&ar8xxx_dev_list_lock); - return ret; -} - -static void -ar8xxx_phy_detach(struct phy_device *phydev) -{ - struct net_device *dev = phydev->attached_dev; - - if (!dev) - return; - -#ifdef CONFIG_ETHERNET_PACKET_MANGLE - dev->phy_ptr = NULL; - dev->priv_flags &= ~IFF_NO_IP_ALIGN; - dev->eth_mangle_rx = NULL; - dev->eth_mangle_tx = NULL; -#endif -} - -static void -ar8xxx_phy_remove(struct phy_device *phydev) -{ - struct ar8xxx_priv *priv = phydev->priv; - - if (WARN_ON(!priv)) - return; - - phydev->priv = NULL; - - mutex_lock(&ar8xxx_dev_list_lock); - - if (--priv->use_count > 0) { - mutex_unlock(&ar8xxx_dev_list_lock); - return; - } - - list_del(&priv->list); - mutex_unlock(&ar8xxx_dev_list_lock); - - unregister_switch(&priv->dev); - ar8xxx_mib_stop(priv); - ar8xxx_free(priv); -} - -static struct phy_driver ar8xxx_phy_driver[] = { - { - .phy_id = 0x004d0000, - .name = "Atheros AR8216/AR8236/AR8316", - .phy_id_mask = 0xffff0000, - .probe = ar8xxx_phy_probe, - .remove = ar8xxx_phy_remove, - .detach = ar8xxx_phy_detach, - .config_init = ar8xxx_phy_config_init, - .config_aneg = ar8xxx_phy_config_aneg, - .read_status = ar8xxx_phy_read_status, - .get_features = ar8xxx_get_features, - } -}; - -static const struct of_device_id ar8xxx_mdiodev_of_match[] = { - { - .compatible = "qca,ar7240sw", - .data = &ar7240sw_chip, - }, { - .compatible = "qca,ar8229", - .data = &ar8229_chip, - }, { - .compatible = "qca,ar8236", - .data = &ar8236_chip, - }, { - .compatible = "qca,ar8327", - .data = &ar8327_chip, - }, - { /* sentinel */ }, -}; - -static int -ar8xxx_mdiodev_probe(struct mdio_device *mdiodev) -{ - const struct of_device_id *match; - struct ar8xxx_priv *priv; - struct switch_dev *swdev; - struct device_node *mdio_node; - int ret; - - match = of_match_device(ar8xxx_mdiodev_of_match, &mdiodev->dev); - if (!match) - return -EINVAL; - - priv = ar8xxx_create(); - if (priv == NULL) - return -ENOMEM; - - priv->mii_bus = mdiodev->bus; - priv->pdev = &mdiodev->dev; - priv->chip = (const struct ar8xxx_chip *) match->data; - - ret = of_property_read_u32(priv->pdev->of_node, "qca,mib-poll-interval", - &priv->mib_poll_interval); - if (ret) - priv->mib_poll_interval = 0; - - ret = ar8xxx_read_id(priv); - if (ret) - goto free_priv; - - ret = ar8xxx_probe_switch(priv); - if (ret) - goto free_priv; - - if (priv->chip->phy_read && priv->chip->phy_write) { - priv->sw_mii_bus = devm_mdiobus_alloc(&mdiodev->dev); - priv->sw_mii_bus->name = "ar8xxx-mdio"; - priv->sw_mii_bus->read = ar8xxx_phy_read; - priv->sw_mii_bus->write = ar8xxx_phy_write; - priv->sw_mii_bus->priv = priv; - priv->sw_mii_bus->parent = &mdiodev->dev; - snprintf(priv->sw_mii_bus->id, MII_BUS_ID_SIZE, "%s", - dev_name(&mdiodev->dev)); - mdio_node = of_get_child_by_name(priv->pdev->of_node, "mdio-bus"); - ret = of_mdiobus_register(priv->sw_mii_bus, mdio_node); - if (ret) - goto free_priv; - } - - swdev = &priv->dev; - swdev->alias = dev_name(&mdiodev->dev); - - if (of_property_read_bool(priv->pdev->of_node, "qca,phy4-mii-enable")) { - priv->port4_phy = true; - swdev->ports--; - } - - ret = register_switch(swdev, NULL); - if (ret) - goto free_priv; - - pr_info("%s: %s rev. %u switch registered on %s\n", - swdev->devname, swdev->name, priv->chip_rev, - dev_name(&priv->mii_bus->dev)); - - mutex_lock(&ar8xxx_dev_list_lock); - list_add(&priv->list, &ar8xxx_dev_list); - mutex_unlock(&ar8xxx_dev_list_lock); - - priv->use_count++; - - ret = ar8xxx_start(priv); - if (ret) - goto err_unregister_switch; - - dev_set_drvdata(&mdiodev->dev, priv); - - return 0; - -err_unregister_switch: - if (--priv->use_count) - return ret; - - unregister_switch(&priv->dev); - -free_priv: - ar8xxx_free(priv); - return ret; -} - -static void -ar8xxx_mdiodev_remove(struct mdio_device *mdiodev) -{ - struct ar8xxx_priv *priv = dev_get_drvdata(&mdiodev->dev); - - if (WARN_ON(!priv)) - return; - - mutex_lock(&ar8xxx_dev_list_lock); - - if (--priv->use_count > 0) { - mutex_unlock(&ar8xxx_dev_list_lock); - return; - } - - list_del(&priv->list); - mutex_unlock(&ar8xxx_dev_list_lock); - - unregister_switch(&priv->dev); - ar8xxx_mib_stop(priv); - if(priv->sw_mii_bus) - mdiobus_unregister(priv->sw_mii_bus); - ar8xxx_free(priv); -} - -static struct mdio_driver ar8xxx_mdio_driver = { - .probe = ar8xxx_mdiodev_probe, - .remove = ar8xxx_mdiodev_remove, - .mdiodrv.driver = { - .name = "ar8xxx-switch", - .of_match_table = ar8xxx_mdiodev_of_match, - }, -}; - -static int __init ar8216_init(void) -{ - int ret; - - ret = phy_drivers_register(ar8xxx_phy_driver, - ARRAY_SIZE(ar8xxx_phy_driver), - THIS_MODULE); - if (ret) - return ret; - - ret = mdio_driver_register(&ar8xxx_mdio_driver); - if (ret) - phy_drivers_unregister(ar8xxx_phy_driver, - ARRAY_SIZE(ar8xxx_phy_driver)); - - return ret; -} -module_init(ar8216_init); - -static void __exit ar8216_exit(void) -{ - mdio_driver_unregister(&ar8xxx_mdio_driver); - phy_drivers_unregister(ar8xxx_phy_driver, - ARRAY_SIZE(ar8xxx_phy_driver)); -} -module_exit(ar8216_exit); - -MODULE_LICENSE("GPL"); diff --git a/target/linux/generic/files-6.12/drivers/net/phy/ar8216.h b/target/linux/generic/files-6.12/drivers/net/phy/ar8216.h deleted file mode 100644 index f046b35f43fba9..00000000000000 --- a/target/linux/generic/files-6.12/drivers/net/phy/ar8216.h +++ /dev/null @@ -1,725 +0,0 @@ -/* - * ar8216.h: AR8216 switch driver - * - * Copyright (C) 2009 Felix Fietkau - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#ifndef __AR8216_H -#define __AR8216_H - -#define BITS(_s, _n) (((1UL << (_n)) - 1) << _s) - -#define AR8XXX_CAP_GIGE BIT(0) -#define AR8XXX_CAP_MIB_COUNTERS BIT(1) - -#define AR8XXX_NUM_PHYS 5 -#define AR8216_PORT_CPU 0 -#define AR8216_NUM_PORTS 6 -#define AR8216_NUM_VLANS 16 -#define AR7240SW_NUM_PORTS 5 -#define AR8316_NUM_VLANS 4096 - -/* size of the vlan table */ -#define AR8X16_MAX_VLANS 128 -#define AR83X7_MAX_VLANS 4096 -#define AR8XXX_MAX_VLANS AR83X7_MAX_VLANS - -#define AR8X16_PROBE_RETRIES 10 -#define AR8X16_MAX_PORTS 8 - -#define AR8XXX_REG_ARL_CTRL_AGE_TIME_SECS 7 -#define AR8XXX_DEFAULT_ARL_AGE_TIME 300 - -/* Atheros specific MII registers */ -#define MII_ATH_MMD_ADDR 0x0d -#define MII_ATH_MMD_DATA 0x0e -#define MII_ATH_DBG_ADDR 0x1d -#define MII_ATH_DBG_DATA 0x1e - -#define AR8216_REG_CTRL 0x0000 -#define AR8216_CTRL_REVISION BITS(0, 8) -#define AR8216_CTRL_REVISION_S 0 -#define AR8216_CTRL_VERSION BITS(8, 8) -#define AR8216_CTRL_VERSION_S 8 -#define AR8216_CTRL_RESET BIT(31) - -#define AR8216_REG_FLOOD_MASK 0x002C -#define AR8216_FM_UNI_DEST_PORTS BITS(0, 6) -#define AR8216_FM_MULTI_DEST_PORTS BITS(16, 6) -#define AR8216_FM_CPU_BROADCAST_EN BIT(26) -#define AR8229_FLOOD_MASK_UC_DP(_p) BIT(_p) -#define AR8229_FLOOD_MASK_MC_DP(_p) BIT(16 + (_p)) -#define AR8229_FLOOD_MASK_BC_DP(_p) BIT(25 + (_p)) - -#define AR8216_REG_GLOBAL_CTRL 0x0030 -#define AR8216_GCTRL_MTU BITS(0, 11) -#define AR8236_GCTRL_MTU BITS(0, 14) -#define AR8316_GCTRL_MTU BITS(0, 14) - -#define AR8216_REG_VTU 0x0040 -#define AR8216_VTU_OP BITS(0, 3) -#define AR8216_VTU_OP_NOOP 0x0 -#define AR8216_VTU_OP_FLUSH 0x1 -#define AR8216_VTU_OP_LOAD 0x2 -#define AR8216_VTU_OP_PURGE 0x3 -#define AR8216_VTU_OP_REMOVE_PORT 0x4 -#define AR8216_VTU_ACTIVE BIT(3) -#define AR8216_VTU_FULL BIT(4) -#define AR8216_VTU_PORT BITS(8, 4) -#define AR8216_VTU_PORT_S 8 -#define AR8216_VTU_VID BITS(16, 12) -#define AR8216_VTU_VID_S 16 -#define AR8216_VTU_PRIO BITS(28, 3) -#define AR8216_VTU_PRIO_S 28 -#define AR8216_VTU_PRIO_EN BIT(31) - -#define AR8216_REG_VTU_DATA 0x0044 -#define AR8216_VTUDATA_MEMBER BITS(0, 10) -#define AR8236_VTUDATA_MEMBER BITS(0, 7) -#define AR8216_VTUDATA_VALID BIT(11) - -#define AR8216_REG_ATU_FUNC0 0x0050 -#define AR8216_ATU_OP BITS(0, 3) -#define AR8216_ATU_OP_NOOP 0x0 -#define AR8216_ATU_OP_FLUSH 0x1 -#define AR8216_ATU_OP_LOAD 0x2 -#define AR8216_ATU_OP_PURGE 0x3 -#define AR8216_ATU_OP_FLUSH_UNLOCKED 0x4 -#define AR8216_ATU_OP_FLUSH_PORT 0x5 -#define AR8216_ATU_OP_GET_NEXT 0x6 -#define AR8216_ATU_ACTIVE BIT(3) -#define AR8216_ATU_PORT_NUM BITS(8, 4) -#define AR8216_ATU_PORT_NUM_S 8 -#define AR8216_ATU_FULL_VIO BIT(12) -#define AR8216_ATU_ADDR5 BITS(16, 8) -#define AR8216_ATU_ADDR5_S 16 -#define AR8216_ATU_ADDR4 BITS(24, 8) -#define AR8216_ATU_ADDR4_S 24 - -#define AR8216_REG_ATU_FUNC1 0x0054 -#define AR8216_ATU_ADDR3 BITS(0, 8) -#define AR8216_ATU_ADDR3_S 0 -#define AR8216_ATU_ADDR2 BITS(8, 8) -#define AR8216_ATU_ADDR2_S 8 -#define AR8216_ATU_ADDR1 BITS(16, 8) -#define AR8216_ATU_ADDR1_S 16 -#define AR8216_ATU_ADDR0 BITS(24, 8) -#define AR8216_ATU_ADDR0_S 24 - -#define AR8216_REG_ATU_FUNC2 0x0058 -#define AR8216_ATU_PORTS BITS(0, 6) -#define AR8216_ATU_PORTS_S 0 -#define AR8216_ATU_PORT0 BIT(0) -#define AR8216_ATU_PORT1 BIT(1) -#define AR8216_ATU_PORT2 BIT(2) -#define AR8216_ATU_PORT3 BIT(3) -#define AR8216_ATU_PORT4 BIT(4) -#define AR8216_ATU_PORT5 BIT(5) -#define AR8216_ATU_STATUS BITS(16, 4) -#define AR8216_ATU_STATUS_S 16 - -#define AR8216_REG_ATU_CTRL 0x005C -#define AR8216_ATU_CTRL_AGE_EN BIT(17) -#define AR8216_ATU_CTRL_AGE_TIME BITS(0, 16) -#define AR8216_ATU_CTRL_AGE_TIME_S 0 -#define AR8236_ATU_CTRL_RES BIT(20) -#define AR8216_ATU_CTRL_LEARN_CHANGE BIT(18) -#define AR8216_ATU_CTRL_RESERVED BIT(19) -#define AR8216_ATU_CTRL_ARP_EN BIT(20) - -#define AR8216_REG_TAG_PRIORITY 0x0070 - -#define AR8216_REG_SERVICE_TAG 0x0074 -#define AR8216_SERVICE_TAG_M BITS(0, 16) - -#define AR8216_REG_MIB_FUNC 0x0080 -#define AR8216_MIB_TIMER BITS(0, 16) -#define AR8216_MIB_AT_HALF_EN BIT(16) -#define AR8216_MIB_BUSY BIT(17) -#define AR8216_MIB_FUNC BITS(24, 3) -#define AR8216_MIB_FUNC_S 24 -#define AR8216_MIB_FUNC_NO_OP 0x0 -#define AR8216_MIB_FUNC_FLUSH 0x1 -#define AR8216_MIB_FUNC_CAPTURE 0x3 -#define AR8236_MIB_EN BIT(30) - -#define AR8216_REG_GLOBAL_CPUPORT 0x0078 -#define AR8216_GLOBAL_CPUPORT_MIRROR_PORT BITS(4, 4) -#define AR8216_GLOBAL_CPUPORT_MIRROR_PORT_S 4 -#define AR8216_GLOBAL_CPUPORT_EN BIT(8) - -#define AR8216_REG_MDIO_CTRL 0x98 -#define AR8216_MDIO_CTRL_DATA_M BITS(0, 16) -#define AR8216_MDIO_CTRL_REG_ADDR_S 16 -#define AR8216_MDIO_CTRL_PHY_ADDR_S 21 -#define AR8216_MDIO_CTRL_CMD_WRITE 0 -#define AR8216_MDIO_CTRL_CMD_READ BIT(27) -#define AR8216_MDIO_CTRL_MASTER_EN BIT(30) -#define AR8216_MDIO_CTRL_BUSY BIT(31) - -#define AR8216_PORT_OFFSET(_i) (0x0100 * (_i + 1)) -#define AR8216_REG_PORT_STATUS(_i) (AR8216_PORT_OFFSET(_i) + 0x0000) -#define AR8216_PORT_STATUS_SPEED BITS(0,2) -#define AR8216_PORT_STATUS_SPEED_S 0 -#define AR8216_PORT_STATUS_TXMAC BIT(2) -#define AR8216_PORT_STATUS_RXMAC BIT(3) -#define AR8216_PORT_STATUS_TXFLOW BIT(4) -#define AR8216_PORT_STATUS_RXFLOW BIT(5) -#define AR8216_PORT_STATUS_DUPLEX BIT(6) -#define AR8216_PORT_STATUS_LINK_UP BIT(8) -#define AR8216_PORT_STATUS_LINK_AUTO BIT(9) -#define AR8216_PORT_STATUS_LINK_PAUSE BIT(10) -#define AR8216_PORT_STATUS_FLOW_CONTROL BIT(12) - -#define AR8216_REG_PORT_CTRL(_i) (AR8216_PORT_OFFSET(_i) + 0x0004) - -/* port forwarding state */ -#define AR8216_PORT_CTRL_STATE BITS(0, 3) -#define AR8216_PORT_CTRL_STATE_S 0 - -#define AR8216_PORT_CTRL_LEARN_LOCK BIT(7) - -/* egress 802.1q mode */ -#define AR8216_PORT_CTRL_VLAN_MODE BITS(8, 2) -#define AR8216_PORT_CTRL_VLAN_MODE_S 8 - -#define AR8216_PORT_CTRL_IGMP_SNOOP BIT(10) -#define AR8216_PORT_CTRL_HEADER BIT(11) -#define AR8216_PORT_CTRL_MAC_LOOP BIT(12) -#define AR8216_PORT_CTRL_SINGLE_VLAN BIT(13) -#define AR8216_PORT_CTRL_LEARN BIT(14) -#define AR8216_PORT_CTRL_MIRROR_TX BIT(16) -#define AR8216_PORT_CTRL_MIRROR_RX BIT(17) - -#define AR8216_REG_PORT_VLAN(_i) (AR8216_PORT_OFFSET(_i) + 0x0008) - -#define AR8216_PORT_VLAN_DEFAULT_ID BITS(0, 12) -#define AR8216_PORT_VLAN_DEFAULT_ID_S 0 - -#define AR8216_PORT_VLAN_DEST_PORTS BITS(16, 9) -#define AR8216_PORT_VLAN_DEST_PORTS_S 16 - -/* bit0 added to the priority field of egress frames */ -#define AR8216_PORT_VLAN_TX_PRIO BIT(27) - -/* port default priority */ -#define AR8216_PORT_VLAN_PRIORITY BITS(28, 2) -#define AR8216_PORT_VLAN_PRIORITY_S 28 - -/* ingress 802.1q mode */ -#define AR8216_PORT_VLAN_MODE BITS(30, 2) -#define AR8216_PORT_VLAN_MODE_S 30 - -#define AR8216_REG_PORT_RATE(_i) (AR8216_PORT_OFFSET(_i) + 0x000c) -#define AR8216_REG_PORT_PRIO(_i) (AR8216_PORT_OFFSET(_i) + 0x0010) - -#define AR8216_STATS_RXBROAD 0x00 -#define AR8216_STATS_RXPAUSE 0x04 -#define AR8216_STATS_RXMULTI 0x08 -#define AR8216_STATS_RXFCSERR 0x0c -#define AR8216_STATS_RXALIGNERR 0x10 -#define AR8216_STATS_RXRUNT 0x14 -#define AR8216_STATS_RXFRAGMENT 0x18 -#define AR8216_STATS_RX64BYTE 0x1c -#define AR8216_STATS_RX128BYTE 0x20 -#define AR8216_STATS_RX256BYTE 0x24 -#define AR8216_STATS_RX512BYTE 0x28 -#define AR8216_STATS_RX1024BYTE 0x2c -#define AR8216_STATS_RXMAXBYTE 0x30 -#define AR8216_STATS_RXTOOLONG 0x34 -#define AR8216_STATS_RXGOODBYTE 0x38 -#define AR8216_STATS_RXBADBYTE 0x40 -#define AR8216_STATS_RXOVERFLOW 0x48 -#define AR8216_STATS_FILTERED 0x4c -#define AR8216_STATS_TXBROAD 0x50 -#define AR8216_STATS_TXPAUSE 0x54 -#define AR8216_STATS_TXMULTI 0x58 -#define AR8216_STATS_TXUNDERRUN 0x5c -#define AR8216_STATS_TX64BYTE 0x60 -#define AR8216_STATS_TX128BYTE 0x64 -#define AR8216_STATS_TX256BYTE 0x68 -#define AR8216_STATS_TX512BYTE 0x6c -#define AR8216_STATS_TX1024BYTE 0x70 -#define AR8216_STATS_TXMAXBYTE 0x74 -#define AR8216_STATS_TXOVERSIZE 0x78 -#define AR8216_STATS_TXBYTE 0x7c -#define AR8216_STATS_TXCOLLISION 0x84 -#define AR8216_STATS_TXABORTCOL 0x88 -#define AR8216_STATS_TXMULTICOL 0x8c -#define AR8216_STATS_TXSINGLECOL 0x90 -#define AR8216_STATS_TXEXCDEFER 0x94 -#define AR8216_STATS_TXDEFER 0x98 -#define AR8216_STATS_TXLATECOL 0x9c - -#define AR8216_MIB_RXB_ID 14 /* RxGoodByte */ -#define AR8216_MIB_TXB_ID 29 /* TxByte */ - -#define AR8229_REG_OPER_MODE0 0x04 -#define AR8229_OPER_MODE0_MAC_GMII_EN BIT(6) -#define AR8229_OPER_MODE0_PHY_MII_EN BIT(10) - -#define AR8229_REG_OPER_MODE1 0x08 -#define AR8229_REG_OPER_MODE1_PHY4_MII_EN BIT(28) - -#define AR8229_REG_QM_CTRL 0x3c -#define AR8229_QM_CTRL_ARP_EN BIT(15) - -#define AR8236_REG_PORT_VLAN(_i) (AR8216_PORT_OFFSET((_i)) + 0x0008) -#define AR8236_PORT_VLAN_DEFAULT_ID BITS(16, 12) -#define AR8236_PORT_VLAN_DEFAULT_ID_S 16 -#define AR8236_PORT_VLAN_PRIORITY BITS(29, 3) -#define AR8236_PORT_VLAN_PRIORITY_S 28 - -#define AR8236_REG_PORT_VLAN2(_i) (AR8216_PORT_OFFSET((_i)) + 0x000c) -#define AR8236_PORT_VLAN2_MEMBER BITS(16, 7) -#define AR8236_PORT_VLAN2_MEMBER_S 16 -#define AR8236_PORT_VLAN2_TX_PRIO BIT(23) -#define AR8236_PORT_VLAN2_VLAN_MODE BITS(30, 2) -#define AR8236_PORT_VLAN2_VLAN_MODE_S 30 - -#define AR8236_STATS_RXBROAD 0x00 -#define AR8236_STATS_RXPAUSE 0x04 -#define AR8236_STATS_RXMULTI 0x08 -#define AR8236_STATS_RXFCSERR 0x0c -#define AR8236_STATS_RXALIGNERR 0x10 -#define AR8236_STATS_RXRUNT 0x14 -#define AR8236_STATS_RXFRAGMENT 0x18 -#define AR8236_STATS_RX64BYTE 0x1c -#define AR8236_STATS_RX128BYTE 0x20 -#define AR8236_STATS_RX256BYTE 0x24 -#define AR8236_STATS_RX512BYTE 0x28 -#define AR8236_STATS_RX1024BYTE 0x2c -#define AR8236_STATS_RX1518BYTE 0x30 -#define AR8236_STATS_RXMAXBYTE 0x34 -#define AR8236_STATS_RXTOOLONG 0x38 -#define AR8236_STATS_RXGOODBYTE 0x3c -#define AR8236_STATS_RXBADBYTE 0x44 -#define AR8236_STATS_RXOVERFLOW 0x4c -#define AR8236_STATS_FILTERED 0x50 -#define AR8236_STATS_TXBROAD 0x54 -#define AR8236_STATS_TXPAUSE 0x58 -#define AR8236_STATS_TXMULTI 0x5c -#define AR8236_STATS_TXUNDERRUN 0x60 -#define AR8236_STATS_TX64BYTE 0x64 -#define AR8236_STATS_TX128BYTE 0x68 -#define AR8236_STATS_TX256BYTE 0x6c -#define AR8236_STATS_TX512BYTE 0x70 -#define AR8236_STATS_TX1024BYTE 0x74 -#define AR8236_STATS_TX1518BYTE 0x78 -#define AR8236_STATS_TXMAXBYTE 0x7c -#define AR8236_STATS_TXOVERSIZE 0x80 -#define AR8236_STATS_TXBYTE 0x84 -#define AR8236_STATS_TXCOLLISION 0x8c -#define AR8236_STATS_TXABORTCOL 0x90 -#define AR8236_STATS_TXMULTICOL 0x94 -#define AR8236_STATS_TXSINGLECOL 0x98 -#define AR8236_STATS_TXEXCDEFER 0x9c -#define AR8236_STATS_TXDEFER 0xa0 -#define AR8236_STATS_TXLATECOL 0xa4 - -#define AR8236_MIB_RXB_ID 15 /* RxGoodByte */ -#define AR8236_MIB_TXB_ID 31 /* TxByte */ - -#define AR8316_REG_POSTRIP 0x0008 -#define AR8316_POSTRIP_MAC0_GMII_EN BIT(0) -#define AR8316_POSTRIP_MAC0_RGMII_EN BIT(1) -#define AR8316_POSTRIP_PHY4_GMII_EN BIT(2) -#define AR8316_POSTRIP_PHY4_RGMII_EN BIT(3) -#define AR8316_POSTRIP_MAC0_MAC_MODE BIT(4) -#define AR8316_POSTRIP_RTL_MODE BIT(5) -#define AR8316_POSTRIP_RGMII_RXCLK_DELAY_EN BIT(6) -#define AR8316_POSTRIP_RGMII_TXCLK_DELAY_EN BIT(7) -#define AR8316_POSTRIP_SERDES_EN BIT(8) -#define AR8316_POSTRIP_SEL_ANA_RST BIT(9) -#define AR8316_POSTRIP_GATE_25M_EN BIT(10) -#define AR8316_POSTRIP_SEL_CLK25M BIT(11) -#define AR8316_POSTRIP_HIB_PULSE_HW BIT(12) -#define AR8316_POSTRIP_DBG_MODE_I BIT(13) -#define AR8316_POSTRIP_MAC5_MAC_MODE BIT(14) -#define AR8316_POSTRIP_MAC5_PHY_MODE BIT(15) -#define AR8316_POSTRIP_POWER_DOWN_HW BIT(16) -#define AR8316_POSTRIP_LPW_STATE_EN BIT(17) -#define AR8316_POSTRIP_MAN_EN BIT(18) -#define AR8316_POSTRIP_PHY_PLL_ON BIT(19) -#define AR8316_POSTRIP_LPW_EXIT BIT(20) -#define AR8316_POSTRIP_TXDELAY_S0 BIT(21) -#define AR8316_POSTRIP_TXDELAY_S1 BIT(22) -#define AR8316_POSTRIP_RXDELAY_S0 BIT(23) -#define AR8316_POSTRIP_LED_OPEN_EN BIT(24) -#define AR8316_POSTRIP_SPI_EN BIT(25) -#define AR8316_POSTRIP_RXDELAY_S1 BIT(26) -#define AR8316_POSTRIP_POWER_ON_SEL BIT(31) - -/* port speed */ -enum { - AR8216_PORT_SPEED_10M = 0, - AR8216_PORT_SPEED_100M = 1, - AR8216_PORT_SPEED_1000M = 2, - AR8216_PORT_SPEED_ERR = 3, -}; - -/* ingress 802.1q mode */ -enum { - AR8216_IN_PORT_ONLY = 0, - AR8216_IN_PORT_FALLBACK = 1, - AR8216_IN_VLAN_ONLY = 2, - AR8216_IN_SECURE = 3 -}; - -/* egress 802.1q mode */ -enum { - AR8216_OUT_KEEP = 0, - AR8216_OUT_STRIP_VLAN = 1, - AR8216_OUT_ADD_VLAN = 2 -}; - -/* port forwarding state */ -enum { - AR8216_PORT_STATE_DISABLED = 0, - AR8216_PORT_STATE_BLOCK = 1, - AR8216_PORT_STATE_LISTEN = 2, - AR8216_PORT_STATE_LEARN = 3, - AR8216_PORT_STATE_FORWARD = 4 -}; - -/* mib counter type */ -enum { - AR8XXX_MIB_BASIC = 0, - AR8XXX_MIB_EXTENDED = 1 -}; - -enum { - AR8XXX_VER_AR8216 = 0x01, - AR8XXX_VER_AR8236 = 0x03, - AR8XXX_VER_AR8316 = 0x10, - AR8XXX_VER_AR8327 = 0x12, - AR8XXX_VER_AR8337 = 0x13, -}; - -#define AR8XXX_NUM_ARL_RECORDS 100 - -enum arl_op { - AR8XXX_ARL_INITIALIZE, - AR8XXX_ARL_GET_NEXT -}; - -struct arl_entry { - u16 portmap; - u8 mac[6]; -}; - -struct ar8xxx_priv; - -struct ar8xxx_mib_desc { - unsigned int size; - unsigned int offset; - const char *name; - u8 type; -}; - -struct ar8xxx_chip { - unsigned long caps; - bool config_at_probe; - bool mii_lo_first; - - /* parameters to calculate REG_PORT_STATS_BASE */ - unsigned reg_port_stats_start; - unsigned reg_port_stats_length; - - unsigned reg_arl_ctrl; - - int (*hw_init)(struct ar8xxx_priv *priv); - void (*cleanup)(struct ar8xxx_priv *priv); - - const char *name; - int vlans; - int ports; - const struct switch_dev_ops *swops; - - void (*init_globals)(struct ar8xxx_priv *priv); - void (*init_port)(struct ar8xxx_priv *priv, int port); - void (*setup_port)(struct ar8xxx_priv *priv, int port, u32 members); - u32 (*read_port_status)(struct ar8xxx_priv *priv, int port); - u32 (*read_port_eee_status)(struct ar8xxx_priv *priv, int port); - int (*atu_flush)(struct ar8xxx_priv *priv); - int (*atu_flush_port)(struct ar8xxx_priv *priv, int port); - void (*vtu_flush)(struct ar8xxx_priv *priv); - void (*vtu_load_vlan)(struct ar8xxx_priv *priv, u32 vid, u32 port_mask); - void (*phy_fixup)(struct ar8xxx_priv *priv, int phy); - void (*set_mirror_regs)(struct ar8xxx_priv *priv); - void (*get_arl_entry)(struct ar8xxx_priv *priv, struct arl_entry *a, - u32 *status, enum arl_op op); - int (*sw_hw_apply)(struct switch_dev *dev); - void (*phy_rgmii_set)(struct ar8xxx_priv *priv, struct phy_device *phydev); - int (*phy_read)(struct ar8xxx_priv *priv, int addr, int regnum); - int (*phy_write)(struct ar8xxx_priv *priv, int addr, int regnum, u16 val); - - const struct ar8xxx_mib_desc *mib_decs; - unsigned num_mibs; - unsigned mib_func; - int mib_rxb_id; - int mib_txb_id; -}; - -struct ar8xxx_priv { - struct switch_dev dev; - struct mii_bus *mii_bus; - struct mii_bus *sw_mii_bus; - struct phy_device *phy; - struct device *pdev; - - int (*get_port_link)(unsigned port); - - const struct net_device_ops *ndo_old; - struct net_device_ops ndo; - struct mutex reg_mutex; - u8 chip_ver; - u8 chip_rev; - const struct ar8xxx_chip *chip; - void *chip_data; - bool initialized; - bool port4_phy; - char buf[2048]; - struct arl_entry arl_table[AR8XXX_NUM_ARL_RECORDS]; - char arl_buf[AR8XXX_NUM_ARL_RECORDS * 32 + 256]; - bool link_up[AR8X16_MAX_PORTS]; - - bool init; - - struct mutex mib_lock; - struct delayed_work mib_work; - u64 *mib_stats; - u32 mib_poll_interval; - u8 mib_type; - - struct list_head list; - unsigned int use_count; - - /* all fields below are cleared on reset */ - struct_group(ar8xxx_priv_volatile, - bool vlan; - - u16 vlan_id[AR8XXX_MAX_VLANS]; - u8 vlan_table[AR8XXX_MAX_VLANS]; - u8 vlan_tagged; - u16 pvid[AR8X16_MAX_PORTS]; - int arl_age_time; - - /* mirroring */ - bool mirror_rx; - bool mirror_tx; - int source_port; - int monitor_port; - u8 port_vlan_prio[AR8X16_MAX_PORTS]; - ); -}; - -u32 -ar8xxx_mii_read32(struct ar8xxx_priv *priv, int phy_id, int regnum); -void -ar8xxx_mii_write32(struct ar8xxx_priv *priv, int phy_id, int regnum, u32 val); -u32 -ar8xxx_read(struct ar8xxx_priv *priv, int reg); -void -ar8xxx_write(struct ar8xxx_priv *priv, int reg, u32 val); -u32 -ar8xxx_rmw(struct ar8xxx_priv *priv, int reg, u32 mask, u32 val); - -void -ar8xxx_phy_dbg_read(struct ar8xxx_priv *priv, int phy_addr, - u16 dbg_addr, u16 *dbg_data); -void -ar8xxx_phy_dbg_write(struct ar8xxx_priv *priv, int phy_addr, - u16 dbg_addr, u16 dbg_data); -void -ar8xxx_phy_mmd_write(struct ar8xxx_priv *priv, int phy_addr, u16 addr, u16 reg, u16 data); -u16 -ar8xxx_phy_mmd_read(struct ar8xxx_priv *priv, int phy_addr, u16 addr, u16 reg); -void -ar8xxx_phy_init(struct ar8xxx_priv *priv); -int -ar8xxx_sw_set_vlan(struct switch_dev *dev, const struct switch_attr *attr, - struct switch_val *val); -int -ar8xxx_sw_get_vlan(struct switch_dev *dev, const struct switch_attr *attr, - struct switch_val *val); -int -ar8xxx_sw_set_reset_mibs(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val); -int -ar8xxx_sw_set_mib_poll_interval(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val); -int -ar8xxx_sw_get_mib_poll_interval(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val); -int -ar8xxx_sw_set_mib_type(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val); -int -ar8xxx_sw_get_mib_type(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val); -int -ar8xxx_sw_set_mirror_rx_enable(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val); -int -ar8xxx_sw_get_mirror_rx_enable(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val); -int -ar8xxx_sw_set_mirror_tx_enable(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val); -int -ar8xxx_sw_get_mirror_tx_enable(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val); -int -ar8xxx_sw_set_mirror_monitor_port(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val); -int -ar8xxx_sw_get_mirror_monitor_port(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val); -int -ar8xxx_sw_set_mirror_source_port(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val); -int -ar8xxx_sw_get_mirror_source_port(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val); -int -ar8xxx_sw_set_pvid(struct switch_dev *dev, int port, int vlan); -int -ar8xxx_sw_get_pvid(struct switch_dev *dev, int port, int *vlan); -int -ar8xxx_sw_hw_apply(struct switch_dev *dev); -int -ar8xxx_sw_reset_switch(struct switch_dev *dev); -int -ar8xxx_sw_get_port_link(struct switch_dev *dev, int port, - struct switch_port_link *link); -int -ar8xxx_sw_set_port_reset_mib(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val); -int -ar8xxx_sw_get_port_mib(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val); -int -ar8xxx_sw_get_arl_age_time(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val); -int -ar8xxx_sw_set_arl_age_time(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val); -int -ar8xxx_sw_get_arl_table(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val); -int -ar8xxx_sw_set_flush_arl_table(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val); -int -ar8xxx_sw_set_flush_port_arl_table(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val); -int -ar8xxx_sw_get_port_stats(struct switch_dev *dev, int port, - struct switch_port_stats *stats); -int -ar8216_wait_bit(struct ar8xxx_priv *priv, int reg, u32 mask, u32 val); - -static inline struct ar8xxx_priv * -swdev_to_ar8xxx(struct switch_dev *swdev) -{ - return container_of(swdev, struct ar8xxx_priv, dev); -} - -static inline bool ar8xxx_has_gige(struct ar8xxx_priv *priv) -{ - return priv->chip->caps & AR8XXX_CAP_GIGE; -} - -static inline bool ar8xxx_has_mib_counters(struct ar8xxx_priv *priv) -{ - return priv->chip->caps & AR8XXX_CAP_MIB_COUNTERS; -} - -static inline bool chip_is_ar8216(struct ar8xxx_priv *priv) -{ - return priv->chip_ver == AR8XXX_VER_AR8216; -} - -static inline bool chip_is_ar8236(struct ar8xxx_priv *priv) -{ - return priv->chip_ver == AR8XXX_VER_AR8236; -} - -static inline bool chip_is_ar8316(struct ar8xxx_priv *priv) -{ - return priv->chip_ver == AR8XXX_VER_AR8316; -} - -static inline bool chip_is_ar8327(struct ar8xxx_priv *priv) -{ - return priv->chip_ver == AR8XXX_VER_AR8327; -} - -static inline bool chip_is_ar8337(struct ar8xxx_priv *priv) -{ - return priv->chip_ver == AR8XXX_VER_AR8337; -} - -static inline void -ar8xxx_reg_set(struct ar8xxx_priv *priv, int reg, u32 val) -{ - ar8xxx_rmw(priv, reg, 0, val); -} - -static inline void -ar8xxx_reg_clear(struct ar8xxx_priv *priv, int reg, u32 val) -{ - ar8xxx_rmw(priv, reg, val, 0); -} - -static inline void -split_addr(u32 regaddr, u16 *r1, u16 *r2, u16 *page) -{ - regaddr >>= 1; - *r1 = regaddr & 0x1e; - - regaddr >>= 5; - *r2 = regaddr & 0x7; - - regaddr >>= 3; - *page = regaddr & 0x1ff; -} - -static inline void -wait_for_page_switch(void) -{ - udelay(5); -} - -#endif diff --git a/target/linux/generic/files-6.12/drivers/net/phy/ar8327.c b/target/linux/generic/files-6.12/drivers/net/phy/ar8327.c deleted file mode 100644 index 33131495598084..00000000000000 --- a/target/linux/generic/files-6.12/drivers/net/phy/ar8327.c +++ /dev/null @@ -1,1550 +0,0 @@ -/* - * ar8327.c: AR8216 switch driver - * - * Copyright (C) 2009 Felix Fietkau - * Copyright (C) 2011-2012 Gabor Juhos - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "ar8216.h" -#include "ar8327.h" - -extern const struct ar8xxx_mib_desc ar8236_mibs[39]; -extern const struct switch_attr ar8xxx_sw_attr_vlan[1]; - -static u32 -ar8327_get_pad_cfg(struct ar8327_pad_cfg *cfg) -{ - u32 t; - - if (!cfg) - return 0; - - t = 0; - switch (cfg->mode) { - case AR8327_PAD_NC: - break; - - case AR8327_PAD_MAC2MAC_MII: - t = AR8327_PAD_MAC_MII_EN; - if (cfg->rxclk_sel) - t |= AR8327_PAD_MAC_MII_RXCLK_SEL; - if (cfg->txclk_sel) - t |= AR8327_PAD_MAC_MII_TXCLK_SEL; - break; - - case AR8327_PAD_MAC2MAC_GMII: - t = AR8327_PAD_MAC_GMII_EN; - if (cfg->rxclk_sel) - t |= AR8327_PAD_MAC_GMII_RXCLK_SEL; - if (cfg->txclk_sel) - t |= AR8327_PAD_MAC_GMII_TXCLK_SEL; - break; - - case AR8327_PAD_MAC_SGMII: - t = AR8327_PAD_SGMII_EN; - - /* - * WAR for the QUalcomm Atheros AP136 board. - * It seems that RGMII TX/RX delay settings needs to be - * applied for SGMII mode as well, The ethernet is not - * reliable without this. - */ - t |= cfg->txclk_delay_sel << AR8327_PAD_RGMII_TXCLK_DELAY_SEL_S; - t |= cfg->rxclk_delay_sel << AR8327_PAD_RGMII_RXCLK_DELAY_SEL_S; - if (cfg->rxclk_delay_en) - t |= AR8327_PAD_RGMII_RXCLK_DELAY_EN; - if (cfg->txclk_delay_en) - t |= AR8327_PAD_RGMII_TXCLK_DELAY_EN; - - if (cfg->sgmii_delay_en) - t |= AR8327_PAD_SGMII_DELAY_EN; - - break; - - case AR8327_PAD_MAC2PHY_MII: - t = AR8327_PAD_PHY_MII_EN; - if (cfg->rxclk_sel) - t |= AR8327_PAD_PHY_MII_RXCLK_SEL; - if (cfg->txclk_sel) - t |= AR8327_PAD_PHY_MII_TXCLK_SEL; - break; - - case AR8327_PAD_MAC2PHY_GMII: - t = AR8327_PAD_PHY_GMII_EN; - if (cfg->pipe_rxclk_sel) - t |= AR8327_PAD_PHY_GMII_PIPE_RXCLK_SEL; - if (cfg->rxclk_sel) - t |= AR8327_PAD_PHY_GMII_RXCLK_SEL; - if (cfg->txclk_sel) - t |= AR8327_PAD_PHY_GMII_TXCLK_SEL; - break; - - case AR8327_PAD_MAC_RGMII: - t = AR8327_PAD_RGMII_EN; - t |= cfg->txclk_delay_sel << AR8327_PAD_RGMII_TXCLK_DELAY_SEL_S; - t |= cfg->rxclk_delay_sel << AR8327_PAD_RGMII_RXCLK_DELAY_SEL_S; - if (cfg->rxclk_delay_en) - t |= AR8327_PAD_RGMII_RXCLK_DELAY_EN; - if (cfg->txclk_delay_en) - t |= AR8327_PAD_RGMII_TXCLK_DELAY_EN; - break; - - case AR8327_PAD_PHY_GMII: - t = AR8327_PAD_PHYX_GMII_EN; - break; - - case AR8327_PAD_PHY_RGMII: - t = AR8327_PAD_PHYX_RGMII_EN; - break; - - case AR8327_PAD_PHY_MII: - t = AR8327_PAD_PHYX_MII_EN; - break; - } - - return t; -} - -static void -ar8327_phy_rgmii_set(struct ar8xxx_priv *priv, struct phy_device *phydev) -{ - u16 phy_val = 0; - int phyaddr = phydev->mdio.addr; - struct device_node *np = phydev->mdio.dev.of_node; - - if (!np) - return; - - if (!of_property_read_bool(np, "qca,phy-rgmii-en")) { - pr_err("ar8327: qca,phy-rgmii-en is not specified\n"); - return; - } - ar8xxx_phy_dbg_read(priv, phyaddr, - AR8327_PHY_MODE_SEL, &phy_val); - phy_val |= AR8327_PHY_MODE_SEL_RGMII; - ar8xxx_phy_dbg_write(priv, phyaddr, - AR8327_PHY_MODE_SEL, phy_val); - - /* set rgmii tx clock delay if needed */ - if (!of_property_read_bool(np, "qca,txclk-delay-en")) { - pr_err("ar8327: qca,txclk-delay-en is not specified\n"); - return; - } - ar8xxx_phy_dbg_read(priv, phyaddr, - AR8327_PHY_SYS_CTRL, &phy_val); - phy_val |= AR8327_PHY_SYS_CTRL_RGMII_TX_DELAY; - ar8xxx_phy_dbg_write(priv, phyaddr, - AR8327_PHY_SYS_CTRL, phy_val); - - /* set rgmii rx clock delay if needed */ - if (!of_property_read_bool(np, "qca,rxclk-delay-en")) { - pr_err("ar8327: qca,rxclk-delay-en is not specified\n"); - return; - } - ar8xxx_phy_dbg_read(priv, phyaddr, - AR8327_PHY_TEST_CTRL, &phy_val); - phy_val |= AR8327_PHY_TEST_CTRL_RGMII_RX_DELAY; - ar8xxx_phy_dbg_write(priv, phyaddr, - AR8327_PHY_TEST_CTRL, phy_val); -} - -static void -ar8327_phy_fixup(struct ar8xxx_priv *priv, int phy) -{ - switch (priv->chip_rev) { - case 1: - /* For 100M waveform */ - ar8xxx_phy_dbg_write(priv, phy, 0, 0x02ea); - /* Turn on Gigabit clock */ - ar8xxx_phy_dbg_write(priv, phy, 0x3d, 0x68a0); - break; - - case 2: - ar8xxx_phy_mmd_write(priv, phy, 0x7, 0x3c, 0x0); - fallthrough; - case 4: - ar8xxx_phy_mmd_write(priv, phy, 0x3, 0x800d, 0x803f); - ar8xxx_phy_dbg_write(priv, phy, 0x3d, 0x6860); - ar8xxx_phy_dbg_write(priv, phy, 0x5, 0x2c46); - ar8xxx_phy_dbg_write(priv, phy, 0x3c, 0x6000); - break; - } -} - -static u32 -ar8327_get_port_init_status(struct ar8327_port_cfg *cfg) -{ - u32 t; - - if (!cfg->force_link) - return AR8216_PORT_STATUS_LINK_AUTO; - - t = AR8216_PORT_STATUS_TXMAC | AR8216_PORT_STATUS_RXMAC; - t |= cfg->duplex ? AR8216_PORT_STATUS_DUPLEX : 0; - t |= cfg->rxpause ? AR8216_PORT_STATUS_RXFLOW : 0; - t |= cfg->txpause ? AR8216_PORT_STATUS_TXFLOW : 0; - - switch (cfg->speed) { - case AR8327_PORT_SPEED_10: - t |= AR8216_PORT_SPEED_10M; - break; - case AR8327_PORT_SPEED_100: - t |= AR8216_PORT_SPEED_100M; - break; - case AR8327_PORT_SPEED_1000: - t |= AR8216_PORT_SPEED_1000M; - break; - } - - return t; -} - -#define AR8327_LED_ENTRY(_num, _reg, _shift) \ - [_num] = { .reg = (_reg), .shift = (_shift) } - -static const struct ar8327_led_entry -ar8327_led_map[AR8327_NUM_LEDS] = { - AR8327_LED_ENTRY(AR8327_LED_PHY0_0, 0, 14), - AR8327_LED_ENTRY(AR8327_LED_PHY0_1, 1, 14), - AR8327_LED_ENTRY(AR8327_LED_PHY0_2, 2, 14), - - AR8327_LED_ENTRY(AR8327_LED_PHY1_0, 3, 8), - AR8327_LED_ENTRY(AR8327_LED_PHY1_1, 3, 10), - AR8327_LED_ENTRY(AR8327_LED_PHY1_2, 3, 12), - - AR8327_LED_ENTRY(AR8327_LED_PHY2_0, 3, 14), - AR8327_LED_ENTRY(AR8327_LED_PHY2_1, 3, 16), - AR8327_LED_ENTRY(AR8327_LED_PHY2_2, 3, 18), - - AR8327_LED_ENTRY(AR8327_LED_PHY3_0, 3, 20), - AR8327_LED_ENTRY(AR8327_LED_PHY3_1, 3, 22), - AR8327_LED_ENTRY(AR8327_LED_PHY3_2, 3, 24), - - AR8327_LED_ENTRY(AR8327_LED_PHY4_0, 0, 30), - AR8327_LED_ENTRY(AR8327_LED_PHY4_1, 1, 30), - AR8327_LED_ENTRY(AR8327_LED_PHY4_2, 2, 30), -}; - -static void -ar8327_set_led_pattern(struct ar8xxx_priv *priv, unsigned int led_num, - enum ar8327_led_pattern pattern) -{ - const struct ar8327_led_entry *entry; - - entry = &ar8327_led_map[led_num]; - ar8xxx_rmw(priv, AR8327_REG_LED_CTRL(entry->reg), - (3 << entry->shift), pattern << entry->shift); -} - -static void -ar8327_led_work_func(struct work_struct *work) -{ - struct ar8327_led *aled; - u8 pattern; - - aled = container_of(work, struct ar8327_led, led_work); - - pattern = aled->pattern; - - ar8327_set_led_pattern(aled->sw_priv, aled->led_num, - pattern); -} - -static void -ar8327_led_schedule_change(struct ar8327_led *aled, u8 pattern) -{ - if (aled->pattern == pattern) - return; - - aled->pattern = pattern; - schedule_work(&aled->led_work); -} - -static inline struct ar8327_led * -led_cdev_to_ar8327_led(struct led_classdev *led_cdev) -{ - return container_of(led_cdev, struct ar8327_led, cdev); -} - -static int -ar8327_led_blink_set(struct led_classdev *led_cdev, - unsigned long *delay_on, - unsigned long *delay_off) -{ - struct ar8327_led *aled = led_cdev_to_ar8327_led(led_cdev); - - if (*delay_on == 0 && *delay_off == 0) { - *delay_on = 125; - *delay_off = 125; - } - - if (*delay_on != 125 || *delay_off != 125) { - /* - * The hardware only supports blinking at 4Hz. Fall back - * to software implementation in other cases. - */ - return -EINVAL; - } - - spin_lock(&aled->lock); - - aled->enable_hw_mode = false; - ar8327_led_schedule_change(aled, AR8327_LED_PATTERN_BLINK); - - spin_unlock(&aled->lock); - - return 0; -} - -static void -ar8327_led_set_brightness(struct led_classdev *led_cdev, - enum led_brightness brightness) -{ - struct ar8327_led *aled = led_cdev_to_ar8327_led(led_cdev); - u8 pattern; - bool active; - - active = (brightness != LED_OFF); - active ^= aled->active_low; - - pattern = (active) ? AR8327_LED_PATTERN_ON : - AR8327_LED_PATTERN_OFF; - - spin_lock(&aled->lock); - - aled->enable_hw_mode = false; - ar8327_led_schedule_change(aled, pattern); - - spin_unlock(&aled->lock); -} - -static ssize_t -ar8327_led_enable_hw_mode_show(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct led_classdev *led_cdev = dev_get_drvdata(dev); - struct ar8327_led *aled = led_cdev_to_ar8327_led(led_cdev); - ssize_t ret = 0; - - ret += scnprintf(buf, PAGE_SIZE, "%d\n", aled->enable_hw_mode); - - return ret; -} - -static ssize_t -ar8327_led_enable_hw_mode_store(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t size) -{ - struct led_classdev *led_cdev = dev_get_drvdata(dev); - struct ar8327_led *aled = led_cdev_to_ar8327_led(led_cdev); - u8 pattern; - u8 value; - int ret; - - ret = kstrtou8(buf, 10, &value); - if (ret < 0) - return -EINVAL; - - spin_lock(&aled->lock); - - aled->enable_hw_mode = !!value; - if (aled->enable_hw_mode) - pattern = AR8327_LED_PATTERN_RULE; - else - pattern = AR8327_LED_PATTERN_OFF; - - ar8327_led_schedule_change(aled, pattern); - - spin_unlock(&aled->lock); - - return size; -} - -static DEVICE_ATTR(enable_hw_mode, S_IRUGO | S_IWUSR, - ar8327_led_enable_hw_mode_show, - ar8327_led_enable_hw_mode_store); - -static int -ar8327_led_register(struct ar8327_led *aled) -{ - int ret; - - ret = led_classdev_register(NULL, &aled->cdev); - if (ret < 0) - return ret; - - if (aled->mode == AR8327_LED_MODE_HW) { - ret = device_create_file(aled->cdev.dev, - &dev_attr_enable_hw_mode); - if (ret) - goto err_unregister; - } - - return 0; - -err_unregister: - led_classdev_unregister(&aled->cdev); - return ret; -} - -static void -ar8327_led_unregister(struct ar8327_led *aled) -{ - if (aled->mode == AR8327_LED_MODE_HW) - device_remove_file(aled->cdev.dev, &dev_attr_enable_hw_mode); - - led_classdev_unregister(&aled->cdev); - cancel_work_sync(&aled->led_work); -} - -static int -ar8327_led_create(struct ar8xxx_priv *priv, - const struct ar8327_led_info *led_info) -{ - struct ar8327_data *data = priv->chip_data; - struct ar8327_led *aled; - int ret; - - if (!IS_ENABLED(CONFIG_AR8216_PHY_LEDS)) - return 0; - - if (!led_info->name) - return -EINVAL; - - if (led_info->led_num >= AR8327_NUM_LEDS) - return -EINVAL; - - aled = kzalloc(sizeof(*aled) + strlen(led_info->name) + 1, - GFP_KERNEL); - if (!aled) - return -ENOMEM; - - aled->sw_priv = priv; - aled->led_num = led_info->led_num; - aled->active_low = led_info->active_low; - aled->mode = led_info->mode; - - if (aled->mode == AR8327_LED_MODE_HW) - aled->enable_hw_mode = true; - - aled->name = (char *)(aled + 1); - strcpy(aled->name, led_info->name); - - aled->cdev.name = aled->name; - aled->cdev.brightness_set = ar8327_led_set_brightness; - aled->cdev.blink_set = ar8327_led_blink_set; - aled->cdev.default_trigger = led_info->default_trigger; - - spin_lock_init(&aled->lock); - mutex_init(&aled->mutex); - INIT_WORK(&aled->led_work, ar8327_led_work_func); - - ret = ar8327_led_register(aled); - if (ret) - goto err_free; - - data->leds[data->num_leds++] = aled; - - return 0; - -err_free: - kfree(aled); - return ret; -} - -static void -ar8327_led_destroy(struct ar8327_led *aled) -{ - ar8327_led_unregister(aled); - kfree(aled); -} - -static void -ar8327_leds_init(struct ar8xxx_priv *priv) -{ - struct ar8327_data *data = priv->chip_data; - unsigned i; - - if (!IS_ENABLED(CONFIG_AR8216_PHY_LEDS)) - return; - - for (i = 0; i < data->num_leds; i++) { - struct ar8327_led *aled; - - aled = data->leds[i]; - - if (aled->enable_hw_mode) - aled->pattern = AR8327_LED_PATTERN_RULE; - else - aled->pattern = AR8327_LED_PATTERN_OFF; - - ar8327_set_led_pattern(priv, aled->led_num, aled->pattern); - } -} - -static void -ar8327_leds_cleanup(struct ar8xxx_priv *priv) -{ - struct ar8327_data *data = priv->chip_data; - unsigned i; - - if (!IS_ENABLED(CONFIG_AR8216_PHY_LEDS)) - return; - - for (i = 0; i < data->num_leds; i++) { - struct ar8327_led *aled; - - aled = data->leds[i]; - ar8327_led_destroy(aled); - } - - kfree(data->leds); -} - -static int -ar8327_hw_config_pdata(struct ar8xxx_priv *priv, - struct ar8327_platform_data *pdata) -{ - struct ar8327_led_cfg *led_cfg; - struct ar8327_data *data = priv->chip_data; - u32 pos, new_pos; - u32 t; - - if (!pdata) - return -EINVAL; - - priv->get_port_link = pdata->get_port_link; - - data->port0_status = ar8327_get_port_init_status(&pdata->port0_cfg); - data->port6_status = ar8327_get_port_init_status(&pdata->port6_cfg); - - t = ar8327_get_pad_cfg(pdata->pad0_cfg); - if (chip_is_ar8337(priv) && !pdata->pad0_cfg->mac06_exchange_dis) - t |= AR8337_PAD_MAC06_EXCHANGE_EN; - ar8xxx_write(priv, AR8327_REG_PAD0_MODE, t); - - t = ar8327_get_pad_cfg(pdata->pad5_cfg); - ar8xxx_write(priv, AR8327_REG_PAD5_MODE, t); - t = ar8327_get_pad_cfg(pdata->pad6_cfg); - ar8xxx_write(priv, AR8327_REG_PAD6_MODE, t); - - pos = ar8xxx_read(priv, AR8327_REG_POWER_ON_STRAP); - new_pos = pos; - - led_cfg = pdata->led_cfg; - if (led_cfg) { - if (led_cfg->open_drain) - new_pos |= AR8327_POWER_ON_STRAP_LED_OPEN_EN; - else - new_pos &= ~AR8327_POWER_ON_STRAP_LED_OPEN_EN; - - ar8xxx_write(priv, AR8327_REG_LED_CTRL0, led_cfg->led_ctrl0); - ar8xxx_write(priv, AR8327_REG_LED_CTRL1, led_cfg->led_ctrl1); - ar8xxx_write(priv, AR8327_REG_LED_CTRL2, led_cfg->led_ctrl2); - ar8xxx_write(priv, AR8327_REG_LED_CTRL3, led_cfg->led_ctrl3); - - if (new_pos != pos) - new_pos |= AR8327_POWER_ON_STRAP_POWER_ON_SEL; - } - - if (pdata->sgmii_cfg) { - t = pdata->sgmii_cfg->sgmii_ctrl; - if (priv->chip_rev == 1) - t |= AR8327_SGMII_CTRL_EN_PLL | - AR8327_SGMII_CTRL_EN_RX | - AR8327_SGMII_CTRL_EN_TX; - else - t &= ~(AR8327_SGMII_CTRL_EN_PLL | - AR8327_SGMII_CTRL_EN_RX | - AR8327_SGMII_CTRL_EN_TX); - - ar8xxx_write(priv, AR8327_REG_SGMII_CTRL, t); - - if (pdata->sgmii_cfg->serdes_aen) - new_pos &= ~AR8327_POWER_ON_STRAP_SERDES_AEN; - else - new_pos |= AR8327_POWER_ON_STRAP_SERDES_AEN; - } - - ar8xxx_write(priv, AR8327_REG_POWER_ON_STRAP, new_pos); - - if (pdata->leds && pdata->num_leds) { - int i; - - data->leds = kzalloc(pdata->num_leds * sizeof(void *), - GFP_KERNEL); - if (!data->leds) - return -ENOMEM; - - for (i = 0; i < pdata->num_leds; i++) - ar8327_led_create(priv, &pdata->leds[i]); - } - - return 0; -} - -#ifdef CONFIG_OF -static int -ar8327_hw_config_of(struct ar8xxx_priv *priv, struct device_node *np) -{ - struct ar8327_data *data = priv->chip_data; - const __be32 *paddr; - int len; - int i; - - paddr = of_get_property(np, "qca,ar8327-initvals", &len); - if (!paddr || len < (2 * sizeof(*paddr))) - return -EINVAL; - - len /= sizeof(*paddr); - - for (i = 0; i < len - 1; i += 2) { - u32 reg; - u32 val; - - reg = be32_to_cpup(paddr + i); - val = be32_to_cpup(paddr + i + 1); - - switch (reg) { - case AR8327_REG_PORT_STATUS(0): - data->port0_status = val; - break; - case AR8327_REG_PORT_STATUS(6): - data->port6_status = val; - break; - default: - ar8xxx_write(priv, reg, val); - break; - } - } - - return 0; -} -#else -static inline int -ar8327_hw_config_of(struct ar8xxx_priv *priv, struct device_node *np) -{ - return -EINVAL; -} -#endif - -static int -ar8327_hw_init(struct ar8xxx_priv *priv) -{ - int ret; - - priv->chip_data = kzalloc(sizeof(struct ar8327_data), GFP_KERNEL); - if (!priv->chip_data) - return -ENOMEM; - - if (priv->pdev->of_node) - ret = ar8327_hw_config_of(priv, priv->pdev->of_node); - else - ret = ar8327_hw_config_pdata(priv, - priv->phy->mdio.dev.platform_data); - - if (ret) - return ret; - - ar8327_leds_init(priv); - - ar8xxx_phy_init(priv); - - return 0; -} - -static void -ar8327_cleanup(struct ar8xxx_priv *priv) -{ - ar8327_leds_cleanup(priv); -} - -static void -ar8327_init_globals(struct ar8xxx_priv *priv) -{ - struct ar8327_data *data = priv->chip_data; - u32 t; - int i; - - /* enable CPU port and disable mirror port */ - t = AR8327_FWD_CTRL0_CPU_PORT_EN | - AR8327_FWD_CTRL0_MIRROR_PORT; - ar8xxx_write(priv, AR8327_REG_FWD_CTRL0, t); - - /* forward multicast and broadcast frames to CPU */ - t = (AR8327_PORTS_ALL << AR8327_FWD_CTRL1_UC_FLOOD_S) | - (AR8327_PORTS_ALL << AR8327_FWD_CTRL1_MC_FLOOD_S) | - (AR8327_PORTS_ALL << AR8327_FWD_CTRL1_BC_FLOOD_S); - ar8xxx_write(priv, AR8327_REG_FWD_CTRL1, t); - - /* enable jumbo frames */ - ar8xxx_rmw(priv, AR8327_REG_MAX_FRAME_SIZE, - AR8327_MAX_FRAME_SIZE_MTU, 9018 + 8 + 2); - - /* Enable MIB counters */ - ar8xxx_reg_set(priv, AR8327_REG_MODULE_EN, - AR8327_MODULE_EN_MIB); - - /* Disable EEE on all phy's due to stability issues */ - for (i = 0; i < AR8XXX_NUM_PHYS; i++) - data->eee[i] = false; -} - -static void -ar8327_init_port(struct ar8xxx_priv *priv, int port) -{ - struct ar8327_data *data = priv->chip_data; - u32 t; - - if (port == AR8216_PORT_CPU) - t = data->port0_status; - else if (port == 6) - t = data->port6_status; - else - t = AR8216_PORT_STATUS_LINK_AUTO; - - if (port != AR8216_PORT_CPU && port != 6) { - /*hw limitation:if configure mac when there is traffic, - port MAC may work abnormal. Need disable lan&wan mac at fisrt*/ - ar8xxx_write(priv, AR8327_REG_PORT_STATUS(port), 0); - msleep(100); - t |= AR8216_PORT_STATUS_FLOW_CONTROL; - ar8xxx_write(priv, AR8327_REG_PORT_STATUS(port), t); - } else { - ar8xxx_write(priv, AR8327_REG_PORT_STATUS(port), t); - } - - ar8xxx_write(priv, AR8327_REG_PORT_HEADER(port), 0); - - ar8xxx_write(priv, AR8327_REG_PORT_VLAN0(port), 0); - - t = AR8327_PORT_VLAN1_OUT_MODE_UNTOUCH << AR8327_PORT_VLAN1_OUT_MODE_S; - ar8xxx_write(priv, AR8327_REG_PORT_VLAN1(port), t); - - t = AR8327_PORT_LOOKUP_LEARN; - t |= AR8216_PORT_STATE_FORWARD << AR8327_PORT_LOOKUP_STATE_S; - ar8xxx_write(priv, AR8327_REG_PORT_LOOKUP(port), t); -} - -static u32 -ar8327_read_port_status(struct ar8xxx_priv *priv, int port) -{ - u32 t; - - t = ar8xxx_read(priv, AR8327_REG_PORT_STATUS(port)); - /* map the flow control autoneg result bits to the flow control bits - * used in forced mode to allow ar8216_read_port_link detect - * flow control properly if autoneg is used - */ - if (t & AR8216_PORT_STATUS_LINK_UP && - t & AR8216_PORT_STATUS_LINK_AUTO) { - t &= ~(AR8216_PORT_STATUS_TXFLOW | AR8216_PORT_STATUS_RXFLOW); - if (t & AR8327_PORT_STATUS_TXFLOW_AUTO) - t |= AR8216_PORT_STATUS_TXFLOW; - if (t & AR8327_PORT_STATUS_RXFLOW_AUTO) - t |= AR8216_PORT_STATUS_RXFLOW; - } - - return t; -} - -static u32 -ar8327_read_port_eee_status(struct ar8xxx_priv *priv, int port) -{ - int phy; - u16 t; - - if (port >= priv->dev.ports) - return 0; - - if (port == 0 || port == 6) - return 0; - - phy = port - 1; - - /* EEE Ability Auto-negotiation Result */ - t = ar8xxx_phy_mmd_read(priv, phy, 0x7, 0x8000); - - return mmd_eee_adv_to_ethtool_adv_t(t); -} - -static int -ar8327_atu_flush(struct ar8xxx_priv *priv) -{ - int ret; - - ret = ar8216_wait_bit(priv, AR8327_REG_ATU_FUNC, - AR8327_ATU_FUNC_BUSY, 0); - if (!ret) - ar8xxx_write(priv, AR8327_REG_ATU_FUNC, - AR8327_ATU_FUNC_OP_FLUSH | - AR8327_ATU_FUNC_BUSY); - - return ret; -} - -static int -ar8327_atu_flush_port(struct ar8xxx_priv *priv, int port) -{ - u32 t; - int ret; - - ret = ar8216_wait_bit(priv, AR8327_REG_ATU_FUNC, - AR8327_ATU_FUNC_BUSY, 0); - if (!ret) { - t = (port << AR8327_ATU_PORT_NUM_S); - t |= AR8327_ATU_FUNC_OP_FLUSH_PORT; - t |= AR8327_ATU_FUNC_BUSY; - ar8xxx_write(priv, AR8327_REG_ATU_FUNC, t); - } - - return ret; -} - -static int -ar8327_get_port_igmp(struct ar8xxx_priv *priv, int port) -{ - u32 fwd_ctrl, frame_ack; - - fwd_ctrl = (BIT(port) << AR8327_FWD_CTRL1_IGMP_S); - frame_ack = ((AR8327_FRAME_ACK_CTRL_IGMP_MLD | - AR8327_FRAME_ACK_CTRL_IGMP_JOIN | - AR8327_FRAME_ACK_CTRL_IGMP_LEAVE) << - AR8327_FRAME_ACK_CTRL_S(port)); - - return (ar8xxx_read(priv, AR8327_REG_FWD_CTRL1) & - fwd_ctrl) == fwd_ctrl && - (ar8xxx_read(priv, AR8327_REG_FRAME_ACK_CTRL(port)) & - frame_ack) == frame_ack; -} - -static void -ar8327_set_port_igmp(struct ar8xxx_priv *priv, int port, int enable) -{ - int reg_frame_ack = AR8327_REG_FRAME_ACK_CTRL(port); - u32 val_frame_ack = (AR8327_FRAME_ACK_CTRL_IGMP_MLD | - AR8327_FRAME_ACK_CTRL_IGMP_JOIN | - AR8327_FRAME_ACK_CTRL_IGMP_LEAVE) << - AR8327_FRAME_ACK_CTRL_S(port); - - if (enable) { - ar8xxx_rmw(priv, AR8327_REG_FWD_CTRL1, - BIT(port) << AR8327_FWD_CTRL1_MC_FLOOD_S, - BIT(port) << AR8327_FWD_CTRL1_IGMP_S); - ar8xxx_reg_set(priv, reg_frame_ack, val_frame_ack); - } else { - ar8xxx_rmw(priv, AR8327_REG_FWD_CTRL1, - BIT(port) << AR8327_FWD_CTRL1_IGMP_S, - BIT(port) << AR8327_FWD_CTRL1_MC_FLOOD_S); - ar8xxx_reg_clear(priv, reg_frame_ack, val_frame_ack); - } -} - -static void -ar8327_vtu_op(struct ar8xxx_priv *priv, u32 op, u32 val) -{ - if (ar8216_wait_bit(priv, AR8327_REG_VTU_FUNC1, - AR8327_VTU_FUNC1_BUSY, 0)) - return; - - if ((op & AR8327_VTU_FUNC1_OP) == AR8327_VTU_FUNC1_OP_LOAD) - ar8xxx_write(priv, AR8327_REG_VTU_FUNC0, val); - - op |= AR8327_VTU_FUNC1_BUSY; - ar8xxx_write(priv, AR8327_REG_VTU_FUNC1, op); -} - -static void -ar8327_vtu_flush(struct ar8xxx_priv *priv) -{ - ar8327_vtu_op(priv, AR8327_VTU_FUNC1_OP_FLUSH, 0); -} - -static void -ar8327_vtu_load_vlan(struct ar8xxx_priv *priv, u32 vid, u32 port_mask) -{ - u32 op; - u32 val; - int i; - - op = AR8327_VTU_FUNC1_OP_LOAD | (vid << AR8327_VTU_FUNC1_VID_S); - val = AR8327_VTU_FUNC0_VALID | AR8327_VTU_FUNC0_IVL; - for (i = 0; i < AR8327_NUM_PORTS; i++) { - u32 mode; - - if ((port_mask & BIT(i)) == 0) - mode = AR8327_VTU_FUNC0_EG_MODE_NOT; - else if (priv->vlan == 0) - mode = AR8327_VTU_FUNC0_EG_MODE_KEEP; - else if ((priv->vlan_tagged & BIT(i)) || (priv->vlan_id[priv->pvid[i]] != vid)) - mode = AR8327_VTU_FUNC0_EG_MODE_TAG; - else - mode = AR8327_VTU_FUNC0_EG_MODE_UNTAG; - - val |= mode << AR8327_VTU_FUNC0_EG_MODE_S(i); - } - ar8327_vtu_op(priv, op, val); -} - -static void -ar8327_setup_port(struct ar8xxx_priv *priv, int port, u32 members) -{ - u32 t; - u32 egress, ingress; - u32 pvid = priv->vlan_id[priv->pvid[port]]; - - if (priv->vlan) { - egress = AR8327_PORT_VLAN1_OUT_MODE_UNMOD; - ingress = AR8216_IN_SECURE; - } else { - egress = AR8327_PORT_VLAN1_OUT_MODE_UNTOUCH; - ingress = AR8216_IN_PORT_ONLY; - } - - t = pvid << AR8327_PORT_VLAN0_DEF_SVID_S; - t |= pvid << AR8327_PORT_VLAN0_DEF_CVID_S; - if (priv->vlan && priv->port_vlan_prio[port]) { - u32 prio = priv->port_vlan_prio[port]; - - t |= prio << AR8327_PORT_VLAN0_DEF_SPRI_S; - t |= prio << AR8327_PORT_VLAN0_DEF_CPRI_S; - } - ar8xxx_write(priv, AR8327_REG_PORT_VLAN0(port), t); - - t = AR8327_PORT_VLAN1_PORT_VLAN_PROP; - t |= egress << AR8327_PORT_VLAN1_OUT_MODE_S; - if (priv->vlan && priv->port_vlan_prio[port]) - t |= AR8327_PORT_VLAN1_VLAN_PRI_PROP; - - ar8xxx_write(priv, AR8327_REG_PORT_VLAN1(port), t); - - t = members; - t |= AR8327_PORT_LOOKUP_LEARN; - t |= ingress << AR8327_PORT_LOOKUP_IN_MODE_S; - t |= AR8216_PORT_STATE_FORWARD << AR8327_PORT_LOOKUP_STATE_S; - ar8xxx_write(priv, AR8327_REG_PORT_LOOKUP(port), t); -} - -static int -ar8327_sw_get_ports(struct switch_dev *dev, struct switch_val *val) -{ - struct ar8xxx_priv *priv = swdev_to_ar8xxx(dev); - u8 ports = priv->vlan_table[val->port_vlan]; - int i; - - val->len = 0; - for (i = 0; i < dev->ports; i++) { - struct switch_port *p; - - if (!(ports & (1 << i))) - continue; - - p = &val->value.ports[val->len++]; - p->id = i; - if ((priv->vlan_tagged & (1 << i)) || (priv->pvid[i] != val->port_vlan)) - p->flags = (1 << SWITCH_PORT_FLAG_TAGGED); - else - p->flags = 0; - } - return 0; -} - -static int -ar8327_sw_set_ports(struct switch_dev *dev, struct switch_val *val) -{ - struct ar8xxx_priv *priv = swdev_to_ar8xxx(dev); - u8 *vt = &priv->vlan_table[val->port_vlan]; - int i; - - *vt = 0; - for (i = 0; i < val->len; i++) { - struct switch_port *p = &val->value.ports[i]; - - if (p->flags & (1 << SWITCH_PORT_FLAG_TAGGED)) { - if (val->port_vlan == priv->pvid[p->id]) { - priv->vlan_tagged |= (1 << p->id); - } - } else { - priv->vlan_tagged &= ~(1 << p->id); - priv->pvid[p->id] = val->port_vlan; - } - - *vt |= 1 << p->id; - } - return 0; -} - -static void -ar8327_set_mirror_regs(struct ar8xxx_priv *priv) -{ - int port; - - /* reset all mirror registers */ - ar8xxx_rmw(priv, AR8327_REG_FWD_CTRL0, - AR8327_FWD_CTRL0_MIRROR_PORT, - (0xF << AR8327_FWD_CTRL0_MIRROR_PORT_S)); - for (port = 0; port < AR8327_NUM_PORTS; port++) { - ar8xxx_reg_clear(priv, AR8327_REG_PORT_LOOKUP(port), - AR8327_PORT_LOOKUP_ING_MIRROR_EN); - - ar8xxx_reg_clear(priv, AR8327_REG_PORT_HOL_CTRL1(port), - AR8327_PORT_HOL_CTRL1_EG_MIRROR_EN); - } - - /* now enable mirroring if necessary */ - if (priv->source_port >= AR8327_NUM_PORTS || - priv->monitor_port >= AR8327_NUM_PORTS || - priv->source_port == priv->monitor_port) { - return; - } - - ar8xxx_rmw(priv, AR8327_REG_FWD_CTRL0, - AR8327_FWD_CTRL0_MIRROR_PORT, - (priv->monitor_port << AR8327_FWD_CTRL0_MIRROR_PORT_S)); - - if (priv->mirror_rx) - ar8xxx_reg_set(priv, AR8327_REG_PORT_LOOKUP(priv->source_port), - AR8327_PORT_LOOKUP_ING_MIRROR_EN); - - if (priv->mirror_tx) - ar8xxx_reg_set(priv, AR8327_REG_PORT_HOL_CTRL1(priv->source_port), - AR8327_PORT_HOL_CTRL1_EG_MIRROR_EN); -} - -static int -ar8327_sw_set_eee(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val) -{ - struct ar8xxx_priv *priv = swdev_to_ar8xxx(dev); - struct ar8327_data *data = priv->chip_data; - int port = val->port_vlan; - int phy; - - if (port >= dev->ports) - return -EINVAL; - if (port == 0 || port == 6) - return -EOPNOTSUPP; - - phy = port - 1; - - data->eee[phy] = !!(val->value.i); - - return 0; -} - -static int -ar8327_sw_get_eee(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val) -{ - struct ar8xxx_priv *priv = swdev_to_ar8xxx(dev); - const struct ar8327_data *data = priv->chip_data; - int port = val->port_vlan; - int phy; - - if (port >= dev->ports) - return -EINVAL; - if (port == 0 || port == 6) - return -EOPNOTSUPP; - - phy = port - 1; - - val->value.i = data->eee[phy]; - - return 0; -} - -static void -ar8327_wait_atu_ready(struct ar8xxx_priv *priv, u16 r2, u16 r1) -{ - int timeout = 20; - - while (ar8xxx_mii_read32(priv, r2, r1) & AR8327_ATU_FUNC_BUSY && --timeout) { - udelay(10); - cond_resched(); - } - - if (!timeout) - pr_err("ar8327: timeout waiting for atu to become ready\n"); -} - -static void ar8327_get_arl_entry(struct ar8xxx_priv *priv, - struct arl_entry *a, u32 *status, enum arl_op op) -{ - struct mii_bus *bus = priv->mii_bus; - u16 r2, page; - u16 r1_data0, r1_data1, r1_data2, r1_func; - u32 val0, val1, val2; - - split_addr(AR8327_REG_ATU_DATA0, &r1_data0, &r2, &page); - r2 |= 0x10; - - r1_data1 = (AR8327_REG_ATU_DATA1 >> 1) & 0x1e; - r1_data2 = (AR8327_REG_ATU_DATA2 >> 1) & 0x1e; - r1_func = (AR8327_REG_ATU_FUNC >> 1) & 0x1e; - - switch (op) { - case AR8XXX_ARL_INITIALIZE: - /* all ATU registers are on the same page - * therefore set page only once - */ - bus->write(bus, 0x18, 0, page); - wait_for_page_switch(); - - ar8327_wait_atu_ready(priv, r2, r1_func); - - ar8xxx_mii_write32(priv, r2, r1_data0, 0); - ar8xxx_mii_write32(priv, r2, r1_data1, 0); - ar8xxx_mii_write32(priv, r2, r1_data2, 0); - break; - case AR8XXX_ARL_GET_NEXT: - ar8xxx_mii_write32(priv, r2, r1_func, - AR8327_ATU_FUNC_OP_GET_NEXT | - AR8327_ATU_FUNC_BUSY); - ar8327_wait_atu_ready(priv, r2, r1_func); - - val0 = ar8xxx_mii_read32(priv, r2, r1_data0); - val1 = ar8xxx_mii_read32(priv, r2, r1_data1); - val2 = ar8xxx_mii_read32(priv, r2, r1_data2); - - *status = val2 & AR8327_ATU_STATUS; - if (!*status) - break; - - a->portmap = (val1 & AR8327_ATU_PORTS) >> AR8327_ATU_PORTS_S; - a->mac[0] = (val0 & AR8327_ATU_ADDR0) >> AR8327_ATU_ADDR0_S; - a->mac[1] = (val0 & AR8327_ATU_ADDR1) >> AR8327_ATU_ADDR1_S; - a->mac[2] = (val0 & AR8327_ATU_ADDR2) >> AR8327_ATU_ADDR2_S; - a->mac[3] = (val0 & AR8327_ATU_ADDR3) >> AR8327_ATU_ADDR3_S; - a->mac[4] = (val1 & AR8327_ATU_ADDR4) >> AR8327_ATU_ADDR4_S; - a->mac[5] = (val1 & AR8327_ATU_ADDR5) >> AR8327_ATU_ADDR5_S; - break; - } -} - -static int -ar8327_sw_hw_apply(struct switch_dev *dev) -{ - struct ar8xxx_priv *priv = swdev_to_ar8xxx(dev); - const struct ar8327_data *data = priv->chip_data; - int ret, i; - - ret = ar8xxx_sw_hw_apply(dev); - if (ret) - return ret; - - for (i=0; i < AR8XXX_NUM_PHYS; i++) { - if (data->eee[i]) - ar8xxx_reg_clear(priv, AR8327_REG_EEE_CTRL, - AR8327_EEE_CTRL_DISABLE_PHY(i)); - else - ar8xxx_reg_set(priv, AR8327_REG_EEE_CTRL, - AR8327_EEE_CTRL_DISABLE_PHY(i)); - } - - return 0; -} - -int -ar8327_sw_get_port_igmp_snooping(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val) -{ - struct ar8xxx_priv *priv = swdev_to_ar8xxx(dev); - int port = val->port_vlan; - - if (port >= dev->ports) - return -EINVAL; - - mutex_lock(&priv->reg_mutex); - val->value.i = ar8327_get_port_igmp(priv, port); - mutex_unlock(&priv->reg_mutex); - - return 0; -} - -int -ar8327_sw_set_port_igmp_snooping(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val) -{ - struct ar8xxx_priv *priv = swdev_to_ar8xxx(dev); - int port = val->port_vlan; - - if (port >= dev->ports) - return -EINVAL; - - mutex_lock(&priv->reg_mutex); - ar8327_set_port_igmp(priv, port, val->value.i); - mutex_unlock(&priv->reg_mutex); - - return 0; -} - -int -ar8327_sw_get_igmp_snooping(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val) -{ - int port; - - for (port = 0; port < dev->ports; port++) { - val->port_vlan = port; - if (ar8327_sw_get_port_igmp_snooping(dev, attr, val) || - !val->value.i) - break; - } - - return 0; -} - -int -ar8327_sw_set_igmp_snooping(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val) -{ - int port; - - for (port = 0; port < dev->ports; port++) { - val->port_vlan = port; - if (ar8327_sw_set_port_igmp_snooping(dev, attr, val)) - break; - } - - return 0; -} - -int -ar8327_sw_get_igmp_v3(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val) -{ - struct ar8xxx_priv *priv = swdev_to_ar8xxx(dev); - u32 val_reg; - - mutex_lock(&priv->reg_mutex); - val_reg = ar8xxx_read(priv, AR8327_REG_FRAME_ACK_CTRL1); - val->value.i = ((val_reg & AR8327_FRAME_ACK_CTRL_IGMP_V3_EN) != 0); - mutex_unlock(&priv->reg_mutex); - - return 0; -} - -int -ar8327_sw_set_igmp_v3(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val) -{ - struct ar8xxx_priv *priv = swdev_to_ar8xxx(dev); - - mutex_lock(&priv->reg_mutex); - if (val->value.i) - ar8xxx_reg_set(priv, AR8327_REG_FRAME_ACK_CTRL1, - AR8327_FRAME_ACK_CTRL_IGMP_V3_EN); - else - ar8xxx_reg_clear(priv, AR8327_REG_FRAME_ACK_CTRL1, - AR8327_FRAME_ACK_CTRL_IGMP_V3_EN); - mutex_unlock(&priv->reg_mutex); - - return 0; -} - -static int -ar8327_sw_set_port_vlan_prio(struct switch_dev *dev, const struct switch_attr *attr, - struct switch_val *val) -{ - struct ar8xxx_priv *priv = swdev_to_ar8xxx(dev); - int port = val->port_vlan; - - if (port >= dev->ports) - return -EINVAL; - if (port == 0 || port == 6) - return -EOPNOTSUPP; - if (val->value.i < 0 || val->value.i > 7) - return -EINVAL; - - priv->port_vlan_prio[port] = val->value.i; - - return 0; -} - -static int -ar8327_sw_get_port_vlan_prio(struct switch_dev *dev, const struct switch_attr *attr, - struct switch_val *val) -{ - struct ar8xxx_priv *priv = swdev_to_ar8xxx(dev); - int port = val->port_vlan; - - val->value.i = priv->port_vlan_prio[port]; - - return 0; -} - -static const struct switch_attr ar8327_sw_attr_globals[] = { - { - .type = SWITCH_TYPE_INT, - .name = "enable_vlan", - .description = "Enable VLAN mode", - .set = ar8xxx_sw_set_vlan, - .get = ar8xxx_sw_get_vlan, - .max = 1 - }, - { - .type = SWITCH_TYPE_NOVAL, - .name = "reset_mibs", - .description = "Reset all MIB counters", - .set = ar8xxx_sw_set_reset_mibs, - }, - { - .type = SWITCH_TYPE_INT, - .name = "ar8xxx_mib_poll_interval", - .description = "MIB polling interval in msecs (0 to disable)", - .set = ar8xxx_sw_set_mib_poll_interval, - .get = ar8xxx_sw_get_mib_poll_interval - }, - { - .type = SWITCH_TYPE_INT, - .name = "ar8xxx_mib_type", - .description = "MIB type (0=basic 1=extended)", - .set = ar8xxx_sw_set_mib_type, - .get = ar8xxx_sw_get_mib_type - }, - { - .type = SWITCH_TYPE_INT, - .name = "enable_mirror_rx", - .description = "Enable mirroring of RX packets", - .set = ar8xxx_sw_set_mirror_rx_enable, - .get = ar8xxx_sw_get_mirror_rx_enable, - .max = 1 - }, - { - .type = SWITCH_TYPE_INT, - .name = "enable_mirror_tx", - .description = "Enable mirroring of TX packets", - .set = ar8xxx_sw_set_mirror_tx_enable, - .get = ar8xxx_sw_get_mirror_tx_enable, - .max = 1 - }, - { - .type = SWITCH_TYPE_INT, - .name = "mirror_monitor_port", - .description = "Mirror monitor port", - .set = ar8xxx_sw_set_mirror_monitor_port, - .get = ar8xxx_sw_get_mirror_monitor_port, - .max = AR8327_NUM_PORTS - 1 - }, - { - .type = SWITCH_TYPE_INT, - .name = "mirror_source_port", - .description = "Mirror source port", - .set = ar8xxx_sw_set_mirror_source_port, - .get = ar8xxx_sw_get_mirror_source_port, - .max = AR8327_NUM_PORTS - 1 - }, - { - .type = SWITCH_TYPE_INT, - .name = "arl_age_time", - .description = "ARL age time (secs)", - .set = ar8xxx_sw_set_arl_age_time, - .get = ar8xxx_sw_get_arl_age_time, - }, - { - .type = SWITCH_TYPE_STRING, - .name = "arl_table", - .description = "Get ARL table", - .set = NULL, - .get = ar8xxx_sw_get_arl_table, - }, - { - .type = SWITCH_TYPE_NOVAL, - .name = "flush_arl_table", - .description = "Flush ARL table", - .set = ar8xxx_sw_set_flush_arl_table, - }, - { - .type = SWITCH_TYPE_INT, - .name = "igmp_snooping", - .description = "Enable IGMP Snooping", - .set = ar8327_sw_set_igmp_snooping, - .get = ar8327_sw_get_igmp_snooping, - .max = 1 - }, - { - .type = SWITCH_TYPE_INT, - .name = "igmp_v3", - .description = "Enable IGMPv3 support", - .set = ar8327_sw_set_igmp_v3, - .get = ar8327_sw_get_igmp_v3, - .max = 1 - }, -}; - -static const struct switch_attr ar8327_sw_attr_port[] = { - { - .type = SWITCH_TYPE_NOVAL, - .name = "reset_mib", - .description = "Reset single port MIB counters", - .set = ar8xxx_sw_set_port_reset_mib, - }, - { - .type = SWITCH_TYPE_STRING, - .name = "mib", - .description = "Get port's MIB counters", - .set = NULL, - .get = ar8xxx_sw_get_port_mib, - }, - { - .type = SWITCH_TYPE_INT, - .name = "enable_eee", - .description = "Enable EEE PHY sleep mode", - .set = ar8327_sw_set_eee, - .get = ar8327_sw_get_eee, - .max = 1, - }, - { - .type = SWITCH_TYPE_NOVAL, - .name = "flush_arl_table", - .description = "Flush port's ARL table entries", - .set = ar8xxx_sw_set_flush_port_arl_table, - }, - { - .type = SWITCH_TYPE_INT, - .name = "igmp_snooping", - .description = "Enable port's IGMP Snooping", - .set = ar8327_sw_set_port_igmp_snooping, - .get = ar8327_sw_get_port_igmp_snooping, - .max = 1 - }, - { - .type = SWITCH_TYPE_INT, - .name = "vlan_prio", - .description = "Port VLAN default priority (VLAN PCP) (0-7)", - .set = ar8327_sw_set_port_vlan_prio, - .get = ar8327_sw_get_port_vlan_prio, - .max = 7, - }, -}; - -static const struct switch_dev_ops ar8327_sw_ops = { - .attr_global = { - .attr = ar8327_sw_attr_globals, - .n_attr = ARRAY_SIZE(ar8327_sw_attr_globals), - }, - .attr_port = { - .attr = ar8327_sw_attr_port, - .n_attr = ARRAY_SIZE(ar8327_sw_attr_port), - }, - .attr_vlan = { - .attr = ar8xxx_sw_attr_vlan, - .n_attr = ARRAY_SIZE(ar8xxx_sw_attr_vlan), - }, - .get_port_pvid = ar8xxx_sw_get_pvid, - .set_port_pvid = ar8xxx_sw_set_pvid, - .get_vlan_ports = ar8327_sw_get_ports, - .set_vlan_ports = ar8327_sw_set_ports, - .apply_config = ar8327_sw_hw_apply, - .reset_switch = ar8xxx_sw_reset_switch, - .get_port_link = ar8xxx_sw_get_port_link, - .get_port_stats = ar8xxx_sw_get_port_stats, -}; - -const struct ar8xxx_chip ar8327_chip = { - .caps = AR8XXX_CAP_GIGE | AR8XXX_CAP_MIB_COUNTERS, - .config_at_probe = true, - .mii_lo_first = true, - - .name = "Atheros AR8327", - .ports = AR8327_NUM_PORTS, - .vlans = AR83X7_MAX_VLANS, - .swops = &ar8327_sw_ops, - - .reg_port_stats_start = 0x1000, - .reg_port_stats_length = 0x100, - .reg_arl_ctrl = AR8327_REG_ARL_CTRL, - - .hw_init = ar8327_hw_init, - .cleanup = ar8327_cleanup, - .init_globals = ar8327_init_globals, - .init_port = ar8327_init_port, - .setup_port = ar8327_setup_port, - .read_port_status = ar8327_read_port_status, - .read_port_eee_status = ar8327_read_port_eee_status, - .atu_flush = ar8327_atu_flush, - .atu_flush_port = ar8327_atu_flush_port, - .vtu_flush = ar8327_vtu_flush, - .vtu_load_vlan = ar8327_vtu_load_vlan, - .phy_fixup = ar8327_phy_fixup, - .set_mirror_regs = ar8327_set_mirror_regs, - .get_arl_entry = ar8327_get_arl_entry, - .sw_hw_apply = ar8327_sw_hw_apply, - - .num_mibs = ARRAY_SIZE(ar8236_mibs), - .mib_decs = ar8236_mibs, - .mib_func = AR8327_REG_MIB_FUNC, - .mib_rxb_id = AR8236_MIB_RXB_ID, - .mib_txb_id = AR8236_MIB_TXB_ID, -}; - -const struct ar8xxx_chip ar8337_chip = { - .caps = AR8XXX_CAP_GIGE | AR8XXX_CAP_MIB_COUNTERS, - .config_at_probe = true, - .mii_lo_first = true, - - .name = "Atheros AR8337", - .ports = AR8327_NUM_PORTS, - .vlans = AR83X7_MAX_VLANS, - .swops = &ar8327_sw_ops, - - .reg_port_stats_start = 0x1000, - .reg_port_stats_length = 0x100, - .reg_arl_ctrl = AR8327_REG_ARL_CTRL, - - .hw_init = ar8327_hw_init, - .cleanup = ar8327_cleanup, - .init_globals = ar8327_init_globals, - .init_port = ar8327_init_port, - .setup_port = ar8327_setup_port, - .read_port_status = ar8327_read_port_status, - .read_port_eee_status = ar8327_read_port_eee_status, - .atu_flush = ar8327_atu_flush, - .atu_flush_port = ar8327_atu_flush_port, - .vtu_flush = ar8327_vtu_flush, - .vtu_load_vlan = ar8327_vtu_load_vlan, - .phy_fixup = ar8327_phy_fixup, - .set_mirror_regs = ar8327_set_mirror_regs, - .get_arl_entry = ar8327_get_arl_entry, - .sw_hw_apply = ar8327_sw_hw_apply, - .phy_rgmii_set = ar8327_phy_rgmii_set, - - .num_mibs = ARRAY_SIZE(ar8236_mibs), - .mib_decs = ar8236_mibs, - .mib_func = AR8327_REG_MIB_FUNC, - .mib_rxb_id = AR8236_MIB_RXB_ID, - .mib_txb_id = AR8236_MIB_TXB_ID, -}; diff --git a/target/linux/generic/files-6.12/drivers/net/phy/ar8327.h b/target/linux/generic/files-6.12/drivers/net/phy/ar8327.h deleted file mode 100644 index 088b28861855a8..00000000000000 --- a/target/linux/generic/files-6.12/drivers/net/phy/ar8327.h +++ /dev/null @@ -1,333 +0,0 @@ -/* - * ar8327.h: AR8216 switch driver - * - * Copyright (C) 2009 Felix Fietkau - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#ifndef __AR8327_H -#define __AR8327_H - -#define AR8327_NUM_PORTS 7 -#define AR8327_NUM_LEDS 15 -#define AR8327_PORTS_ALL 0x7f -#define AR8327_NUM_LED_CTRL_REGS 4 - -#define AR8327_REG_MASK 0x000 - -#define AR8327_REG_PAD0_MODE 0x004 -#define AR8327_REG_PAD5_MODE 0x008 -#define AR8327_REG_PAD6_MODE 0x00c -#define AR8327_PAD_MAC_MII_RXCLK_SEL BIT(0) -#define AR8327_PAD_MAC_MII_TXCLK_SEL BIT(1) -#define AR8327_PAD_MAC_MII_EN BIT(2) -#define AR8327_PAD_MAC_GMII_RXCLK_SEL BIT(4) -#define AR8327_PAD_MAC_GMII_TXCLK_SEL BIT(5) -#define AR8327_PAD_MAC_GMII_EN BIT(6) -#define AR8327_PAD_SGMII_EN BIT(7) -#define AR8327_PAD_PHY_MII_RXCLK_SEL BIT(8) -#define AR8327_PAD_PHY_MII_TXCLK_SEL BIT(9) -#define AR8327_PAD_PHY_MII_EN BIT(10) -#define AR8327_PAD_PHY_GMII_PIPE_RXCLK_SEL BIT(11) -#define AR8327_PAD_PHY_GMII_RXCLK_SEL BIT(12) -#define AR8327_PAD_PHY_GMII_TXCLK_SEL BIT(13) -#define AR8327_PAD_PHY_GMII_EN BIT(14) -#define AR8327_PAD_PHYX_GMII_EN BIT(16) -#define AR8327_PAD_PHYX_RGMII_EN BIT(17) -#define AR8327_PAD_PHYX_MII_EN BIT(18) -#define AR8327_PAD_SGMII_DELAY_EN BIT(19) -#define AR8327_PAD_RGMII_RXCLK_DELAY_SEL BITS(20, 2) -#define AR8327_PAD_RGMII_RXCLK_DELAY_SEL_S 20 -#define AR8327_PAD_RGMII_TXCLK_DELAY_SEL BITS(22, 2) -#define AR8327_PAD_RGMII_TXCLK_DELAY_SEL_S 22 -#define AR8327_PAD_RGMII_RXCLK_DELAY_EN BIT(24) -#define AR8327_PAD_RGMII_TXCLK_DELAY_EN BIT(25) -#define AR8327_PAD_RGMII_EN BIT(26) - -#define AR8327_REG_POWER_ON_STRAP 0x010 -#define AR8327_POWER_ON_STRAP_POWER_ON_SEL BIT(31) -#define AR8327_POWER_ON_STRAP_LED_OPEN_EN BIT(24) -#define AR8327_POWER_ON_STRAP_SERDES_AEN BIT(7) - -#define AR8327_REG_INT_STATUS0 0x020 -#define AR8327_INT0_VT_DONE BIT(20) - -#define AR8327_REG_INT_STATUS1 0x024 -#define AR8327_REG_INT_MASK0 0x028 -#define AR8327_REG_INT_MASK1 0x02c - -#define AR8327_REG_MODULE_EN 0x030 -#define AR8327_MODULE_EN_MIB BIT(0) - -#define AR8327_REG_MIB_FUNC 0x034 -#define AR8327_MIB_CPU_KEEP BIT(20) - -#define AR8327_REG_SERVICE_TAG 0x048 -#define AR8327_REG_LED_CTRL(_i) (0x050 + (_i) * 4) -#define AR8327_REG_LED_CTRL0 0x050 -#define AR8327_REG_LED_CTRL1 0x054 -#define AR8327_REG_LED_CTRL2 0x058 -#define AR8327_REG_LED_CTRL3 0x05c -#define AR8327_REG_MAC_ADDR0 0x060 -#define AR8327_REG_MAC_ADDR1 0x064 - -#define AR8327_REG_MAX_FRAME_SIZE 0x078 -#define AR8327_MAX_FRAME_SIZE_MTU BITS(0, 14) - -#define AR8327_REG_PORT_STATUS(_i) (0x07c + (_i) * 4) -#define AR8327_PORT_STATUS_TXFLOW_AUTO BIT(10) -#define AR8327_PORT_STATUS_RXFLOW_AUTO BIT(11) - -#define AR8327_REG_HEADER_CTRL 0x098 -#define AR8327_REG_PORT_HEADER(_i) (0x09c + (_i) * 4) - -#define AR8327_REG_SGMII_CTRL 0x0e0 -#define AR8327_SGMII_CTRL_EN_PLL BIT(1) -#define AR8327_SGMII_CTRL_EN_RX BIT(2) -#define AR8327_SGMII_CTRL_EN_TX BIT(3) - -#define AR8327_REG_EEE_CTRL 0x100 -#define AR8327_EEE_CTRL_DISABLE_PHY(_i) BIT(4 + (_i) * 2) - -#define AR8327_REG_FRAME_ACK_CTRL0 0x210 -#define AR8327_FRAME_ACK_CTRL_IGMP_MLD_EN0 BIT(0) -#define AR8327_FRAME_ACK_CTRL_IGMP_JOIN_EN0 BIT(1) -#define AR8327_FRAME_ACK_CTRL_IGMP_LEAVE_EN0 BIT(2) -#define AR8327_FRAME_ACK_CTRL_EAPOL_EN0 BIT(3) -#define AR8327_FRAME_ACK_CTRL_DHCP_EN0 BIT(4) -#define AR8327_FRAME_ACK_CTRL_ARP_ACK_EN0 BIT(5) -#define AR8327_FRAME_ACK_CTRL_ARP_REQ_EN0 BIT(6) -#define AR8327_FRAME_ACK_CTRL_IGMP_MLD_EN1 BIT(8) -#define AR8327_FRAME_ACK_CTRL_IGMP_JOIN_EN1 BIT(9) -#define AR8327_FRAME_ACK_CTRL_IGMP_LEAVE_EN1 BIT(10) -#define AR8327_FRAME_ACK_CTRL_EAPOL_EN1 BIT(11) -#define AR8327_FRAME_ACK_CTRL_DHCP_EN1 BIT(12) -#define AR8327_FRAME_ACK_CTRL_ARP_ACK_EN1 BIT(13) -#define AR8327_FRAME_ACK_CTRL_ARP_REQ_EN1 BIT(14) -#define AR8327_FRAME_ACK_CTRL_IGMP_MLD_EN2 BIT(16) -#define AR8327_FRAME_ACK_CTRL_IGMP_JOIN_EN2 BIT(17) -#define AR8327_FRAME_ACK_CTRL_IGMP_LEAVE_EN2 BIT(18) -#define AR8327_FRAME_ACK_CTRL_EAPOL_EN2 BIT(19) -#define AR8327_FRAME_ACK_CTRL_DHCP_EN2 BIT(20) -#define AR8327_FRAME_ACK_CTRL_ARP_ACK_EN2 BIT(21) -#define AR8327_FRAME_ACK_CTRL_ARP_REQ_EN2 BIT(22) -#define AR8327_FRAME_ACK_CTRL_IGMP_MLD_EN3 BIT(24) -#define AR8327_FRAME_ACK_CTRL_IGMP_JOIN_EN3 BIT(25) -#define AR8327_FRAME_ACK_CTRL_IGMP_LEAVE_EN3 BIT(26) -#define AR8327_FRAME_ACK_CTRL_EAPOL_EN3 BIT(27) -#define AR8327_FRAME_ACK_CTRL_DHCP_EN3 BIT(28) -#define AR8327_FRAME_ACK_CTRL_ARP_ACK_EN3 BIT(29) -#define AR8327_FRAME_ACK_CTRL_ARP_REQ_EN3 BIT(30) - -#define AR8327_REG_FRAME_ACK_CTRL1 0x214 -#define AR8327_FRAME_ACK_CTRL_IGMP_MLD_EN4 BIT(0) -#define AR8327_FRAME_ACK_CTRL_IGMP_JOIN_EN4 BIT(1) -#define AR8327_FRAME_ACK_CTRL_IGMP_LEAVE_EN4 BIT(2) -#define AR8327_FRAME_ACK_CTRL_EAPOL_EN4 BIT(3) -#define AR8327_FRAME_ACK_CTRL_DHCP_EN4 BIT(4) -#define AR8327_FRAME_ACK_CTRL_ARP_ACK_EN4 BIT(5) -#define AR8327_FRAME_ACK_CTRL_ARP_REQ_EN4 BIT(6) -#define AR8327_FRAME_ACK_CTRL_IGMP_MLD_EN5 BIT(8) -#define AR8327_FRAME_ACK_CTRL_IGMP_JOIN_EN5 BIT(9) -#define AR8327_FRAME_ACK_CTRL_IGMP_LEAVE_EN5 BIT(10) -#define AR8327_FRAME_ACK_CTRL_EAPOL_EN5 BIT(11) -#define AR8327_FRAME_ACK_CTRL_DHCP_EN5 BIT(12) -#define AR8327_FRAME_ACK_CTRL_ARP_ACK_EN5 BIT(13) -#define AR8327_FRAME_ACK_CTRL_ARP_REQ_EN5 BIT(14) -#define AR8327_FRAME_ACK_CTRL_IGMP_MLD_EN6 BIT(16) -#define AR8327_FRAME_ACK_CTRL_IGMP_JOIN_EN6 BIT(17) -#define AR8327_FRAME_ACK_CTRL_IGMP_LEAVE_EN6 BIT(18) -#define AR8327_FRAME_ACK_CTRL_EAPOL_EN6 BIT(19) -#define AR8327_FRAME_ACK_CTRL_DHCP_EN6 BIT(20) -#define AR8327_FRAME_ACK_CTRL_ARP_ACK_EN6 BIT(21) -#define AR8327_FRAME_ACK_CTRL_ARP_REQ_EN6 BIT(22) -#define AR8327_FRAME_ACK_CTRL_IGMP_V3_EN BIT(24) -#define AR8327_FRAME_ACK_CTRL_PPPOE_EN BIT(25) - -#define AR8327_REG_FRAME_ACK_CTRL(_i) (0x210 + ((_i) / 4) * 0x4) -#define AR8327_FRAME_ACK_CTRL_IGMP_MLD BIT(0) -#define AR8327_FRAME_ACK_CTRL_IGMP_JOIN BIT(1) -#define AR8327_FRAME_ACK_CTRL_IGMP_LEAVE BIT(2) -#define AR8327_FRAME_ACK_CTRL_EAPOL BIT(3) -#define AR8327_FRAME_ACK_CTRL_DHCP BIT(4) -#define AR8327_FRAME_ACK_CTRL_ARP_ACK BIT(5) -#define AR8327_FRAME_ACK_CTRL_ARP_REQ BIT(6) -#define AR8327_FRAME_ACK_CTRL_S(_i) (((_i) % 4) * 8) - -#define AR8327_REG_PORT_VLAN0(_i) (0x420 + (_i) * 0x8) -#define AR8327_PORT_VLAN0_DEF_PRI_MASK BITS(0, 3) -#define AR8327_PORT_VLAN0_DEF_SVID BITS(0, 12) -#define AR8327_PORT_VLAN0_DEF_SVID_S 0 -#define AR8327_PORT_VLAN0_DEF_SPRI BITS(13, 3) -#define AR8327_PORT_VLAN0_DEF_SPRI_S 13 -#define AR8327_PORT_VLAN0_DEF_CVID BITS(16, 12) -#define AR8327_PORT_VLAN0_DEF_CVID_S 16 -#define AR8327_PORT_VLAN0_DEF_CPRI BITS(29, 3) -#define AR8327_PORT_VLAN0_DEF_CPRI_S 29 - -#define AR8327_REG_PORT_VLAN1(_i) (0x424 + (_i) * 0x8) -#define AR8327_PORT_VLAN1_VLAN_PRI_PROP BIT(4) -#define AR8327_PORT_VLAN1_PORT_VLAN_PROP BIT(6) -#define AR8327_PORT_VLAN1_OUT_MODE BITS(12, 2) -#define AR8327_PORT_VLAN1_OUT_MODE_S 12 -#define AR8327_PORT_VLAN1_OUT_MODE_UNMOD 0 -#define AR8327_PORT_VLAN1_OUT_MODE_UNTAG 1 -#define AR8327_PORT_VLAN1_OUT_MODE_TAG 2 -#define AR8327_PORT_VLAN1_OUT_MODE_UNTOUCH 3 - -#define AR8327_REG_ATU_DATA0 0x600 -#define AR8327_ATU_ADDR0 BITS(0, 8) -#define AR8327_ATU_ADDR0_S 0 -#define AR8327_ATU_ADDR1 BITS(8, 8) -#define AR8327_ATU_ADDR1_S 8 -#define AR8327_ATU_ADDR2 BITS(16, 8) -#define AR8327_ATU_ADDR2_S 16 -#define AR8327_ATU_ADDR3 BITS(24, 8) -#define AR8327_ATU_ADDR3_S 24 -#define AR8327_REG_ATU_DATA1 0x604 -#define AR8327_ATU_ADDR4 BITS(0, 8) -#define AR8327_ATU_ADDR4_S 0 -#define AR8327_ATU_ADDR5 BITS(8, 8) -#define AR8327_ATU_ADDR5_S 8 -#define AR8327_ATU_PORTS BITS(16, 7) -#define AR8327_ATU_PORTS_S 16 -#define AR8327_ATU_PORT0 BIT(16) -#define AR8327_ATU_PORT1 BIT(17) -#define AR8327_ATU_PORT2 BIT(18) -#define AR8327_ATU_PORT3 BIT(19) -#define AR8327_ATU_PORT4 BIT(20) -#define AR8327_ATU_PORT5 BIT(21) -#define AR8327_ATU_PORT6 BIT(22) -#define AR8327_REG_ATU_DATA2 0x608 -#define AR8327_ATU_STATUS BITS(0, 4) - -#define AR8327_REG_ATU_FUNC 0x60c -#define AR8327_ATU_FUNC_OP BITS(0, 4) -#define AR8327_ATU_FUNC_OP_NOOP 0x0 -#define AR8327_ATU_FUNC_OP_FLUSH 0x1 -#define AR8327_ATU_FUNC_OP_LOAD 0x2 -#define AR8327_ATU_FUNC_OP_PURGE 0x3 -#define AR8327_ATU_FUNC_OP_FLUSH_UNLOCKED 0x4 -#define AR8327_ATU_FUNC_OP_FLUSH_PORT 0x5 -#define AR8327_ATU_FUNC_OP_GET_NEXT 0x6 -#define AR8327_ATU_FUNC_OP_SEARCH_MAC 0x7 -#define AR8327_ATU_FUNC_OP_CHANGE_TRUNK 0x8 -#define AR8327_ATU_PORT_NUM BITS(8, 4) -#define AR8327_ATU_PORT_NUM_S 8 -#define AR8327_ATU_FUNC_BUSY BIT(31) - -#define AR8327_REG_VTU_FUNC0 0x0610 -#define AR8327_VTU_FUNC0_EG_MODE BITS(4, 14) -#define AR8327_VTU_FUNC0_EG_MODE_S(_i) (4 + (_i) * 2) -#define AR8327_VTU_FUNC0_EG_MODE_KEEP 0 -#define AR8327_VTU_FUNC0_EG_MODE_UNTAG 1 -#define AR8327_VTU_FUNC0_EG_MODE_TAG 2 -#define AR8327_VTU_FUNC0_EG_MODE_NOT 3 -#define AR8327_VTU_FUNC0_IVL BIT(19) -#define AR8327_VTU_FUNC0_VALID BIT(20) - -#define AR8327_REG_VTU_FUNC1 0x0614 -#define AR8327_VTU_FUNC1_OP BITS(0, 3) -#define AR8327_VTU_FUNC1_OP_NOOP 0 -#define AR8327_VTU_FUNC1_OP_FLUSH 1 -#define AR8327_VTU_FUNC1_OP_LOAD 2 -#define AR8327_VTU_FUNC1_OP_PURGE 3 -#define AR8327_VTU_FUNC1_OP_REMOVE_PORT 4 -#define AR8327_VTU_FUNC1_OP_GET_NEXT 5 -#define AR8327_VTU_FUNC1_OP_GET_ONE 6 -#define AR8327_VTU_FUNC1_FULL BIT(4) -#define AR8327_VTU_FUNC1_PORT BIT(8, 4) -#define AR8327_VTU_FUNC1_PORT_S 8 -#define AR8327_VTU_FUNC1_VID BIT(16, 12) -#define AR8327_VTU_FUNC1_VID_S 16 -#define AR8327_VTU_FUNC1_BUSY BIT(31) - -#define AR8327_REG_ARL_CTRL 0x0618 - -#define AR8327_REG_FWD_CTRL0 0x620 -#define AR8327_FWD_CTRL0_CPU_PORT_EN BIT(10) -#define AR8327_FWD_CTRL0_MIRROR_PORT BITS(4, 4) -#define AR8327_FWD_CTRL0_MIRROR_PORT_S 4 - -#define AR8327_REG_FWD_CTRL1 0x624 -#define AR8327_FWD_CTRL1_UC_FLOOD BITS(0, 7) -#define AR8327_FWD_CTRL1_UC_FLOOD_S 0 -#define AR8327_FWD_CTRL1_MC_FLOOD BITS(8, 7) -#define AR8327_FWD_CTRL1_MC_FLOOD_S 8 -#define AR8327_FWD_CTRL1_BC_FLOOD BITS(16, 7) -#define AR8327_FWD_CTRL1_BC_FLOOD_S 16 -#define AR8327_FWD_CTRL1_IGMP BITS(24, 7) -#define AR8327_FWD_CTRL1_IGMP_S 24 - -#define AR8327_REG_PORT_LOOKUP(_i) (0x660 + (_i) * 0xc) -#define AR8327_PORT_LOOKUP_MEMBER BITS(0, 7) -#define AR8327_PORT_LOOKUP_IN_MODE BITS(8, 2) -#define AR8327_PORT_LOOKUP_IN_MODE_S 8 -#define AR8327_PORT_LOOKUP_STATE BITS(16, 3) -#define AR8327_PORT_LOOKUP_STATE_S 16 -#define AR8327_PORT_LOOKUP_LEARN BIT(20) -#define AR8327_PORT_LOOKUP_ING_MIRROR_EN BIT(25) - -#define AR8327_REG_PORT_PRIO(_i) (0x664 + (_i) * 0xc) - -#define AR8327_REG_PORT_HOL_CTRL1(_i) (0x974 + (_i) * 0x8) -#define AR8327_PORT_HOL_CTRL1_EG_MIRROR_EN BIT(16) - -#define AR8337_PAD_MAC06_EXCHANGE_EN BIT(31) - -#define AR8327_PHY_MODE_SEL 0x12 -#define AR8327_PHY_MODE_SEL_RGMII BIT(3) -#define AR8327_PHY_TEST_CTRL 0x0 -#define AR8327_PHY_TEST_CTRL_RGMII_RX_DELAY BIT(15) -#define AR8327_PHY_SYS_CTRL 0x5 -#define AR8327_PHY_SYS_CTRL_RGMII_TX_DELAY BIT(8) - -enum ar8327_led_pattern { - AR8327_LED_PATTERN_OFF = 0, - AR8327_LED_PATTERN_BLINK, - AR8327_LED_PATTERN_ON, - AR8327_LED_PATTERN_RULE, -}; - -struct ar8327_led_entry { - unsigned reg; - unsigned shift; -}; - -struct ar8327_led { - struct led_classdev cdev; - struct ar8xxx_priv *sw_priv; - - char *name; - bool active_low; - u8 led_num; - enum ar8327_led_mode mode; - - struct mutex mutex; - spinlock_t lock; - struct work_struct led_work; - bool enable_hw_mode; - enum ar8327_led_pattern pattern; -}; - -struct ar8327_data { - u32 port0_status; - u32 port6_status; - - struct ar8327_led **leds; - unsigned int num_leds; - - /* all fields below are cleared on reset */ - bool eee[AR8XXX_NUM_PHYS]; -}; - -#endif diff --git a/target/linux/generic/files-6.12/drivers/net/phy/b53/Kconfig b/target/linux/generic/files-6.12/drivers/net/phy/b53/Kconfig deleted file mode 100644 index 08287e7adf79d4..00000000000000 --- a/target/linux/generic/files-6.12/drivers/net/phy/b53/Kconfig +++ /dev/null @@ -1,37 +0,0 @@ -menuconfig SWCONFIG_B53 - tristate "Broadcom bcm53xx managed switch support" - depends on SWCONFIG - help - This driver adds support for Broadcom managed switch chips. It supports - BCM5325E, BCM5365, BCM539x, BCM53115 and BCM53125 as well as BCM63XX - integrated switches. - -config SWCONFIG_B53_SPI_DRIVER - tristate "B53 SPI connected switch driver" - depends on SWCONFIG_B53 && SPI - help - Select to enable support for registering switches configured through SPI. - -config SWCONFIG_B53_PHY_DRIVER - tristate "B53 MDIO connected switch driver" - depends on SWCONFIG_B53 - select SWCONFIG_B53_PHY_FIXUP - help - Select to enable support for registering switches configured through MDIO. - -config SWCONFIG_B53_MMAP_DRIVER - tristate "B53 MMAP connected switch driver" - depends on SWCONFIG_B53 - help - Select to enable support for memory-mapped switches like the BCM63XX - integrated switches. - -config SWCONFIG_B53_SRAB_DRIVER - tristate "B53 SRAB connected switch driver" - depends on SWCONFIG_B53 - help - Select to enable support for memory-mapped Switch Register Access - Bridge Registers (SRAB) like it is found on the BCM53010 - -config SWCONFIG_B53_PHY_FIXUP - bool diff --git a/target/linux/generic/files-6.12/drivers/net/phy/b53/Makefile b/target/linux/generic/files-6.12/drivers/net/phy/b53/Makefile deleted file mode 100644 index 13ff366448dff1..00000000000000 --- a/target/linux/generic/files-6.12/drivers/net/phy/b53/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -obj-$(CONFIG_SWCONFIG_B53) += b53_common.o - -obj-$(CONFIG_SWCONFIG_B53_PHY_FIXUP) += b53_phy_fixup.o - -obj-$(CONFIG_SWCONFIG_B53_MMAP_DRIVER) += b53_mmap.o -obj-$(CONFIG_SWCONFIG_B53_SRAB_DRIVER) += b53_srab.o -obj-$(CONFIG_SWCONFIG_B53_PHY_DRIVER) += b53_mdio.o -obj-$(CONFIG_SWCONFIG_B53_SPI_DRIVER) += b53_spi.o - -ccflags-y += -Werror diff --git a/target/linux/generic/files-6.12/drivers/net/phy/b53/b53_common.c b/target/linux/generic/files-6.12/drivers/net/phy/b53/b53_common.c deleted file mode 100644 index d5f9bfc2f0438b..00000000000000 --- a/target/linux/generic/files-6.12/drivers/net/phy/b53/b53_common.c +++ /dev/null @@ -1,1724 +0,0 @@ -/* - * B53 switch driver main logic - * - * Copyright (C) 2011-2013 Jonas Gorski - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "b53_regs.h" -#include "b53_priv.h" - -/* buffer size needed for displaying all MIBs with max'd values */ -#define B53_BUF_SIZE 1188 - -struct b53_mib_desc { - u8 size; - u8 offset; - const char *name; -}; - -/* BCM5365 MIB counters */ -static const struct b53_mib_desc b53_mibs_65[] = { - { 8, 0x00, "TxOctets" }, - { 4, 0x08, "TxDropPkts" }, - { 4, 0x10, "TxBroadcastPkts" }, - { 4, 0x14, "TxMulticastPkts" }, - { 4, 0x18, "TxUnicastPkts" }, - { 4, 0x1c, "TxCollisions" }, - { 4, 0x20, "TxSingleCollision" }, - { 4, 0x24, "TxMultipleCollision" }, - { 4, 0x28, "TxDeferredTransmit" }, - { 4, 0x2c, "TxLateCollision" }, - { 4, 0x30, "TxExcessiveCollision" }, - { 4, 0x38, "TxPausePkts" }, - { 8, 0x44, "RxOctets" }, - { 4, 0x4c, "RxUndersizePkts" }, - { 4, 0x50, "RxPausePkts" }, - { 4, 0x54, "Pkts64Octets" }, - { 4, 0x58, "Pkts65to127Octets" }, - { 4, 0x5c, "Pkts128to255Octets" }, - { 4, 0x60, "Pkts256to511Octets" }, - { 4, 0x64, "Pkts512to1023Octets" }, - { 4, 0x68, "Pkts1024to1522Octets" }, - { 4, 0x6c, "RxOversizePkts" }, - { 4, 0x70, "RxJabbers" }, - { 4, 0x74, "RxAlignmentErrors" }, - { 4, 0x78, "RxFCSErrors" }, - { 8, 0x7c, "RxGoodOctets" }, - { 4, 0x84, "RxDropPkts" }, - { 4, 0x88, "RxUnicastPkts" }, - { 4, 0x8c, "RxMulticastPkts" }, - { 4, 0x90, "RxBroadcastPkts" }, - { 4, 0x94, "RxSAChanges" }, - { 4, 0x98, "RxFragments" }, - { }, -}; - -#define B63XX_MIB_TXB_ID 0 /* TxOctets */ -#define B63XX_MIB_RXB_ID 14 /* RxOctets */ - -/* BCM63xx MIB counters */ -static const struct b53_mib_desc b53_mibs_63xx[] = { - { 8, 0x00, "TxOctets" }, - { 4, 0x08, "TxDropPkts" }, - { 4, 0x0c, "TxQoSPkts" }, - { 4, 0x10, "TxBroadcastPkts" }, - { 4, 0x14, "TxMulticastPkts" }, - { 4, 0x18, "TxUnicastPkts" }, - { 4, 0x1c, "TxCollisions" }, - { 4, 0x20, "TxSingleCollision" }, - { 4, 0x24, "TxMultipleCollision" }, - { 4, 0x28, "TxDeferredTransmit" }, - { 4, 0x2c, "TxLateCollision" }, - { 4, 0x30, "TxExcessiveCollision" }, - { 4, 0x38, "TxPausePkts" }, - { 8, 0x3c, "TxQoSOctets" }, - { 8, 0x44, "RxOctets" }, - { 4, 0x4c, "RxUndersizePkts" }, - { 4, 0x50, "RxPausePkts" }, - { 4, 0x54, "Pkts64Octets" }, - { 4, 0x58, "Pkts65to127Octets" }, - { 4, 0x5c, "Pkts128to255Octets" }, - { 4, 0x60, "Pkts256to511Octets" }, - { 4, 0x64, "Pkts512to1023Octets" }, - { 4, 0x68, "Pkts1024to1522Octets" }, - { 4, 0x6c, "RxOversizePkts" }, - { 4, 0x70, "RxJabbers" }, - { 4, 0x74, "RxAlignmentErrors" }, - { 4, 0x78, "RxFCSErrors" }, - { 8, 0x7c, "RxGoodOctets" }, - { 4, 0x84, "RxDropPkts" }, - { 4, 0x88, "RxUnicastPkts" }, - { 4, 0x8c, "RxMulticastPkts" }, - { 4, 0x90, "RxBroadcastPkts" }, - { 4, 0x94, "RxSAChanges" }, - { 4, 0x98, "RxFragments" }, - { 4, 0xa0, "RxSymbolErrors" }, - { 4, 0xa4, "RxQoSPkts" }, - { 8, 0xa8, "RxQoSOctets" }, - { 4, 0xb0, "Pkts1523to2047Octets" }, - { 4, 0xb4, "Pkts2048to4095Octets" }, - { 4, 0xb8, "Pkts4096to8191Octets" }, - { 4, 0xbc, "Pkts8192to9728Octets" }, - { 4, 0xc0, "RxDiscarded" }, - { } -}; - -#define B53XX_MIB_TXB_ID 0 /* TxOctets */ -#define B53XX_MIB_RXB_ID 12 /* RxOctets */ - -/* MIB counters */ -static const struct b53_mib_desc b53_mibs[] = { - { 8, 0x00, "TxOctets" }, - { 4, 0x08, "TxDropPkts" }, - { 4, 0x10, "TxBroadcastPkts" }, - { 4, 0x14, "TxMulticastPkts" }, - { 4, 0x18, "TxUnicastPkts" }, - { 4, 0x1c, "TxCollisions" }, - { 4, 0x20, "TxSingleCollision" }, - { 4, 0x24, "TxMultipleCollision" }, - { 4, 0x28, "TxDeferredTransmit" }, - { 4, 0x2c, "TxLateCollision" }, - { 4, 0x30, "TxExcessiveCollision" }, - { 4, 0x38, "TxPausePkts" }, - { 8, 0x50, "RxOctets" }, - { 4, 0x58, "RxUndersizePkts" }, - { 4, 0x5c, "RxPausePkts" }, - { 4, 0x60, "Pkts64Octets" }, - { 4, 0x64, "Pkts65to127Octets" }, - { 4, 0x68, "Pkts128to255Octets" }, - { 4, 0x6c, "Pkts256to511Octets" }, - { 4, 0x70, "Pkts512to1023Octets" }, - { 4, 0x74, "Pkts1024to1522Octets" }, - { 4, 0x78, "RxOversizePkts" }, - { 4, 0x7c, "RxJabbers" }, - { 4, 0x80, "RxAlignmentErrors" }, - { 4, 0x84, "RxFCSErrors" }, - { 8, 0x88, "RxGoodOctets" }, - { 4, 0x90, "RxDropPkts" }, - { 4, 0x94, "RxUnicastPkts" }, - { 4, 0x98, "RxMulticastPkts" }, - { 4, 0x9c, "RxBroadcastPkts" }, - { 4, 0xa0, "RxSAChanges" }, - { 4, 0xa4, "RxFragments" }, - { 4, 0xa8, "RxJumboPkts" }, - { 4, 0xac, "RxSymbolErrors" }, - { 4, 0xc0, "RxDiscarded" }, - { } -}; - -static int b53_do_vlan_op(struct b53_device *dev, u8 op) -{ - unsigned int i; - - b53_write8(dev, B53_ARLIO_PAGE, dev->vta_regs[0], VTA_START_CMD | op); - - for (i = 0; i < 10; i++) { - u8 vta; - - b53_read8(dev, B53_ARLIO_PAGE, dev->vta_regs[0], &vta); - if (!(vta & VTA_START_CMD)) - return 0; - - usleep_range(100, 200); - } - - return -EIO; -} - -static void b53_set_vlan_entry(struct b53_device *dev, u16 vid, u16 members, - u16 untag) -{ - if (is5325(dev)) { - u32 entry = 0; - - if (members) { - entry = ((untag & VA_UNTAG_MASK_25) << VA_UNTAG_S_25) | - members; - if (dev->core_rev >= 3) - entry |= VA_VALID_25_R4 | vid << VA_VID_HIGH_S; - else - entry |= VA_VALID_25; - } - - b53_write32(dev, B53_VLAN_PAGE, B53_VLAN_WRITE_25, entry); - b53_write16(dev, B53_VLAN_PAGE, B53_VLAN_TABLE_ACCESS_25, vid | - VTA_RW_STATE_WR | VTA_RW_OP_EN); - } else if (is5365(dev)) { - u16 entry = 0; - - if (members) - entry = ((untag & VA_UNTAG_MASK_65) << VA_UNTAG_S_65) | - members | VA_VALID_65; - - b53_write16(dev, B53_VLAN_PAGE, B53_VLAN_WRITE_65, entry); - b53_write16(dev, B53_VLAN_PAGE, B53_VLAN_TABLE_ACCESS_65, vid | - VTA_RW_STATE_WR | VTA_RW_OP_EN); - } else { - b53_write16(dev, B53_ARLIO_PAGE, dev->vta_regs[1], vid); - b53_write32(dev, B53_ARLIO_PAGE, dev->vta_regs[2], - (untag << VTE_UNTAG_S) | members); - - b53_do_vlan_op(dev, VTA_CMD_WRITE); - } -} - -void b53_set_forwarding(struct b53_device *dev, int enable) -{ - u8 mgmt; - - b53_read8(dev, B53_CTRL_PAGE, B53_SWITCH_MODE, &mgmt); - - if (enable) - mgmt |= SM_SW_FWD_EN; - else - mgmt &= ~SM_SW_FWD_EN; - - b53_write8(dev, B53_CTRL_PAGE, B53_SWITCH_MODE, mgmt); -} - -static void b53_enable_vlan(struct b53_device *dev, int enable) -{ - u8 mgmt, vc0, vc1, vc4 = 0, vc5; - - b53_read8(dev, B53_CTRL_PAGE, B53_SWITCH_MODE, &mgmt); - b53_read8(dev, B53_VLAN_PAGE, B53_VLAN_CTRL0, &vc0); - b53_read8(dev, B53_VLAN_PAGE, B53_VLAN_CTRL1, &vc1); - - if (is5325(dev) || is5365(dev)) { - b53_read8(dev, B53_VLAN_PAGE, B53_VLAN_CTRL4_25, &vc4); - b53_read8(dev, B53_VLAN_PAGE, B53_VLAN_CTRL5_25, &vc5); - } else if (is63xx(dev)) { - b53_read8(dev, B53_VLAN_PAGE, B53_VLAN_CTRL4_63XX, &vc4); - b53_read8(dev, B53_VLAN_PAGE, B53_VLAN_CTRL5_63XX, &vc5); - } else { - b53_read8(dev, B53_VLAN_PAGE, B53_VLAN_CTRL4, &vc4); - b53_read8(dev, B53_VLAN_PAGE, B53_VLAN_CTRL5, &vc5); - } - - mgmt &= ~SM_SW_FWD_MODE; - - if (enable) { - vc0 |= VC0_VLAN_EN | VC0_VID_CHK_EN | VC0_VID_HASH_VID; - vc1 |= VC1_RX_MCST_UNTAG_EN | VC1_RX_MCST_FWD_EN; - vc4 &= ~VC4_ING_VID_CHECK_MASK; - vc4 |= VC4_ING_VID_VIO_DROP << VC4_ING_VID_CHECK_S; - vc5 |= VC5_DROP_VTABLE_MISS; - - if (is5325(dev)) - vc0 &= ~VC0_RESERVED_1; - - if (is5325(dev) || is5365(dev)) - vc1 |= VC1_RX_MCST_TAG_EN; - - if (!is5325(dev) && !is5365(dev)) { - if (dev->allow_vid_4095) - vc5 |= VC5_VID_FFF_EN; - else - vc5 &= ~VC5_VID_FFF_EN; - } - } else { - vc0 &= ~(VC0_VLAN_EN | VC0_VID_CHK_EN | VC0_VID_HASH_VID); - vc1 &= ~(VC1_RX_MCST_UNTAG_EN | VC1_RX_MCST_FWD_EN); - vc4 &= ~VC4_ING_VID_CHECK_MASK; - vc5 &= ~VC5_DROP_VTABLE_MISS; - - if (is5325(dev) || is5365(dev)) - vc4 |= VC4_ING_VID_VIO_FWD << VC4_ING_VID_CHECK_S; - else - vc4 |= VC4_ING_VID_VIO_TO_IMP << VC4_ING_VID_CHECK_S; - - if (is5325(dev) || is5365(dev)) - vc1 &= ~VC1_RX_MCST_TAG_EN; - - if (!is5325(dev) && !is5365(dev)) - vc5 &= ~VC5_VID_FFF_EN; - } - - b53_write8(dev, B53_VLAN_PAGE, B53_VLAN_CTRL0, vc0); - b53_write8(dev, B53_VLAN_PAGE, B53_VLAN_CTRL1, vc1); - - if (is5325(dev) || is5365(dev)) { - /* enable the high 8 bit vid check on 5325 */ - if (is5325(dev) && enable) - b53_write8(dev, B53_VLAN_PAGE, B53_VLAN_CTRL3, - VC3_HIGH_8BIT_EN); - else - b53_write8(dev, B53_VLAN_PAGE, B53_VLAN_CTRL3, 0); - - b53_write8(dev, B53_VLAN_PAGE, B53_VLAN_CTRL4_25, vc4); - b53_write8(dev, B53_VLAN_PAGE, B53_VLAN_CTRL5_25, vc5); - } else if (is63xx(dev)) { - b53_write16(dev, B53_VLAN_PAGE, B53_VLAN_CTRL3_63XX, 0); - b53_write8(dev, B53_VLAN_PAGE, B53_VLAN_CTRL4_63XX, vc4); - b53_write8(dev, B53_VLAN_PAGE, B53_VLAN_CTRL5_63XX, vc5); - } else { - b53_write16(dev, B53_VLAN_PAGE, B53_VLAN_CTRL3, 0); - b53_write8(dev, B53_VLAN_PAGE, B53_VLAN_CTRL4, vc4); - b53_write8(dev, B53_VLAN_PAGE, B53_VLAN_CTRL5, vc5); - } - - b53_write8(dev, B53_CTRL_PAGE, B53_SWITCH_MODE, mgmt); -} - -static int b53_set_jumbo(struct b53_device *dev, int enable, int allow_10_100) -{ - u32 port_mask = 0; - u16 max_size = JMS_MIN_SIZE; - - if (is5325(dev) || is5365(dev)) - return -EINVAL; - - if (enable) { - port_mask = dev->enabled_ports; - max_size = JMS_MAX_SIZE; - if (allow_10_100) - port_mask |= JPM_10_100_JUMBO_EN; - } - - b53_write32(dev, B53_JUMBO_PAGE, dev->jumbo_pm_reg, port_mask); - return b53_write16(dev, B53_JUMBO_PAGE, dev->jumbo_size_reg, max_size); -} - -static int b53_flush_arl(struct b53_device *dev) -{ - unsigned int i; - - b53_write8(dev, B53_CTRL_PAGE, B53_FAST_AGE_CTRL, - FAST_AGE_DONE | FAST_AGE_DYNAMIC | FAST_AGE_STATIC); - - for (i = 0; i < 10; i++) { - u8 fast_age_ctrl; - - b53_read8(dev, B53_CTRL_PAGE, B53_FAST_AGE_CTRL, - &fast_age_ctrl); - - if (!(fast_age_ctrl & FAST_AGE_DONE)) - return 0; - - mdelay(1); - } - - pr_warn("time out while flushing ARL\n"); - - return -EINVAL; -} - -static void b53_enable_ports(struct b53_device *dev) -{ - unsigned i; - - b53_for_each_port(dev, i) { - u8 port_ctrl; - u16 pvlan_mask; - - /* - * prevent leaking packets between wan and lan in unmanaged - * mode through port vlans. - */ - if (dev->enable_vlan || is_cpu_port(dev, i)) - pvlan_mask = 0x1ff; - else if (is531x5(dev) || is5301x(dev)) - /* BCM53115 may use a different port as cpu port */ - pvlan_mask = BIT(dev->sw_dev.cpu_port); - else - pvlan_mask = BIT(B53_CPU_PORT); - - /* BCM5325 CPU port is at 8 */ - if ((is5325(dev) || is5365(dev)) && i == B53_CPU_PORT_25) - i = B53_CPU_PORT; - - if (dev->chip_id == BCM5398_DEVICE_ID && (i == 6 || i == 7)) - /* disable unused ports 6 & 7 */ - port_ctrl = PORT_CTRL_RX_DISABLE | PORT_CTRL_TX_DISABLE; - else if (i == B53_CPU_PORT) - port_ctrl = PORT_CTRL_RX_BCST_EN | - PORT_CTRL_RX_MCST_EN | - PORT_CTRL_RX_UCST_EN; - else - port_ctrl = 0; - - b53_write16(dev, B53_PVLAN_PAGE, B53_PVLAN_PORT_MASK(i), - pvlan_mask); - - /* port state is handled by bcm63xx_enet driver */ - if (!is63xx(dev) && !(is5301x(dev) && i == 6)) - b53_write8(dev, B53_CTRL_PAGE, B53_PORT_CTRL(i), - port_ctrl); - } -} - -static void b53_enable_mib(struct b53_device *dev) -{ - u8 gc; - - b53_read8(dev, B53_MGMT_PAGE, B53_GLOBAL_CONFIG, &gc); - - gc &= ~(GC_RESET_MIB | GC_MIB_AC_EN); - - b53_write8(dev, B53_MGMT_PAGE, B53_GLOBAL_CONFIG, gc); -} - -static int b53_apply(struct b53_device *dev) -{ - int i; - - /* clear all vlan entries */ - if (is5325(dev) || is5365(dev)) { - for (i = 1; i < dev->sw_dev.vlans; i++) - b53_set_vlan_entry(dev, i, 0, 0); - } else { - b53_do_vlan_op(dev, VTA_CMD_CLEAR); - } - - b53_enable_vlan(dev, dev->enable_vlan); - - /* fill VLAN table */ - if (dev->enable_vlan) { - for (i = 0; i < dev->sw_dev.vlans; i++) { - struct b53_vlan *vlan = &dev->vlans[i]; - - if (!vlan->members) - continue; - - b53_set_vlan_entry(dev, i, vlan->members, vlan->untag); - } - - b53_for_each_port(dev, i) - b53_write16(dev, B53_VLAN_PAGE, - B53_VLAN_PORT_DEF_TAG(i), - dev->ports[i].pvid); - } else { - b53_for_each_port(dev, i) - b53_write16(dev, B53_VLAN_PAGE, - B53_VLAN_PORT_DEF_TAG(i), 1); - - } - - b53_enable_ports(dev); - - if (!is5325(dev) && !is5365(dev)) - b53_set_jumbo(dev, dev->enable_jumbo, 1); - - return 0; -} - -static void b53_switch_reset_gpio(struct b53_device *dev) -{ - int gpio = dev->reset_gpio; - - if (gpio < 0) - return; - - /* - * Reset sequence: RESET low(50ms)->high(20ms) - */ - gpio_set_value(gpio, 0); - mdelay(50); - - gpio_set_value(gpio, 1); - mdelay(20); - - dev->current_page = 0xff; -} - -static int b53_configure_ports_of(struct b53_device *dev) -{ - struct device_node *dn, *pn; - u32 port_num; - - dn = of_get_child_by_name(dev_of_node(dev->dev), "ports"); - - for_each_available_child_of_node(dn, pn) { - struct device_node *fixed_link; - - if (of_property_read_u32(pn, "reg", &port_num)) - continue; - - if (port_num > B53_CPU_PORT) - continue; - - fixed_link = of_get_child_by_name(pn, "fixed-link"); - if (fixed_link) { - u32 spd; - u8 po = GMII_PO_LINK; - phy_interface_t mode; - - of_get_phy_mode(pn, &mode); - - if (!of_property_read_u32(fixed_link, "speed", &spd)) { - switch (spd) { - case 10: - po |= GMII_PO_SPEED_10M; - break; - case 100: - po |= GMII_PO_SPEED_100M; - break; - case 2000: - if (is_imp_port(dev, port_num)) - po |= PORT_OVERRIDE_SPEED_2000M; - else - po |= GMII_PO_SPEED_2000M; - fallthrough; - case 1000: - po |= GMII_PO_SPEED_1000M; - break; - } - } - - if (of_property_read_bool(fixed_link, "full-duplex")) - po |= PORT_OVERRIDE_FULL_DUPLEX; - if (of_property_read_bool(fixed_link, "pause")) - po |= GMII_PO_RX_FLOW; - if (of_property_read_bool(fixed_link, "asym-pause")) - po |= GMII_PO_TX_FLOW; - - if (is_imp_port(dev, port_num)) { - po |= PORT_OVERRIDE_EN; - - if (is5325(dev) && - mode == PHY_INTERFACE_MODE_REVMII) - po |= PORT_OVERRIDE_RV_MII_25; - - b53_write8(dev, B53_CTRL_PAGE, - B53_PORT_OVERRIDE_CTRL, po); - - if (is5325(dev) && - mode == PHY_INTERFACE_MODE_REVMII) { - b53_read8(dev, B53_CTRL_PAGE, - B53_PORT_OVERRIDE_CTRL, &po); - if (!(po & PORT_OVERRIDE_RV_MII_25)) - pr_err("Failed to enable reverse MII mode\n"); - return -EINVAL; - } - } else { - po |= GMII_PO_EN; - b53_write8(dev, B53_CTRL_PAGE, - B53_GMII_PORT_OVERRIDE_CTRL(port_num), - po); - } - } - } - - return 0; -} - -static int b53_configure_ports(struct b53_device *dev) -{ - u8 cpu_port = dev->sw_dev.cpu_port; - - /* configure MII port if necessary */ - if (is5325(dev)) { - u8 mii_port_override; - - b53_read8(dev, B53_CTRL_PAGE, B53_PORT_OVERRIDE_CTRL, - &mii_port_override); - /* reverse mii needs to be enabled */ - if (!(mii_port_override & PORT_OVERRIDE_RV_MII_25)) { - b53_write8(dev, B53_CTRL_PAGE, B53_PORT_OVERRIDE_CTRL, - mii_port_override | PORT_OVERRIDE_RV_MII_25); - b53_read8(dev, B53_CTRL_PAGE, B53_PORT_OVERRIDE_CTRL, - &mii_port_override); - - if (!(mii_port_override & PORT_OVERRIDE_RV_MII_25)) { - pr_err("Failed to enable reverse MII mode\n"); - return -EINVAL; - } - } - } else if (is531x5(dev) && cpu_port == B53_CPU_PORT) { - u8 mii_port_override; - - b53_read8(dev, B53_CTRL_PAGE, B53_PORT_OVERRIDE_CTRL, - &mii_port_override); - b53_write8(dev, B53_CTRL_PAGE, B53_PORT_OVERRIDE_CTRL, - mii_port_override | PORT_OVERRIDE_EN | - PORT_OVERRIDE_LINK); - - /* BCM47189 has another interface connected to the port 5 */ - if (dev->enabled_ports & BIT(5)) { - u8 po_reg = B53_GMII_PORT_OVERRIDE_CTRL(5); - u8 gmii_po; - - b53_read8(dev, B53_CTRL_PAGE, po_reg, &gmii_po); - gmii_po |= GMII_PO_LINK | - GMII_PO_RX_FLOW | - GMII_PO_TX_FLOW | - GMII_PO_EN; - b53_write8(dev, B53_CTRL_PAGE, po_reg, gmii_po); - } - } else if (is5301x(dev)) { - if (cpu_port == 8) { - u8 mii_port_override; - - b53_read8(dev, B53_CTRL_PAGE, B53_PORT_OVERRIDE_CTRL, - &mii_port_override); - mii_port_override |= PORT_OVERRIDE_LINK | - PORT_OVERRIDE_RX_FLOW | - PORT_OVERRIDE_TX_FLOW | - PORT_OVERRIDE_SPEED_2000M | - PORT_OVERRIDE_EN; - b53_write8(dev, B53_CTRL_PAGE, B53_PORT_OVERRIDE_CTRL, - mii_port_override); - - /* TODO: Ports 5 & 7 require some extra handling */ - } else { - u8 po_reg = B53_GMII_PORT_OVERRIDE_CTRL(cpu_port); - u8 gmii_po; - - b53_read8(dev, B53_CTRL_PAGE, po_reg, &gmii_po); - gmii_po |= GMII_PO_LINK | - GMII_PO_RX_FLOW | - GMII_PO_TX_FLOW | - GMII_PO_EN | - GMII_PO_SPEED_2000M; - b53_write8(dev, B53_CTRL_PAGE, po_reg, gmii_po); - } - } - - return 0; -} - -static int b53_switch_reset(struct b53_device *dev) -{ - int ret = 0; - u8 mgmt; - - b53_switch_reset_gpio(dev); - - if (is539x(dev)) { - b53_write8(dev, B53_CTRL_PAGE, B53_SOFTRESET, 0x83); - b53_write8(dev, B53_CTRL_PAGE, B53_SOFTRESET, 0x00); - } - - b53_read8(dev, B53_CTRL_PAGE, B53_SWITCH_MODE, &mgmt); - - if (!(mgmt & SM_SW_FWD_EN)) { - mgmt &= ~SM_SW_FWD_MODE; - mgmt |= SM_SW_FWD_EN; - - b53_write8(dev, B53_CTRL_PAGE, B53_SWITCH_MODE, mgmt); - b53_read8(dev, B53_CTRL_PAGE, B53_SWITCH_MODE, &mgmt); - - if (!(mgmt & SM_SW_FWD_EN)) { - pr_err("Failed to enable switch!\n"); - return -EINVAL; - } - } - - /* enable all ports */ - b53_enable_ports(dev); - - if (dev->dev->of_node) - ret = b53_configure_ports_of(dev); - else - ret = b53_configure_ports(dev); - - if (ret) - return ret; - - b53_enable_mib(dev); - - return b53_flush_arl(dev); -} - -/* - * Swconfig glue functions - */ - -static int b53_global_get_vlan_enable(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val) -{ - struct b53_device *priv = sw_to_b53(dev); - - val->value.i = priv->enable_vlan; - - return 0; -} - -static int b53_global_set_vlan_enable(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val) -{ - struct b53_device *priv = sw_to_b53(dev); - - priv->enable_vlan = val->value.i; - - return 0; -} - -static int b53_global_get_jumbo_enable(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val) -{ - struct b53_device *priv = sw_to_b53(dev); - - val->value.i = priv->enable_jumbo; - - return 0; -} - -static int b53_global_set_jumbo_enable(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val) -{ - struct b53_device *priv = sw_to_b53(dev); - - priv->enable_jumbo = val->value.i; - - return 0; -} - -static int b53_global_get_4095_enable(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val) -{ - struct b53_device *priv = sw_to_b53(dev); - - val->value.i = priv->allow_vid_4095; - - return 0; -} - -static int b53_global_set_4095_enable(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val) -{ - struct b53_device *priv = sw_to_b53(dev); - - priv->allow_vid_4095 = val->value.i; - - return 0; -} - -static int b53_global_get_ports(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val) -{ - struct b53_device *priv = sw_to_b53(dev); - - val->len = snprintf(priv->buf, B53_BUF_SIZE, "0x%04x", - priv->enabled_ports); - val->value.s = priv->buf; - - return 0; -} - -static int b53_port_get_pvid(struct switch_dev *dev, int port, int *val) -{ - struct b53_device *priv = sw_to_b53(dev); - - *val = priv->ports[port].pvid; - - return 0; -} - -static int b53_port_set_pvid(struct switch_dev *dev, int port, int val) -{ - struct b53_device *priv = sw_to_b53(dev); - - if (val > 15 && is5325(priv)) - return -EINVAL; - if (val == 4095 && !priv->allow_vid_4095) - return -EINVAL; - - priv->ports[port].pvid = val; - - return 0; -} - -static int b53_vlan_get_ports(struct switch_dev *dev, struct switch_val *val) -{ - struct b53_device *priv = sw_to_b53(dev); - struct switch_port *port = &val->value.ports[0]; - struct b53_vlan *vlan = &priv->vlans[val->port_vlan]; - int i; - - val->len = 0; - - if (!vlan->members) - return 0; - - for (i = 0; i < dev->ports; i++) { - if (!(vlan->members & BIT(i))) - continue; - - - if (!(vlan->untag & BIT(i))) - port->flags = BIT(SWITCH_PORT_FLAG_TAGGED); - else - port->flags = 0; - - port->id = i; - val->len++; - port++; - } - - return 0; -} - -static int b53_vlan_set_ports(struct switch_dev *dev, struct switch_val *val) -{ - struct b53_device *priv = sw_to_b53(dev); - struct switch_port *port; - struct b53_vlan *vlan = &priv->vlans[val->port_vlan]; - int i; - - /* only BCM5325 and BCM5365 supports VID 0 */ - if (val->port_vlan == 0 && !is5325(priv) && !is5365(priv)) - return -EINVAL; - - /* VLAN 4095 needs special handling */ - if (val->port_vlan == 4095 && !priv->allow_vid_4095) - return -EINVAL; - - port = &val->value.ports[0]; - vlan->members = 0; - vlan->untag = 0; - for (i = 0; i < val->len; i++, port++) { - vlan->members |= BIT(port->id); - - if (!(port->flags & BIT(SWITCH_PORT_FLAG_TAGGED))) { - vlan->untag |= BIT(port->id); - priv->ports[port->id].pvid = val->port_vlan; - }; - } - - /* ignore disabled ports */ - vlan->members &= priv->enabled_ports; - vlan->untag &= priv->enabled_ports; - - return 0; -} - -static int b53_port_get_link(struct switch_dev *dev, int port, - struct switch_port_link *link) -{ - struct b53_device *priv = sw_to_b53(dev); - - if (is_cpu_port(priv, port)) { - link->link = 1; - link->duplex = 1; - link->speed = is5325(priv) || is5365(priv) ? - SWITCH_PORT_SPEED_100 : SWITCH_PORT_SPEED_1000; - link->aneg = 0; - } else if (priv->enabled_ports & BIT(port)) { - u32 speed; - u16 lnk, duplex; - - b53_read16(priv, B53_STAT_PAGE, B53_LINK_STAT, &lnk); - b53_read16(priv, B53_STAT_PAGE, priv->duplex_reg, &duplex); - - lnk = (lnk >> port) & 1; - duplex = (duplex >> port) & 1; - - if (is5325(priv) || is5365(priv)) { - u16 tmp; - - b53_read16(priv, B53_STAT_PAGE, B53_SPEED_STAT, &tmp); - speed = SPEED_PORT_FE(tmp, port); - } else { - b53_read32(priv, B53_STAT_PAGE, B53_SPEED_STAT, &speed); - speed = SPEED_PORT_GE(speed, port); - } - - link->link = lnk; - if (lnk) { - link->duplex = duplex; - switch (speed) { - case SPEED_STAT_10M: - link->speed = SWITCH_PORT_SPEED_10; - break; - case SPEED_STAT_100M: - link->speed = SWITCH_PORT_SPEED_100; - break; - case SPEED_STAT_1000M: - link->speed = SWITCH_PORT_SPEED_1000; - break; - } - } - - link->aneg = 1; - } else { - link->link = 0; - } - - return 0; - -} - -static int b53_port_set_link(struct switch_dev *sw_dev, int port, - struct switch_port_link *link) -{ - struct b53_device *dev = sw_to_b53(sw_dev); - - /* - * TODO: BCM63XX requires special handling as it can have external phys - * and ports might be GE or only FE - */ - if (is63xx(dev)) - return -ENOTSUPP; - - if (port == sw_dev->cpu_port) - return -EINVAL; - - if (!(BIT(port) & dev->enabled_ports)) - return -EINVAL; - - if (link->speed == SWITCH_PORT_SPEED_1000 && - (is5325(dev) || is5365(dev))) - return -EINVAL; - - if (link->speed == SWITCH_PORT_SPEED_1000 && !link->duplex) - return -EINVAL; - - return switch_generic_set_link(sw_dev, port, link); -} - -static int b53_phy_read16(struct switch_dev *dev, int addr, u8 reg, u16 *value) -{ - struct b53_device *priv = sw_to_b53(dev); - - if (priv->ops->phy_read16) - return priv->ops->phy_read16(priv, addr, reg, value); - - return b53_read16(priv, B53_PORT_MII_PAGE(addr), reg, value); -} - -static int b53_phy_write16(struct switch_dev *dev, int addr, u8 reg, u16 value) -{ - struct b53_device *priv = sw_to_b53(dev); - - if (priv->ops->phy_write16) - return priv->ops->phy_write16(priv, addr, reg, value); - - return b53_write16(priv, B53_PORT_MII_PAGE(addr), reg, value); -} - -static int b53_global_reset_switch(struct switch_dev *dev) -{ - struct b53_device *priv = sw_to_b53(dev); - - /* reset vlans */ - priv->enable_vlan = 0; - priv->enable_jumbo = 0; - priv->allow_vid_4095 = 0; - - memset(priv->vlans, 0, sizeof(*priv->vlans) * dev->vlans); - memset(priv->ports, 0, sizeof(*priv->ports) * dev->ports); - - return b53_switch_reset(priv); -} - -static int b53_global_apply_config(struct switch_dev *dev) -{ - struct b53_device *priv = sw_to_b53(dev); - - /* disable switching */ - b53_set_forwarding(priv, 0); - - b53_apply(priv); - - /* enable switching */ - b53_set_forwarding(priv, 1); - - return 0; -} - - -static int b53_global_reset_mib(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val) -{ - struct b53_device *priv = sw_to_b53(dev); - u8 gc; - - b53_read8(priv, B53_MGMT_PAGE, B53_GLOBAL_CONFIG, &gc); - - b53_write8(priv, B53_MGMT_PAGE, B53_GLOBAL_CONFIG, gc | GC_RESET_MIB); - mdelay(1); - b53_write8(priv, B53_MGMT_PAGE, B53_GLOBAL_CONFIG, gc & ~GC_RESET_MIB); - mdelay(1); - - return 0; -} - -static int b53_port_get_mib(struct switch_dev *sw_dev, - const struct switch_attr *attr, - struct switch_val *val) -{ - struct b53_device *dev = sw_to_b53(sw_dev); - const struct b53_mib_desc *mibs; - int port = val->port_vlan; - int len = 0; - - if (!(BIT(port) & dev->enabled_ports)) - return -1; - - if (is5365(dev)) { - if (port == 5) - port = 8; - - mibs = b53_mibs_65; - } else if (is63xx(dev)) { - mibs = b53_mibs_63xx; - } else { - mibs = b53_mibs; - } - - dev->buf[0] = 0; - - for (; mibs->size > 0; mibs++) { - u64 val; - - if (mibs->size == 8) { - b53_read64(dev, B53_MIB_PAGE(port), mibs->offset, &val); - } else { - u32 val32; - - b53_read32(dev, B53_MIB_PAGE(port), mibs->offset, - &val32); - val = val32; - } - - len += snprintf(dev->buf + len, B53_BUF_SIZE - len, - "%-20s: %llu\n", mibs->name, val); - } - - val->len = len; - val->value.s = dev->buf; - - return 0; -} - -static int b53_port_get_stats(struct switch_dev *sw_dev, int port, - struct switch_port_stats *stats) -{ - struct b53_device *dev = sw_to_b53(sw_dev); - const struct b53_mib_desc *mibs; - int txb_id, rxb_id; - u64 rxb, txb; - - if (!(BIT(port) & dev->enabled_ports)) - return -EINVAL; - - txb_id = B53XX_MIB_TXB_ID; - rxb_id = B53XX_MIB_RXB_ID; - - if (is5365(dev)) { - if (port == 5) - port = 8; - - mibs = b53_mibs_65; - } else if (is63xx(dev)) { - mibs = b53_mibs_63xx; - txb_id = B63XX_MIB_TXB_ID; - rxb_id = B63XX_MIB_RXB_ID; - } else { - mibs = b53_mibs; - } - - dev->buf[0] = 0; - - if (mibs->size == 8) { - b53_read64(dev, B53_MIB_PAGE(port), mibs[txb_id].offset, &txb); - b53_read64(dev, B53_MIB_PAGE(port), mibs[rxb_id].offset, &rxb); - } else { - u32 val32; - - b53_read32(dev, B53_MIB_PAGE(port), mibs[txb_id].offset, &val32); - txb = val32; - - b53_read32(dev, B53_MIB_PAGE(port), mibs[rxb_id].offset, &val32); - rxb = val32; - } - - stats->tx_bytes = txb; - stats->rx_bytes = rxb; - - return 0; -} - -static struct switch_attr b53_global_ops_25[] = { - { - .type = SWITCH_TYPE_INT, - .name = "enable_vlan", - .description = "Enable VLAN mode", - .set = b53_global_set_vlan_enable, - .get = b53_global_get_vlan_enable, - .max = 1, - }, - { - .type = SWITCH_TYPE_STRING, - .name = "ports", - .description = "Available ports (as bitmask)", - .get = b53_global_get_ports, - }, -}; - -static struct switch_attr b53_global_ops_65[] = { - { - .type = SWITCH_TYPE_INT, - .name = "enable_vlan", - .description = "Enable VLAN mode", - .set = b53_global_set_vlan_enable, - .get = b53_global_get_vlan_enable, - .max = 1, - }, - { - .type = SWITCH_TYPE_STRING, - .name = "ports", - .description = "Available ports (as bitmask)", - .get = b53_global_get_ports, - }, - { - .type = SWITCH_TYPE_INT, - .name = "reset_mib", - .description = "Reset MIB counters", - .set = b53_global_reset_mib, - }, -}; - -static struct switch_attr b53_global_ops[] = { - { - .type = SWITCH_TYPE_INT, - .name = "enable_vlan", - .description = "Enable VLAN mode", - .set = b53_global_set_vlan_enable, - .get = b53_global_get_vlan_enable, - .max = 1, - }, - { - .type = SWITCH_TYPE_STRING, - .name = "ports", - .description = "Available Ports (as bitmask)", - .get = b53_global_get_ports, - }, - { - .type = SWITCH_TYPE_INT, - .name = "reset_mib", - .description = "Reset MIB counters", - .set = b53_global_reset_mib, - }, - { - .type = SWITCH_TYPE_INT, - .name = "enable_jumbo", - .description = "Enable Jumbo Frames", - .set = b53_global_set_jumbo_enable, - .get = b53_global_get_jumbo_enable, - .max = 1, - }, - { - .type = SWITCH_TYPE_INT, - .name = "allow_vid_4095", - .description = "Allow VID 4095", - .set = b53_global_set_4095_enable, - .get = b53_global_get_4095_enable, - .max = 1, - }, -}; - -static struct switch_attr b53_port_ops[] = { - { - .type = SWITCH_TYPE_STRING, - .name = "mib", - .description = "Get port's MIB counters", - .get = b53_port_get_mib, - }, -}; - -static struct switch_attr b53_no_ops[] = { -}; - -static const struct switch_dev_ops b53_switch_ops_25 = { - .attr_global = { - .attr = b53_global_ops_25, - .n_attr = ARRAY_SIZE(b53_global_ops_25), - }, - .attr_port = { - .attr = b53_no_ops, - .n_attr = ARRAY_SIZE(b53_no_ops), - }, - .attr_vlan = { - .attr = b53_no_ops, - .n_attr = ARRAY_SIZE(b53_no_ops), - }, - - .get_vlan_ports = b53_vlan_get_ports, - .set_vlan_ports = b53_vlan_set_ports, - .get_port_pvid = b53_port_get_pvid, - .set_port_pvid = b53_port_set_pvid, - .apply_config = b53_global_apply_config, - .reset_switch = b53_global_reset_switch, - .get_port_link = b53_port_get_link, - .set_port_link = b53_port_set_link, - .get_port_stats = b53_port_get_stats, - .phy_read16 = b53_phy_read16, - .phy_write16 = b53_phy_write16, -}; - -static const struct switch_dev_ops b53_switch_ops_65 = { - .attr_global = { - .attr = b53_global_ops_65, - .n_attr = ARRAY_SIZE(b53_global_ops_65), - }, - .attr_port = { - .attr = b53_port_ops, - .n_attr = ARRAY_SIZE(b53_port_ops), - }, - .attr_vlan = { - .attr = b53_no_ops, - .n_attr = ARRAY_SIZE(b53_no_ops), - }, - - .get_vlan_ports = b53_vlan_get_ports, - .set_vlan_ports = b53_vlan_set_ports, - .get_port_pvid = b53_port_get_pvid, - .set_port_pvid = b53_port_set_pvid, - .apply_config = b53_global_apply_config, - .reset_switch = b53_global_reset_switch, - .get_port_link = b53_port_get_link, - .set_port_link = b53_port_set_link, - .get_port_stats = b53_port_get_stats, - .phy_read16 = b53_phy_read16, - .phy_write16 = b53_phy_write16, -}; - -static const struct switch_dev_ops b53_switch_ops = { - .attr_global = { - .attr = b53_global_ops, - .n_attr = ARRAY_SIZE(b53_global_ops), - }, - .attr_port = { - .attr = b53_port_ops, - .n_attr = ARRAY_SIZE(b53_port_ops), - }, - .attr_vlan = { - .attr = b53_no_ops, - .n_attr = ARRAY_SIZE(b53_no_ops), - }, - - .get_vlan_ports = b53_vlan_get_ports, - .set_vlan_ports = b53_vlan_set_ports, - .get_port_pvid = b53_port_get_pvid, - .set_port_pvid = b53_port_set_pvid, - .apply_config = b53_global_apply_config, - .reset_switch = b53_global_reset_switch, - .get_port_link = b53_port_get_link, - .set_port_link = b53_port_set_link, - .get_port_stats = b53_port_get_stats, - .phy_read16 = b53_phy_read16, - .phy_write16 = b53_phy_write16, -}; - -struct b53_chip_data { - u32 chip_id; - const char *dev_name; - const char *alias; - u16 vlans; - u16 enabled_ports; - u8 cpu_port; - u8 vta_regs[3]; - u8 duplex_reg; - u8 jumbo_pm_reg; - u8 jumbo_size_reg; - const struct switch_dev_ops *sw_ops; -}; - -#define B53_VTA_REGS \ - { B53_VT_ACCESS, B53_VT_INDEX, B53_VT_ENTRY } -#define B53_VTA_REGS_9798 \ - { B53_VT_ACCESS_9798, B53_VT_INDEX_9798, B53_VT_ENTRY_9798 } -#define B53_VTA_REGS_63XX \ - { B53_VT_ACCESS_63XX, B53_VT_INDEX_63XX, B53_VT_ENTRY_63XX } - -static const struct b53_chip_data b53_switch_chips[] = { - { - .chip_id = BCM5325_DEVICE_ID, - .dev_name = "BCM5325", - .alias = "bcm5325", - .vlans = 16, - .enabled_ports = 0x1f, - .cpu_port = B53_CPU_PORT_25, - .duplex_reg = B53_DUPLEX_STAT_FE, - .sw_ops = &b53_switch_ops_25, - }, - { - .chip_id = BCM5365_DEVICE_ID, - .dev_name = "BCM5365", - .alias = "bcm5365", - .vlans = 256, - .enabled_ports = 0x1f, - .cpu_port = B53_CPU_PORT_25, - .duplex_reg = B53_DUPLEX_STAT_FE, - .sw_ops = &b53_switch_ops_65, - }, - { - .chip_id = BCM5395_DEVICE_ID, - .dev_name = "BCM5395", - .alias = "bcm5395", - .vlans = 4096, - .enabled_ports = 0x1f, - .cpu_port = B53_CPU_PORT, - .vta_regs = B53_VTA_REGS, - .duplex_reg = B53_DUPLEX_STAT_GE, - .jumbo_pm_reg = B53_JUMBO_PORT_MASK, - .jumbo_size_reg = B53_JUMBO_MAX_SIZE, - .sw_ops = &b53_switch_ops, - }, - { - .chip_id = BCM5397_DEVICE_ID, - .dev_name = "BCM5397", - .alias = "bcm5397", - .vlans = 4096, - .enabled_ports = 0x1f, - .cpu_port = B53_CPU_PORT, - .vta_regs = B53_VTA_REGS_9798, - .duplex_reg = B53_DUPLEX_STAT_GE, - .jumbo_pm_reg = B53_JUMBO_PORT_MASK, - .jumbo_size_reg = B53_JUMBO_MAX_SIZE, - .sw_ops = &b53_switch_ops, - }, - { - .chip_id = BCM5398_DEVICE_ID, - .dev_name = "BCM5398", - .alias = "bcm5398", - .vlans = 4096, - .enabled_ports = 0x7f, - .cpu_port = B53_CPU_PORT, - .vta_regs = B53_VTA_REGS_9798, - .duplex_reg = B53_DUPLEX_STAT_GE, - .jumbo_pm_reg = B53_JUMBO_PORT_MASK, - .jumbo_size_reg = B53_JUMBO_MAX_SIZE, - .sw_ops = &b53_switch_ops, - }, - { - .chip_id = BCM53115_DEVICE_ID, - .dev_name = "BCM53115", - .alias = "bcm53115", - .vlans = 4096, - .enabled_ports = 0x1f, - .vta_regs = B53_VTA_REGS, - .cpu_port = B53_CPU_PORT, - .duplex_reg = B53_DUPLEX_STAT_GE, - .jumbo_pm_reg = B53_JUMBO_PORT_MASK, - .jumbo_size_reg = B53_JUMBO_MAX_SIZE, - .sw_ops = &b53_switch_ops, - }, - { - .chip_id = BCM53125_DEVICE_ID, - .dev_name = "BCM53125", - .alias = "bcm53125", - .vlans = 4096, - .enabled_ports = 0x1f, - .cpu_port = B53_CPU_PORT, - .vta_regs = B53_VTA_REGS, - .duplex_reg = B53_DUPLEX_STAT_GE, - .jumbo_pm_reg = B53_JUMBO_PORT_MASK, - .jumbo_size_reg = B53_JUMBO_MAX_SIZE, - .sw_ops = &b53_switch_ops, - }, - { - .chip_id = BCM53128_DEVICE_ID, - .dev_name = "BCM53128", - .alias = "bcm53128", - .vlans = 4096, - .enabled_ports = 0x1ff, - .cpu_port = B53_CPU_PORT, - .vta_regs = B53_VTA_REGS, - .duplex_reg = B53_DUPLEX_STAT_GE, - .jumbo_pm_reg = B53_JUMBO_PORT_MASK, - .jumbo_size_reg = B53_JUMBO_MAX_SIZE, - .sw_ops = &b53_switch_ops, - }, - { - .chip_id = BCM63XX_DEVICE_ID, - .dev_name = "BCM63xx", - .alias = "bcm63xx", - .vlans = 4096, - .enabled_ports = 0, /* pdata must provide them */ - .cpu_port = B53_CPU_PORT, - .vta_regs = B53_VTA_REGS_63XX, - .duplex_reg = B53_DUPLEX_STAT_63XX, - .jumbo_pm_reg = B53_JUMBO_PORT_MASK_63XX, - .jumbo_size_reg = B53_JUMBO_MAX_SIZE_63XX, - .sw_ops = &b53_switch_ops, - }, - { - .chip_id = BCM53010_DEVICE_ID, - .dev_name = "BCM53010", - .alias = "bcm53011", - .vlans = 4096, - .enabled_ports = 0x1f, - .cpu_port = B53_CPU_PORT_25, /* TODO: auto detect */ - .vta_regs = B53_VTA_REGS, - .duplex_reg = B53_DUPLEX_STAT_GE, - .jumbo_pm_reg = B53_JUMBO_PORT_MASK, - .jumbo_size_reg = B53_JUMBO_MAX_SIZE, - .sw_ops = &b53_switch_ops, - }, - { - .chip_id = BCM53011_DEVICE_ID, - .dev_name = "BCM53011", - .alias = "bcm53011", - .vlans = 4096, - .enabled_ports = 0x1bf, - .cpu_port = B53_CPU_PORT_25, /* TODO: auto detect */ - .vta_regs = B53_VTA_REGS, - .duplex_reg = B53_DUPLEX_STAT_GE, - .jumbo_pm_reg = B53_JUMBO_PORT_MASK, - .jumbo_size_reg = B53_JUMBO_MAX_SIZE, - .sw_ops = &b53_switch_ops, - }, - { - .chip_id = BCM53012_DEVICE_ID, - .dev_name = "BCM53012", - .alias = "bcm53011", - .vlans = 4096, - .enabled_ports = 0x1bf, - .cpu_port = B53_CPU_PORT_25, /* TODO: auto detect */ - .vta_regs = B53_VTA_REGS, - .duplex_reg = B53_DUPLEX_STAT_GE, - .jumbo_pm_reg = B53_JUMBO_PORT_MASK, - .jumbo_size_reg = B53_JUMBO_MAX_SIZE, - .sw_ops = &b53_switch_ops, - }, - { - .chip_id = BCM53018_DEVICE_ID, - .dev_name = "BCM53018", - .alias = "bcm53018", - .vlans = 4096, - .enabled_ports = 0x1f, - .cpu_port = B53_CPU_PORT_25, /* TODO: auto detect */ - .vta_regs = B53_VTA_REGS, - .duplex_reg = B53_DUPLEX_STAT_GE, - .jumbo_pm_reg = B53_JUMBO_PORT_MASK, - .jumbo_size_reg = B53_JUMBO_MAX_SIZE, - .sw_ops = &b53_switch_ops, - }, - { - .chip_id = BCM53019_DEVICE_ID, - .dev_name = "BCM53019", - .alias = "bcm53019", - .vlans = 4096, - .enabled_ports = 0x1f, - .cpu_port = B53_CPU_PORT_25, /* TODO: auto detect */ - .vta_regs = B53_VTA_REGS, - .duplex_reg = B53_DUPLEX_STAT_GE, - .jumbo_pm_reg = B53_JUMBO_PORT_MASK, - .jumbo_size_reg = B53_JUMBO_MAX_SIZE, - .sw_ops = &b53_switch_ops, - }, -}; - -static int b53_switch_init_of(struct b53_device *dev) -{ - struct device_node *dn, *pn; - const char *alias; - u32 port_num; - u16 ports = 0; - - dn = of_get_child_by_name(dev_of_node(dev->dev), "ports"); - if (!dn) - return -EINVAL; - - for_each_available_child_of_node(dn, pn) { - const char *label; - int len; - - if (of_property_read_u32(pn, "reg", &port_num)) - continue; - - if (port_num > B53_CPU_PORT) - continue; - - ports |= BIT(port_num); - - label = of_get_property(pn, "label", &len); - if (label && !strcmp(label, "cpu")) - dev->sw_dev.cpu_port = port_num; - } - - dev->enabled_ports = ports; - - if (!of_property_read_string(dev_of_node(dev->dev), "lede,alias", - &alias)) - dev->sw_dev.alias = devm_kstrdup(dev->dev, alias, GFP_KERNEL); - - return 0; -} - -static int b53_switch_init(struct b53_device *dev) -{ - struct switch_dev *sw_dev = &dev->sw_dev; - unsigned i; - int ret; - - for (i = 0; i < ARRAY_SIZE(b53_switch_chips); i++) { - const struct b53_chip_data *chip = &b53_switch_chips[i]; - - if (chip->chip_id == dev->chip_id) { - sw_dev->name = chip->dev_name; - if (!sw_dev->alias) - sw_dev->alias = chip->alias; - if (!dev->enabled_ports) - dev->enabled_ports = chip->enabled_ports; - dev->duplex_reg = chip->duplex_reg; - dev->vta_regs[0] = chip->vta_regs[0]; - dev->vta_regs[1] = chip->vta_regs[1]; - dev->vta_regs[2] = chip->vta_regs[2]; - dev->jumbo_pm_reg = chip->jumbo_pm_reg; - sw_dev->ops = chip->sw_ops; - sw_dev->cpu_port = chip->cpu_port; - sw_dev->vlans = chip->vlans; - break; - } - } - - if (!sw_dev->name) - return -EINVAL; - - /* check which BCM5325x version we have */ - if (is5325(dev)) { - u8 vc4; - - b53_read8(dev, B53_VLAN_PAGE, B53_VLAN_CTRL4_25, &vc4); - - /* check reserved bits */ - switch (vc4 & 3) { - case 1: - /* BCM5325E */ - break; - case 3: - /* BCM5325F - do not use port 4 */ - dev->enabled_ports &= ~BIT(4); - break; - default: -/* On the BCM47XX SoCs this is the supported internal switch.*/ -#ifndef CONFIG_BCM47XX - /* BCM5325M */ - return -EINVAL; -#else - break; -#endif - } - } else if (dev->chip_id == BCM53115_DEVICE_ID) { - u64 strap_value; - - b53_read48(dev, B53_STAT_PAGE, B53_STRAP_VALUE, &strap_value); - /* use second IMP port if GMII is enabled */ - if (strap_value & SV_GMII_CTRL_115) - sw_dev->cpu_port = 5; - } - - if (dev_of_node(dev->dev)) { - ret = b53_switch_init_of(dev); - if (ret) - return ret; - } - - dev->enabled_ports |= BIT(sw_dev->cpu_port); - sw_dev->ports = fls(dev->enabled_ports); - - dev->ports = devm_kzalloc(dev->dev, - sizeof(struct b53_port) * sw_dev->ports, - GFP_KERNEL); - if (!dev->ports) - return -ENOMEM; - - dev->vlans = devm_kzalloc(dev->dev, - sizeof(struct b53_vlan) * sw_dev->vlans, - GFP_KERNEL); - if (!dev->vlans) - return -ENOMEM; - - dev->buf = devm_kzalloc(dev->dev, B53_BUF_SIZE, GFP_KERNEL); - if (!dev->buf) - return -ENOMEM; - - dev->reset_gpio = b53_switch_get_reset_gpio(dev); - if (dev->reset_gpio >= 0) { - ret = devm_gpio_request_one(dev->dev, dev->reset_gpio, - GPIOF_OUT_INIT_HIGH, "robo_reset"); - if (ret) - return ret; - } - - return b53_switch_reset(dev); -} - -struct b53_device *b53_swconfig_switch_alloc(struct device *base, struct b53_io_ops *ops, - void *priv) -{ - struct b53_device *dev; - - dev = devm_kzalloc(base, sizeof(*dev), GFP_KERNEL); - if (!dev) - return NULL; - - dev->dev = base; - dev->ops = ops; - dev->priv = priv; - mutex_init(&dev->reg_mutex); - - return dev; -} -EXPORT_SYMBOL(b53_swconfig_switch_alloc); - -int b53_swconfig_switch_detect(struct b53_device *dev) -{ - u32 id32; - u16 tmp; - u8 id8; - int ret; - - ret = b53_read8(dev, B53_MGMT_PAGE, B53_DEVICE_ID, &id8); - if (ret) - return ret; - - switch (id8) { - case 0: - /* - * BCM5325 and BCM5365 do not have this register so reads - * return 0. But the read operation did succeed, so assume - * this is one of them. - * - * Next check if we can write to the 5325's VTA register; for - * 5365 it is read only. - */ - - b53_write16(dev, B53_VLAN_PAGE, B53_VLAN_TABLE_ACCESS_25, 0xf); - b53_read16(dev, B53_VLAN_PAGE, B53_VLAN_TABLE_ACCESS_25, &tmp); - - if (tmp == 0xf) - dev->chip_id = BCM5325_DEVICE_ID; - else - dev->chip_id = BCM5365_DEVICE_ID; - break; - case BCM5395_DEVICE_ID: - case BCM5397_DEVICE_ID: - case BCM5398_DEVICE_ID: - dev->chip_id = id8; - break; - default: - ret = b53_read32(dev, B53_MGMT_PAGE, B53_DEVICE_ID, &id32); - if (ret) - return ret; - - switch (id32) { - case BCM53115_DEVICE_ID: - case BCM53125_DEVICE_ID: - case BCM53128_DEVICE_ID: - case BCM53010_DEVICE_ID: - case BCM53011_DEVICE_ID: - case BCM53012_DEVICE_ID: - case BCM53018_DEVICE_ID: - case BCM53019_DEVICE_ID: - dev->chip_id = id32; - break; - default: - pr_err("unsupported switch detected (BCM53%02x/BCM%x)\n", - id8, id32); - return -ENODEV; - } - } - - if (dev->chip_id == BCM5325_DEVICE_ID) - return b53_read8(dev, B53_STAT_PAGE, B53_REV_ID_25, - &dev->core_rev); - else - return b53_read8(dev, B53_MGMT_PAGE, B53_REV_ID, - &dev->core_rev); -} -EXPORT_SYMBOL(b53_swconfig_switch_detect); - -int b53_swconfig_switch_register(struct b53_device *dev) -{ - int ret; - - if (dev->pdata) { - dev->chip_id = dev->pdata->chip_id; - dev->enabled_ports = dev->pdata->enabled_ports; - dev->sw_dev.alias = dev->pdata->alias; - } - - if (!dev->chip_id && b53_swconfig_switch_detect(dev)) - return -EINVAL; - - ret = b53_switch_init(dev); - if (ret) - return ret; - - pr_info("found switch: %s, rev %i\n", dev->sw_dev.name, dev->core_rev); - - return register_switch(&dev->sw_dev, NULL); -} -EXPORT_SYMBOL(b53_swconfig_switch_register); - -MODULE_AUTHOR("Jonas Gorski "); -MODULE_DESCRIPTION("B53 switch library"); -MODULE_LICENSE("Dual BSD/GPL"); diff --git a/target/linux/generic/files-6.12/drivers/net/phy/b53/b53_mdio.c b/target/linux/generic/files-6.12/drivers/net/phy/b53/b53_mdio.c deleted file mode 100644 index c85df1f3055801..00000000000000 --- a/target/linux/generic/files-6.12/drivers/net/phy/b53/b53_mdio.c +++ /dev/null @@ -1,436 +0,0 @@ -/* - * B53 register access through MII registers - * - * Copyright (C) 2011-2013 Jonas Gorski - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include -#include -#include - -#include "b53_priv.h" - -#define B53_PSEUDO_PHY 0x1e /* Register Access Pseudo PHY */ - -/* MII registers */ -#define REG_MII_PAGE 0x10 /* MII Page register */ -#define REG_MII_ADDR 0x11 /* MII Address register */ -#define REG_MII_DATA0 0x18 /* MII Data register 0 */ -#define REG_MII_DATA1 0x19 /* MII Data register 1 */ -#define REG_MII_DATA2 0x1a /* MII Data register 2 */ -#define REG_MII_DATA3 0x1b /* MII Data register 3 */ - -#define REG_MII_PAGE_ENABLE BIT(0) -#define REG_MII_ADDR_WRITE BIT(0) -#define REG_MII_ADDR_READ BIT(1) - -static int b53_mdio_op(struct b53_device *dev, u8 page, u8 reg, u16 op) -{ - int i; - u16 v; - int ret; - struct mii_bus *bus = dev->priv; - - if (dev->current_page != page) { - /* set page number */ - v = (page << 8) | REG_MII_PAGE_ENABLE; - ret = mdiobus_write(bus, B53_PSEUDO_PHY, REG_MII_PAGE, v); - if (ret) - return ret; - dev->current_page = page; - } - - /* set register address */ - v = (reg << 8) | op; - ret = mdiobus_write(bus, B53_PSEUDO_PHY, REG_MII_ADDR, v); - if (ret) - return ret; - - /* check if operation completed */ - for (i = 0; i < 5; ++i) { - v = mdiobus_read(bus, B53_PSEUDO_PHY, REG_MII_ADDR); - if (!(v & (REG_MII_ADDR_WRITE | REG_MII_ADDR_READ))) - break; - usleep_range(10, 100); - } - - if (WARN_ON(i == 5)) - return -EIO; - - return 0; -} - -static int b53_mdio_read8(struct b53_device *dev, u8 page, u8 reg, u8 *val) -{ - struct mii_bus *bus = dev->priv; - int ret; - - ret = b53_mdio_op(dev, page, reg, REG_MII_ADDR_READ); - if (ret) - return ret; - - *val = mdiobus_read(bus, B53_PSEUDO_PHY, REG_MII_DATA0) & 0xff; - - return 0; -} - -static int b53_mdio_read16(struct b53_device *dev, u8 page, u8 reg, u16 *val) -{ - struct mii_bus *bus = dev->priv; - int ret; - - ret = b53_mdio_op(dev, page, reg, REG_MII_ADDR_READ); - if (ret) - return ret; - - *val = mdiobus_read(bus, B53_PSEUDO_PHY, REG_MII_DATA0); - - return 0; -} - -static int b53_mdio_read32(struct b53_device *dev, u8 page, u8 reg, u32 *val) -{ - struct mii_bus *bus = dev->priv; - int ret; - - ret = b53_mdio_op(dev, page, reg, REG_MII_ADDR_READ); - if (ret) - return ret; - - *val = mdiobus_read(bus, B53_PSEUDO_PHY, REG_MII_DATA0); - *val |= mdiobus_read(bus, B53_PSEUDO_PHY, REG_MII_DATA1) << 16; - - return 0; -} - -static int b53_mdio_read48(struct b53_device *dev, u8 page, u8 reg, u64 *val) -{ - struct mii_bus *bus = dev->priv; - u64 temp = 0; - int i; - int ret; - - ret = b53_mdio_op(dev, page, reg, REG_MII_ADDR_READ); - if (ret) - return ret; - - for (i = 2; i >= 0; i--) { - temp <<= 16; - temp |= mdiobus_read(bus, B53_PSEUDO_PHY, REG_MII_DATA0 + i); - } - - *val = temp; - - return 0; -} - -static int b53_mdio_read64(struct b53_device *dev, u8 page, u8 reg, u64 *val) -{ - struct mii_bus *bus = dev->priv; - u64 temp = 0; - int i; - int ret; - - ret = b53_mdio_op(dev, page, reg, REG_MII_ADDR_READ); - if (ret) - return ret; - - for (i = 3; i >= 0; i--) { - temp <<= 16; - temp |= mdiobus_read(bus, B53_PSEUDO_PHY, REG_MII_DATA0 + i); - } - - *val = temp; - - return 0; -} - -static int b53_mdio_write8(struct b53_device *dev, u8 page, u8 reg, u8 value) -{ - struct mii_bus *bus = dev->priv; - int ret; - - ret = mdiobus_write(bus, B53_PSEUDO_PHY, REG_MII_DATA0, value); - if (ret) - return ret; - - return b53_mdio_op(dev, page, reg, REG_MII_ADDR_WRITE); -} - -static int b53_mdio_write16(struct b53_device *dev, u8 page, u8 reg, - u16 value) -{ - struct mii_bus *bus = dev->priv; - int ret; - - ret = mdiobus_write(bus, B53_PSEUDO_PHY, REG_MII_DATA0, value); - if (ret) - return ret; - - return b53_mdio_op(dev, page, reg, REG_MII_ADDR_WRITE); -} - -static int b53_mdio_write32(struct b53_device *dev, u8 page, u8 reg, - u32 value) -{ - struct mii_bus *bus = dev->priv; - unsigned int i; - u32 temp = value; - - for (i = 0; i < 2; i++) { - int ret = mdiobus_write(bus, B53_PSEUDO_PHY, REG_MII_DATA0 + i, - temp & 0xffff); - if (ret) - return ret; - temp >>= 16; - } - - return b53_mdio_op(dev, page, reg, REG_MII_ADDR_WRITE); - -} - -static int b53_mdio_write48(struct b53_device *dev, u8 page, u8 reg, - u64 value) -{ - struct mii_bus *bus = dev->priv; - unsigned i; - u64 temp = value; - - for (i = 0; i < 3; i++) { - int ret = mdiobus_write(bus, B53_PSEUDO_PHY, REG_MII_DATA0 + i, - temp & 0xffff); - if (ret) - return ret; - temp >>= 16; - } - - return b53_mdio_op(dev, page, reg, REG_MII_ADDR_WRITE); - -} - -static int b53_mdio_write64(struct b53_device *dev, u8 page, u8 reg, - u64 value) -{ - struct mii_bus *bus = dev->priv; - unsigned i; - u64 temp = value; - - for (i = 0; i < 4; i++) { - int ret = mdiobus_write(bus, B53_PSEUDO_PHY, REG_MII_DATA0 + i, - temp & 0xffff); - if (ret) - return ret; - temp >>= 16; - } - - return b53_mdio_op(dev, page, reg, REG_MII_ADDR_WRITE); -} - -static int b53_mdio_phy_read16(struct b53_device *dev, int addr, u8 reg, - u16 *value) -{ - struct mii_bus *bus = dev->priv; - - *value = mdiobus_read(bus, addr, reg); - - return 0; -} - -static int b53_mdio_phy_write16(struct b53_device *dev, int addr, u8 reg, - u16 value) -{ - struct mii_bus *bus = dev->priv; - - return mdiobus_write(bus, addr, reg, value); -} - -static struct b53_io_ops b53_mdio_ops = { - .read8 = b53_mdio_read8, - .read16 = b53_mdio_read16, - .read32 = b53_mdio_read32, - .read48 = b53_mdio_read48, - .read64 = b53_mdio_read64, - .write8 = b53_mdio_write8, - .write16 = b53_mdio_write16, - .write32 = b53_mdio_write32, - .write48 = b53_mdio_write48, - .write64 = b53_mdio_write64, - .phy_read16 = b53_mdio_phy_read16, - .phy_write16 = b53_mdio_phy_write16, -}; - -static int b53_phy_probe(struct phy_device *phydev) -{ - struct b53_device *dev; - int ret; - - /* allow the generic phy driver to take over */ - if (phydev->mdio.addr != B53_PSEUDO_PHY && phydev->mdio.addr != 0) - return -ENODEV; - - dev = b53_swconfig_switch_alloc(&phydev->mdio.dev, &b53_mdio_ops, phydev->mdio.bus); - if (!dev) - return -ENOMEM; - - dev->current_page = 0xff; - dev->priv = phydev->mdio.bus; - dev->ops = &b53_mdio_ops; - dev->pdata = NULL; - mutex_init(&dev->reg_mutex); - - ret = b53_swconfig_switch_detect(dev); - if (ret) - return ret; - - linkmode_zero(phydev->supported); - if (is5325(dev) || is5365(dev)) - linkmode_set_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT, phydev->supported); - else - linkmode_set_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT, phydev->supported); - - linkmode_copy(phydev->advertising, phydev->supported); - - ret = b53_swconfig_switch_register(dev); - if (ret) { - dev_err(dev->dev, "failed to register switch: %i\n", ret); - return ret; - } - - phydev->priv = dev; - - return 0; -} - -static int b53_phy_config_init(struct phy_device *phydev) -{ - struct b53_device *dev = phydev->priv; - - /* we don't use page 0xff, so force a page set */ - dev->current_page = 0xff; - /* force the ethX as alias */ - dev->sw_dev.alias = phydev->attached_dev->name; - - return 0; -} - -static void b53_phy_remove(struct phy_device *phydev) -{ - struct b53_device *priv = phydev->priv; - - if (!priv) - return; - - b53_switch_remove(priv); - - phydev->priv = NULL; -} - -static int b53_phy_config_aneg(struct phy_device *phydev) -{ - return 0; -} - -static int b53_phy_read_status(struct phy_device *phydev) -{ - struct b53_device *priv = phydev->priv; - - if (is5325(priv) || is5365(priv)) - phydev->speed = 100; - else - phydev->speed = 1000; - - phydev->duplex = DUPLEX_FULL; - phydev->link = 1; - phydev->state = PHY_RUNNING; - - netif_carrier_on(phydev->attached_dev); - phydev->adjust_link(phydev->attached_dev); - - return 0; -} - -/* BCM5325, BCM539x */ -static struct phy_driver b53_phy_driver_id1 = { - .phy_id = 0x0143bc00, - .name = "Broadcom B53 (1)", - .phy_id_mask = 0x1ffffc00, - .features = 0, - .probe = b53_phy_probe, - .remove = b53_phy_remove, - .config_aneg = b53_phy_config_aneg, - .config_init = b53_phy_config_init, - .read_status = b53_phy_read_status, -}; - -/* BCM53125, BCM53128 */ -static struct phy_driver b53_phy_driver_id2 = { - .phy_id = 0x03625c00, - .name = "Broadcom B53 (2)", - .phy_id_mask = 0x1ffffc00, - .features = 0, - .probe = b53_phy_probe, - .remove = b53_phy_remove, - .config_aneg = b53_phy_config_aneg, - .config_init = b53_phy_config_init, - .read_status = b53_phy_read_status, -}; - -/* BCM5365 */ -static struct phy_driver b53_phy_driver_id3 = { - .phy_id = 0x00406300, - .name = "Broadcom B53 (3)", - .phy_id_mask = 0x1fffff00, - .features = 0, - .probe = b53_phy_probe, - .remove = b53_phy_remove, - .config_aneg = b53_phy_config_aneg, - .config_init = b53_phy_config_init, - .read_status = b53_phy_read_status, -}; - -int __init b53_phy_driver_register(void) -{ - int ret; - - ret = phy_driver_register(&b53_phy_driver_id1, THIS_MODULE); - if (ret) - return ret; - - ret = phy_driver_register(&b53_phy_driver_id2, THIS_MODULE); - if (ret) - goto err1; - - ret = phy_driver_register(&b53_phy_driver_id3, THIS_MODULE); - if (!ret) - return 0; - - phy_driver_unregister(&b53_phy_driver_id2); -err1: - phy_driver_unregister(&b53_phy_driver_id1); - return ret; -} - -void __exit b53_phy_driver_unregister(void) -{ - phy_driver_unregister(&b53_phy_driver_id3); - phy_driver_unregister(&b53_phy_driver_id2); - phy_driver_unregister(&b53_phy_driver_id1); -} - -module_init(b53_phy_driver_register); -module_exit(b53_phy_driver_unregister); - -MODULE_DESCRIPTION("B53 MDIO access driver"); -MODULE_LICENSE("Dual BSD/GPL"); diff --git a/target/linux/generic/files-6.12/drivers/net/phy/b53/b53_mmap.c b/target/linux/generic/files-6.12/drivers/net/phy/b53/b53_mmap.c deleted file mode 100644 index 0a21ff1de55ed4..00000000000000 --- a/target/linux/generic/files-6.12/drivers/net/phy/b53/b53_mmap.c +++ /dev/null @@ -1,241 +0,0 @@ -/* - * B53 register access through memory mapped registers - * - * Copyright (C) 2012-2013 Jonas Gorski - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include -#include -#include -#include - -#include "b53_priv.h" - -static int b53_mmap_read8(struct b53_device *dev, u8 page, u8 reg, u8 *val) -{ - u8 __iomem *regs = dev->priv; - - *val = readb(regs + (page << 8) + reg); - - return 0; -} - -static int b53_mmap_read16(struct b53_device *dev, u8 page, u8 reg, u16 *val) -{ - u8 __iomem *regs = dev->priv; - - if (WARN_ON(reg % 2)) - return -EINVAL; - - if (dev->pdata && dev->pdata->big_endian) - *val = readw_be(regs + (page << 8) + reg); - else - *val = readw(regs + (page << 8) + reg); - - return 0; -} - -static int b53_mmap_read32(struct b53_device *dev, u8 page, u8 reg, u32 *val) -{ - u8 __iomem *regs = dev->priv; - - if (WARN_ON(reg % 4)) - return -EINVAL; - - if (dev->pdata && dev->pdata->big_endian) - *val = readl_be(regs + (page << 8) + reg); - else - *val = readl(regs + (page << 8) + reg); - - return 0; -} - -static int b53_mmap_read48(struct b53_device *dev, u8 page, u8 reg, u64 *val) -{ - if (WARN_ON(reg % 2)) - return -EINVAL; - - if (reg % 4) { - u16 lo; - u32 hi; - - b53_mmap_read16(dev, page, reg, &lo); - b53_mmap_read32(dev, page, reg + 2, &hi); - - *val = ((u64)hi << 16) | lo; - } else { - u32 lo; - u16 hi; - - b53_mmap_read32(dev, page, reg, &lo); - b53_mmap_read16(dev, page, reg + 4, &hi); - - *val = ((u64)hi << 32) | lo; - } - - return 0; -} - -static int b53_mmap_read64(struct b53_device *dev, u8 page, u8 reg, u64 *val) -{ - u32 hi, lo; - - if (WARN_ON(reg % 4)) - return -EINVAL; - - b53_mmap_read32(dev, page, reg, &lo); - b53_mmap_read32(dev, page, reg + 4, &hi); - - *val = ((u64)hi << 32) | lo; - - return 0; -} - -static int b53_mmap_write8(struct b53_device *dev, u8 page, u8 reg, u8 value) -{ - u8 __iomem *regs = dev->priv; - - writeb(value, regs + (page << 8) + reg); - - return 0; -} - -static int b53_mmap_write16(struct b53_device *dev, u8 page, u8 reg, - u16 value) -{ - u8 __iomem *regs = dev->priv; - - if (WARN_ON(reg % 2)) - return -EINVAL; - - if (dev->pdata && dev->pdata->big_endian) - writew_be(value, regs + (page << 8) + reg); - else - writew(value, regs + (page << 8) + reg); - - return 0; -} - -static int b53_mmap_write32(struct b53_device *dev, u8 page, u8 reg, - u32 value) -{ - u8 __iomem *regs = dev->priv; - - if (WARN_ON(reg % 4)) - return -EINVAL; - - if (dev->pdata && dev->pdata->big_endian) - writel_be(value, regs + (page << 8) + reg); - else - writel(value, regs + (page << 8) + reg); - - return 0; -} - -static int b53_mmap_write48(struct b53_device *dev, u8 page, u8 reg, - u64 value) -{ - if (WARN_ON(reg % 2)) - return -EINVAL; - - if (reg % 4) { - u32 hi = (u32)(value >> 16); - u16 lo = (u16)value; - - b53_mmap_write16(dev, page, reg, lo); - b53_mmap_write32(dev, page, reg + 2, hi); - } else { - u16 hi = (u16)(value >> 32); - u32 lo = (u32)value; - - b53_mmap_write32(dev, page, reg, lo); - b53_mmap_write16(dev, page, reg + 4, hi); - } - - return 0; -} - -static int b53_mmap_write64(struct b53_device *dev, u8 page, u8 reg, - u64 value) -{ - u32 hi, lo; - - hi = (u32)(value >> 32); - lo = (u32)value; - - if (WARN_ON(reg % 4)) - return -EINVAL; - - b53_mmap_write32(dev, page, reg, lo); - b53_mmap_write32(dev, page, reg + 4, hi); - - return 0; -} - -static struct b53_io_ops b53_mmap_ops = { - .read8 = b53_mmap_read8, - .read16 = b53_mmap_read16, - .read32 = b53_mmap_read32, - .read48 = b53_mmap_read48, - .read64 = b53_mmap_read64, - .write8 = b53_mmap_write8, - .write16 = b53_mmap_write16, - .write32 = b53_mmap_write32, - .write48 = b53_mmap_write48, - .write64 = b53_mmap_write64, -}; - -static int b53_mmap_probe(struct platform_device *pdev) -{ - struct b53_platform_data *pdata = pdev->dev.platform_data; - struct b53_device *dev; - - if (!pdata) - return -EINVAL; - - dev = b53_swconfig_switch_alloc(&pdev->dev, &b53_mmap_ops, pdata->regs); - if (!dev) - return -ENOMEM; - - if (pdata) - dev->pdata = pdata; - - platform_set_drvdata(pdev, dev); - - return b53_swconfig_switch_register(dev); -} - -static int b53_mmap_remove(struct platform_device *pdev) -{ - struct b53_device *dev = platform_get_drvdata(pdev); - - if (dev) - b53_switch_remove(dev); - - return 0; -} - -static struct platform_driver b53_mmap_driver = { - .probe = b53_mmap_probe, - .remove = b53_mmap_remove, - .driver = { - .name = "b53-switch", - }, -}; - -module_platform_driver(b53_mmap_driver); -MODULE_AUTHOR("Jonas Gorski "); -MODULE_DESCRIPTION("B53 MMAP access driver"); -MODULE_LICENSE("Dual BSD/GPL"); diff --git a/target/linux/generic/files-6.12/drivers/net/phy/b53/b53_phy_fixup.c b/target/linux/generic/files-6.12/drivers/net/phy/b53/b53_phy_fixup.c deleted file mode 100644 index a19eccefd14c5b..00000000000000 --- a/target/linux/generic/files-6.12/drivers/net/phy/b53/b53_phy_fixup.c +++ /dev/null @@ -1,55 +0,0 @@ -/* - * B53 PHY Fixup call - * - * Copyright (C) 2013 Jonas Gorski - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include -#include -#include - -#define B53_PSEUDO_PHY 0x1e /* Register Access Pseudo PHY */ - -#define B53_BRCM_OUI_1 0x0143bc00 -#define B53_BRCM_OUI_2 0x03625c00 -#define B53_BRCM_OUI_3 0x00406300 - -static int b53_phy_fixup(struct phy_device *dev) -{ - struct mii_bus *bus = dev->mdio.bus; - u32 phy_id; - - if (dev->mdio.addr != B53_PSEUDO_PHY) - return 0; - - /* read the first port's id */ - phy_id = mdiobus_read(bus, 0, 2) << 16; - phy_id |= mdiobus_read(bus, 0, 3); - - if ((phy_id & 0xfffffc00) == B53_BRCM_OUI_1 || - (phy_id & 0xfffffc00) == B53_BRCM_OUI_2 || - (phy_id & 0xffffff00) == B53_BRCM_OUI_3) { - dev->phy_id = phy_id; - } - - return 0; -} - -int __init b53_phy_fixup_register(void) -{ - return phy_register_fixup_for_id(PHY_ANY_ID, b53_phy_fixup); -} - -subsys_initcall(b53_phy_fixup_register); diff --git a/target/linux/generic/files-6.12/drivers/net/phy/b53/b53_priv.h b/target/linux/generic/files-6.12/drivers/net/phy/b53/b53_priv.h deleted file mode 100644 index e455c755bf22e3..00000000000000 --- a/target/linux/generic/files-6.12/drivers/net/phy/b53/b53_priv.h +++ /dev/null @@ -1,336 +0,0 @@ -/* - * B53 common definitions - * - * Copyright (C) 2011-2013 Jonas Gorski - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#ifndef __B53_PRIV_H -#define __B53_PRIV_H - -#include -#include -#include - -struct b53_device; - -struct b53_io_ops { - int (*read8)(struct b53_device *dev, u8 page, u8 reg, u8 *value); - int (*read16)(struct b53_device *dev, u8 page, u8 reg, u16 *value); - int (*read32)(struct b53_device *dev, u8 page, u8 reg, u32 *value); - int (*read48)(struct b53_device *dev, u8 page, u8 reg, u64 *value); - int (*read64)(struct b53_device *dev, u8 page, u8 reg, u64 *value); - int (*write8)(struct b53_device *dev, u8 page, u8 reg, u8 value); - int (*write16)(struct b53_device *dev, u8 page, u8 reg, u16 value); - int (*write32)(struct b53_device *dev, u8 page, u8 reg, u32 value); - int (*write48)(struct b53_device *dev, u8 page, u8 reg, u64 value); - int (*write64)(struct b53_device *dev, u8 page, u8 reg, u64 value); - int (*phy_read16)(struct b53_device *dev, int addr, u8 reg, u16 *value); - int (*phy_write16)(struct b53_device *dev, int addr, u8 reg, u16 value); -}; - -enum { - BCM5325_DEVICE_ID = 0x25, - BCM5365_DEVICE_ID = 0x65, - BCM5395_DEVICE_ID = 0x95, - BCM5397_DEVICE_ID = 0x97, - BCM5398_DEVICE_ID = 0x98, - BCM53115_DEVICE_ID = 0x53115, - BCM53125_DEVICE_ID = 0x53125, - BCM53128_DEVICE_ID = 0x53128, - BCM63XX_DEVICE_ID = 0x6300, - BCM53010_DEVICE_ID = 0x53010, - BCM53011_DEVICE_ID = 0x53011, - BCM53012_DEVICE_ID = 0x53012, - BCM53018_DEVICE_ID = 0x53018, - BCM53019_DEVICE_ID = 0x53019, -}; - -#define B53_N_PORTS 9 -#define B53_N_PORTS_25 6 - -struct b53_vlan { - unsigned int members:B53_N_PORTS; - unsigned int untag:B53_N_PORTS; -}; - -struct b53_port { - unsigned int pvid:12; -}; - -struct b53_device { - struct switch_dev sw_dev; - struct b53_platform_data *pdata; - - struct mutex reg_mutex; - const struct b53_io_ops *ops; - - /* chip specific data */ - u32 chip_id; - u8 core_rev; - u8 vta_regs[3]; - u8 duplex_reg; - u8 jumbo_pm_reg; - u8 jumbo_size_reg; - int reset_gpio; - - /* used ports mask */ - u16 enabled_ports; - - /* connect specific data */ - u8 current_page; - struct device *dev; - void *priv; - - /* run time configuration */ - unsigned enable_vlan:1; - unsigned enable_jumbo:1; - unsigned allow_vid_4095:1; - - struct b53_port *ports; - struct b53_vlan *vlans; - - char *buf; -}; - -#define b53_for_each_port(dev, i) \ - for (i = 0; i < B53_N_PORTS; i++) \ - if (dev->enabled_ports & BIT(i)) - - - -static inline int is5325(struct b53_device *dev) -{ - return dev->chip_id == BCM5325_DEVICE_ID; -} - -static inline int is5365(struct b53_device *dev) -{ -#ifdef CONFIG_BCM47XX - return dev->chip_id == BCM5365_DEVICE_ID; -#else - return 0; -#endif -} - -static inline int is5397_98(struct b53_device *dev) -{ - return dev->chip_id == BCM5397_DEVICE_ID || - dev->chip_id == BCM5398_DEVICE_ID; -} - -static inline int is539x(struct b53_device *dev) -{ - return dev->chip_id == BCM5395_DEVICE_ID || - dev->chip_id == BCM5397_DEVICE_ID || - dev->chip_id == BCM5398_DEVICE_ID; -} - -static inline int is531x5(struct b53_device *dev) -{ - return dev->chip_id == BCM53115_DEVICE_ID || - dev->chip_id == BCM53125_DEVICE_ID || - dev->chip_id == BCM53128_DEVICE_ID; -} - -static inline int is63xx(struct b53_device *dev) -{ -#ifdef CONFIG_BCM63XX - return dev->chip_id == BCM63XX_DEVICE_ID; -#else - return 0; -#endif -} - -static inline int is5301x(struct b53_device *dev) -{ - return dev->chip_id == BCM53010_DEVICE_ID || - dev->chip_id == BCM53011_DEVICE_ID || - dev->chip_id == BCM53012_DEVICE_ID || - dev->chip_id == BCM53018_DEVICE_ID || - dev->chip_id == BCM53019_DEVICE_ID; -} - -#define B53_CPU_PORT_25 5 -#define B53_CPU_PORT 8 - -static inline int is_cpu_port(struct b53_device *dev, int port) -{ - return dev->sw_dev.cpu_port == port; -} - -static inline int is_imp_port(struct b53_device *dev, int port) -{ - if (is5325(dev) || is5365(dev)) - return port == B53_CPU_PORT_25; - else - return port == B53_CPU_PORT; -} - -static inline struct b53_device *sw_to_b53(struct switch_dev *sw) -{ - return container_of(sw, struct b53_device, sw_dev); -} - -struct b53_device *b53_swconfig_switch_alloc(struct device *base, struct b53_io_ops *ops, - void *priv); - -int b53_swconfig_switch_detect(struct b53_device *dev); - -int b53_swconfig_switch_register(struct b53_device *dev); - -static inline void b53_switch_remove(struct b53_device *dev) -{ - unregister_switch(&dev->sw_dev); -} - -static inline int b53_read8(struct b53_device *dev, u8 page, u8 reg, u8 *val) -{ - int ret; - - mutex_lock(&dev->reg_mutex); - ret = dev->ops->read8(dev, page, reg, val); - mutex_unlock(&dev->reg_mutex); - - return ret; -} - -static inline int b53_read16(struct b53_device *dev, u8 page, u8 reg, u16 *val) -{ - int ret; - - mutex_lock(&dev->reg_mutex); - ret = dev->ops->read16(dev, page, reg, val); - mutex_unlock(&dev->reg_mutex); - - return ret; -} - -static inline int b53_read32(struct b53_device *dev, u8 page, u8 reg, u32 *val) -{ - int ret; - - mutex_lock(&dev->reg_mutex); - ret = dev->ops->read32(dev, page, reg, val); - mutex_unlock(&dev->reg_mutex); - - return ret; -} - -static inline int b53_read48(struct b53_device *dev, u8 page, u8 reg, u64 *val) -{ - int ret; - - mutex_lock(&dev->reg_mutex); - ret = dev->ops->read48(dev, page, reg, val); - mutex_unlock(&dev->reg_mutex); - - return ret; -} - -static inline int b53_read64(struct b53_device *dev, u8 page, u8 reg, u64 *val) -{ - int ret; - - mutex_lock(&dev->reg_mutex); - ret = dev->ops->read64(dev, page, reg, val); - mutex_unlock(&dev->reg_mutex); - - return ret; -} - -static inline int b53_write8(struct b53_device *dev, u8 page, u8 reg, u8 value) -{ - int ret; - - mutex_lock(&dev->reg_mutex); - ret = dev->ops->write8(dev, page, reg, value); - mutex_unlock(&dev->reg_mutex); - - return ret; -} - -static inline int b53_write16(struct b53_device *dev, u8 page, u8 reg, - u16 value) -{ - int ret; - - mutex_lock(&dev->reg_mutex); - ret = dev->ops->write16(dev, page, reg, value); - mutex_unlock(&dev->reg_mutex); - - return ret; -} - -static inline int b53_write32(struct b53_device *dev, u8 page, u8 reg, - u32 value) -{ - int ret; - - mutex_lock(&dev->reg_mutex); - ret = dev->ops->write32(dev, page, reg, value); - mutex_unlock(&dev->reg_mutex); - - return ret; -} - -static inline int b53_write48(struct b53_device *dev, u8 page, u8 reg, - u64 value) -{ - int ret; - - mutex_lock(&dev->reg_mutex); - ret = dev->ops->write48(dev, page, reg, value); - mutex_unlock(&dev->reg_mutex); - - return ret; -} - -static inline int b53_write64(struct b53_device *dev, u8 page, u8 reg, - u64 value) -{ - int ret; - - mutex_lock(&dev->reg_mutex); - ret = dev->ops->write64(dev, page, reg, value); - mutex_unlock(&dev->reg_mutex); - - return ret; -} - -#ifdef CONFIG_BCM47XX -#include -#endif - -#include -#include - -static inline int b53_switch_get_reset_gpio(struct b53_device *dev) -{ -#ifdef CONFIG_BCM47XX - enum bcm47xx_board board = bcm47xx_board_get(); - - switch (board) { - case BCM47XX_BOARD_LINKSYS_WRT300NV11: - case BCM47XX_BOARD_LINKSYS_WRT310NV1: - return 8; - default: - break; - } -#endif - - return bcm47xx_nvram_gpio_pin("robo_reset"); -} - -#endif diff --git a/target/linux/generic/files-6.12/drivers/net/phy/b53/b53_regs.h b/target/linux/generic/files-6.12/drivers/net/phy/b53/b53_regs.h deleted file mode 100644 index f0bf6744a75c3b..00000000000000 --- a/target/linux/generic/files-6.12/drivers/net/phy/b53/b53_regs.h +++ /dev/null @@ -1,348 +0,0 @@ -/* - * B53 register definitions - * - * Copyright (C) 2004 Broadcom Corporation - * Copyright (C) 2011-2013 Jonas Gorski - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#ifndef __B53_REGS_H -#define __B53_REGS_H - -/* Management Port (SMP) Page offsets */ -#define B53_CTRL_PAGE 0x00 /* Control */ -#define B53_STAT_PAGE 0x01 /* Status */ -#define B53_MGMT_PAGE 0x02 /* Management Mode */ -#define B53_MIB_AC_PAGE 0x03 /* MIB Autocast */ -#define B53_ARLCTRL_PAGE 0x04 /* ARL Control */ -#define B53_ARLIO_PAGE 0x05 /* ARL Access */ -#define B53_FRAMEBUF_PAGE 0x06 /* Management frame access */ -#define B53_MEM_ACCESS_PAGE 0x08 /* Memory access */ - -/* PHY Registers */ -#define B53_PORT_MII_PAGE(i) (0x10 + (i)) /* Port i MII Registers */ -#define B53_IM_PORT_PAGE 0x18 /* Inverse MII Port (to EMAC) */ -#define B53_ALL_PORT_PAGE 0x19 /* All ports MII (broadcast) */ - -/* MIB registers */ -#define B53_MIB_PAGE(i) (0x20 + (i)) - -/* Quality of Service (QoS) Registers */ -#define B53_QOS_PAGE 0x30 - -/* Port VLAN Page */ -#define B53_PVLAN_PAGE 0x31 - -/* VLAN Registers */ -#define B53_VLAN_PAGE 0x34 - -/* Jumbo Frame Registers */ -#define B53_JUMBO_PAGE 0x40 - -/* CFP Configuration Registers Page */ -#define B53_CFP_PAGE 0xa1 - -/************************************************************************* - * Control Page registers - *************************************************************************/ - -/* Port Control Register (8 bit) */ -#define B53_PORT_CTRL(i) (0x00 + (i)) -#define PORT_CTRL_RX_DISABLE BIT(0) -#define PORT_CTRL_TX_DISABLE BIT(1) -#define PORT_CTRL_RX_BCST_EN BIT(2) /* Broadcast RX (P8 only) */ -#define PORT_CTRL_RX_MCST_EN BIT(3) /* Multicast RX (P8 only) */ -#define PORT_CTRL_RX_UCST_EN BIT(4) /* Unicast RX (P8 only) */ -#define PORT_CTRL_STP_STATE_S 5 -#define PORT_CTRL_STP_STATE_MASK (0x7 << PORT_CTRL_STP_STATE_S) - -/* SMP Control Register (8 bit) */ -#define B53_SMP_CTRL 0x0a - -/* Switch Mode Control Register (8 bit) */ -#define B53_SWITCH_MODE 0x0b -#define SM_SW_FWD_MODE BIT(0) /* 1 = Managed Mode */ -#define SM_SW_FWD_EN BIT(1) /* Forwarding Enable */ - -/* IMP Port state override register (8 bit) */ -#define B53_PORT_OVERRIDE_CTRL 0x0e -#define PORT_OVERRIDE_LINK BIT(0) -#define PORT_OVERRIDE_FULL_DUPLEX BIT(1) /* 0 = Half Duplex */ -#define PORT_OVERRIDE_SPEED_S 2 -#define PORT_OVERRIDE_SPEED_10M (0 << PORT_OVERRIDE_SPEED_S) -#define PORT_OVERRIDE_SPEED_100M (1 << PORT_OVERRIDE_SPEED_S) -#define PORT_OVERRIDE_SPEED_1000M (2 << PORT_OVERRIDE_SPEED_S) -#define PORT_OVERRIDE_RV_MII_25 BIT(4) /* BCM5325 only */ -#define PORT_OVERRIDE_RX_FLOW BIT(4) -#define PORT_OVERRIDE_TX_FLOW BIT(5) -#define PORT_OVERRIDE_SPEED_2000M BIT(6) /* BCM5301X only, requires setting 1000M */ -#define PORT_OVERRIDE_EN BIT(7) /* Use the register contents */ - -/* Power-down mode control */ -#define B53_PD_MODE_CTRL_25 0x0f - -/* IP Multicast control (8 bit) */ -#define B53_IP_MULTICAST_CTRL 0x21 -#define B53_IPMC_FWD_EN BIT(1) -#define B53_UC_FWD_EN BIT(6) -#define B53_MC_FWD_EN BIT(7) - -/* (16 bit) */ -#define B53_UC_FLOOD_MASK 0x32 -#define B53_MC_FLOOD_MASK 0x34 -#define B53_IPMC_FLOOD_MASK 0x36 - -/* - * Override Ports 0-7 State on devices with xMII interfaces (8 bit) - * - * For port 8 still use B53_PORT_OVERRIDE_CTRL - * Please note that not all ports are available on every hardware, e.g. BCM5301X - * don't include overriding port 6, BCM63xx also have some limitations. - */ -#define B53_GMII_PORT_OVERRIDE_CTRL(i) (0x58 + (i)) -#define GMII_PO_LINK BIT(0) -#define GMII_PO_FULL_DUPLEX BIT(1) /* 0 = Half Duplex */ -#define GMII_PO_SPEED_S 2 -#define GMII_PO_SPEED_10M (0 << GMII_PO_SPEED_S) -#define GMII_PO_SPEED_100M (1 << GMII_PO_SPEED_S) -#define GMII_PO_SPEED_1000M (2 << GMII_PO_SPEED_S) -#define GMII_PO_RX_FLOW BIT(4) -#define GMII_PO_TX_FLOW BIT(5) -#define GMII_PO_EN BIT(6) /* Use the register contents */ -#define GMII_PO_SPEED_2000M BIT(7) /* BCM5301X only, requires setting 1000M */ - -/* Software reset register (8 bit) */ -#define B53_SOFTRESET 0x79 - -/* Fast Aging Control register (8 bit) */ -#define B53_FAST_AGE_CTRL 0x88 -#define FAST_AGE_STATIC BIT(0) -#define FAST_AGE_DYNAMIC BIT(1) -#define FAST_AGE_PORT BIT(2) -#define FAST_AGE_VLAN BIT(3) -#define FAST_AGE_STP BIT(4) -#define FAST_AGE_MC BIT(5) -#define FAST_AGE_DONE BIT(7) - -/************************************************************************* - * Status Page registers - *************************************************************************/ - -/* Link Status Summary Register (16bit) */ -#define B53_LINK_STAT 0x00 - -/* Link Status Change Register (16 bit) */ -#define B53_LINK_STAT_CHANGE 0x02 - -/* Port Speed Summary Register (16 bit for FE, 32 bit for GE) */ -#define B53_SPEED_STAT 0x04 -#define SPEED_PORT_FE(reg, port) (((reg) >> (port)) & 1) -#define SPEED_PORT_GE(reg, port) (((reg) >> 2 * (port)) & 3) -#define SPEED_STAT_10M 0 -#define SPEED_STAT_100M 1 -#define SPEED_STAT_1000M 2 - -/* Duplex Status Summary (16 bit) */ -#define B53_DUPLEX_STAT_FE 0x06 -#define B53_DUPLEX_STAT_GE 0x08 -#define B53_DUPLEX_STAT_63XX 0x0c - -/* Revision ID register for BCM5325 */ -#define B53_REV_ID_25 0x50 - -/* Strap Value (48 bit) */ -#define B53_STRAP_VALUE 0x70 -#define SV_GMII_CTRL_115 BIT(27) - -/************************************************************************* - * Management Mode Page Registers - *************************************************************************/ - -/* Global Management Config Register (8 bit) */ -#define B53_GLOBAL_CONFIG 0x00 -#define GC_RESET_MIB 0x01 -#define GC_RX_BPDU_EN 0x02 -#define GC_MIB_AC_HDR_EN 0x10 -#define GC_MIB_AC_EN 0x20 -#define GC_FRM_MGMT_PORT_M 0xC0 -#define GC_FRM_MGMT_PORT_04 0x00 -#define GC_FRM_MGMT_PORT_MII 0x80 - -/* Broadcom Header control register (8 bit) */ -#define B53_BRCM_HDR 0x03 -#define BRCM_HDR_P8_EN BIT(0) /* Enable tagging on port 8 */ -#define BRCM_HDR_P5_EN BIT(1) /* Enable tagging on port 5 */ - -/* Device ID register (8 or 32 bit) */ -#define B53_DEVICE_ID 0x30 - -/* Revision ID register (8 bit) */ -#define B53_REV_ID 0x40 - -/************************************************************************* - * ARL Access Page Registers - *************************************************************************/ - -/* VLAN Table Access Register (8 bit) */ -#define B53_VT_ACCESS 0x80 -#define B53_VT_ACCESS_9798 0x60 /* for BCM5397/BCM5398 */ -#define B53_VT_ACCESS_63XX 0x60 /* for BCM6328/62/68 */ -#define VTA_CMD_WRITE 0 -#define VTA_CMD_READ 1 -#define VTA_CMD_CLEAR 2 -#define VTA_START_CMD BIT(7) - -/* VLAN Table Index Register (16 bit) */ -#define B53_VT_INDEX 0x81 -#define B53_VT_INDEX_9798 0x61 -#define B53_VT_INDEX_63XX 0x62 - -/* VLAN Table Entry Register (32 bit) */ -#define B53_VT_ENTRY 0x83 -#define B53_VT_ENTRY_9798 0x63 -#define B53_VT_ENTRY_63XX 0x64 -#define VTE_MEMBERS 0x1ff -#define VTE_UNTAG_S 9 -#define VTE_UNTAG (0x1ff << 9) - -/************************************************************************* - * Port VLAN Registers - *************************************************************************/ - -/* Port VLAN mask (16 bit) IMP port is always 8, also on 5325 & co */ -#define B53_PVLAN_PORT_MASK(i) ((i) * 2) - -/************************************************************************* - * 802.1Q Page Registers - *************************************************************************/ - -/* Global QoS Control (8 bit) */ -#define B53_QOS_GLOBAL_CTL 0x00 - -/* Enable 802.1Q for individual Ports (16 bit) */ -#define B53_802_1P_EN 0x04 - -/************************************************************************* - * VLAN Page Registers - *************************************************************************/ - -/* VLAN Control 0 (8 bit) */ -#define B53_VLAN_CTRL0 0x00 -#define VC0_8021PF_CTRL_MASK 0x3 -#define VC0_8021PF_CTRL_NONE 0x0 -#define VC0_8021PF_CTRL_CHANGE_PRI 0x1 -#define VC0_8021PF_CTRL_CHANGE_VID 0x2 -#define VC0_8021PF_CTRL_CHANGE_BOTH 0x3 -#define VC0_8021QF_CTRL_MASK 0xc -#define VC0_8021QF_CTRL_CHANGE_PRI 0x1 -#define VC0_8021QF_CTRL_CHANGE_VID 0x2 -#define VC0_8021QF_CTRL_CHANGE_BOTH 0x3 -#define VC0_RESERVED_1 BIT(1) -#define VC0_DROP_VID_MISS BIT(4) -#define VC0_VID_HASH_VID BIT(5) -#define VC0_VID_CHK_EN BIT(6) /* Use VID,DA or VID,SA */ -#define VC0_VLAN_EN BIT(7) /* 802.1Q VLAN Enabled */ - -/* VLAN Control 1 (8 bit) */ -#define B53_VLAN_CTRL1 0x01 -#define VC1_RX_MCST_TAG_EN BIT(1) -#define VC1_RX_MCST_FWD_EN BIT(2) -#define VC1_RX_MCST_UNTAG_EN BIT(3) - -/* VLAN Control 2 (8 bit) */ -#define B53_VLAN_CTRL2 0x02 - -/* VLAN Control 3 (8 bit when BCM5325, 16 bit else) */ -#define B53_VLAN_CTRL3 0x03 -#define B53_VLAN_CTRL3_63XX 0x04 -#define VC3_MAXSIZE_1532 BIT(6) /* 5325 only */ -#define VC3_HIGH_8BIT_EN BIT(7) /* 5325 only */ - -/* VLAN Control 4 (8 bit) */ -#define B53_VLAN_CTRL4 0x05 -#define B53_VLAN_CTRL4_25 0x04 -#define B53_VLAN_CTRL4_63XX 0x06 -#define VC4_ING_VID_CHECK_S 6 -#define VC4_ING_VID_CHECK_MASK (0x3 << VC4_ING_VID_CHECK_S) -#define VC4_ING_VID_VIO_FWD 0 /* forward, but do not learn */ -#define VC4_ING_VID_VIO_DROP 1 /* drop VID violations */ -#define VC4_NO_ING_VID_CHK 2 /* do not check */ -#define VC4_ING_VID_VIO_TO_IMP 3 /* redirect to MII port */ - -/* VLAN Control 5 (8 bit) */ -#define B53_VLAN_CTRL5 0x06 -#define B53_VLAN_CTRL5_25 0x05 -#define B53_VLAN_CTRL5_63XX 0x07 -#define VC5_VID_FFF_EN BIT(2) -#define VC5_DROP_VTABLE_MISS BIT(3) - -/* VLAN Control 6 (8 bit) */ -#define B53_VLAN_CTRL6 0x07 -#define B53_VLAN_CTRL6_63XX 0x08 - -/* VLAN Table Access Register (16 bit) */ -#define B53_VLAN_TABLE_ACCESS_25 0x06 /* BCM5325E/5350 */ -#define B53_VLAN_TABLE_ACCESS_65 0x08 /* BCM5365 */ -#define VTA_VID_LOW_MASK_25 0xf -#define VTA_VID_LOW_MASK_65 0xff -#define VTA_VID_HIGH_S_25 4 -#define VTA_VID_HIGH_S_65 8 -#define VTA_VID_HIGH_MASK_25 (0xff << VTA_VID_HIGH_S_25E) -#define VTA_VID_HIGH_MASK_65 (0xf << VTA_VID_HIGH_S_65) -#define VTA_RW_STATE BIT(12) -#define VTA_RW_STATE_RD 0 -#define VTA_RW_STATE_WR BIT(12) -#define VTA_RW_OP_EN BIT(13) - -/* VLAN Read/Write Registers for (16/32 bit) */ -#define B53_VLAN_WRITE_25 0x08 -#define B53_VLAN_WRITE_65 0x0a -#define B53_VLAN_READ 0x0c -#define VA_MEMBER_MASK 0x3f -#define VA_UNTAG_S_25 6 -#define VA_UNTAG_MASK_25 0x3f -#define VA_UNTAG_S_65 7 -#define VA_UNTAG_MASK_65 0x1f -#define VA_VID_HIGH_S 12 -#define VA_VID_HIGH_MASK (0xffff << VA_VID_HIGH_S) -#define VA_VALID_25 BIT(20) -#define VA_VALID_25_R4 BIT(24) -#define VA_VALID_65 BIT(14) - -/* VLAN Port Default Tag (16 bit) */ -#define B53_VLAN_PORT_DEF_TAG(i) (0x10 + 2 * (i)) - -/************************************************************************* - * Jumbo Frame Page Registers - *************************************************************************/ - -/* Jumbo Enable Port Mask (bit i == port i enabled) (32 bit) */ -#define B53_JUMBO_PORT_MASK 0x01 -#define B53_JUMBO_PORT_MASK_63XX 0x04 -#define JPM_10_100_JUMBO_EN BIT(24) /* GigE always enabled */ - -/* Good Frame Max Size without 802.1Q TAG (16 bit) */ -#define B53_JUMBO_MAX_SIZE 0x05 -#define B53_JUMBO_MAX_SIZE_63XX 0x08 -#define JMS_MIN_SIZE 1518 -#define JMS_MAX_SIZE 9724 - -/************************************************************************* - * CFP Configuration Page Registers - *************************************************************************/ - -/* CFP Control Register with ports map (8 bit) */ -#define B53_CFP_CTRL 0x00 - -#endif /* !__B53_REGS_H */ diff --git a/target/linux/generic/files-6.12/drivers/net/phy/b53/b53_spi.c b/target/linux/generic/files-6.12/drivers/net/phy/b53/b53_spi.c deleted file mode 100644 index 400454df18c119..00000000000000 --- a/target/linux/generic/files-6.12/drivers/net/phy/b53/b53_spi.c +++ /dev/null @@ -1,344 +0,0 @@ -/* - * B53 register access through SPI - * - * Copyright (C) 2011-2013 Jonas Gorski - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include - -#include -#include -#include -#include -#include - -#include "b53_priv.h" - -#define B53_SPI_DATA 0xf0 - -#define B53_SPI_STATUS 0xfe -#define B53_SPI_CMD_SPIF BIT(7) -#define B53_SPI_CMD_RACK BIT(5) - -#define B53_SPI_CMD_READ 0x00 -#define B53_SPI_CMD_WRITE 0x01 -#define B53_SPI_CMD_NORMAL 0x60 -#define B53_SPI_CMD_FAST 0x10 - -#define B53_SPI_PAGE_SELECT 0xff - -static inline int b53_spi_read_reg(struct spi_device *spi, u8 reg, u8 *val, - unsigned len) -{ - u8 txbuf[2]; - - txbuf[0] = B53_SPI_CMD_NORMAL | B53_SPI_CMD_READ; - txbuf[1] = reg; - - return spi_write_then_read(spi, txbuf, 2, val, len); -} - -static inline int b53_spi_clear_status(struct spi_device *spi) -{ - unsigned int i; - u8 rxbuf; - int ret; - - for (i = 0; i < 10; i++) { - ret = b53_spi_read_reg(spi, B53_SPI_STATUS, &rxbuf, 1); - if (ret) - return ret; - - if (!(rxbuf & B53_SPI_CMD_SPIF)) - break; - - mdelay(1); - } - - if (i == 10) - return -EIO; - - return 0; -} - -static inline int b53_spi_set_page(struct spi_device *spi, u8 page) -{ - u8 txbuf[3]; - - txbuf[0] = B53_SPI_CMD_NORMAL | B53_SPI_CMD_WRITE; - txbuf[1] = B53_SPI_PAGE_SELECT; - txbuf[2] = page; - - return spi_write(spi, txbuf, sizeof(txbuf)); -} - -static inline int b53_prepare_reg_access(struct spi_device *spi, u8 page) -{ - int ret = b53_spi_clear_status(spi); - - if (ret) - return ret; - - return b53_spi_set_page(spi, page); -} - -static int b53_spi_prepare_reg_read(struct spi_device *spi, u8 reg) -{ - u8 rxbuf; - int retry_count; - int ret; - - ret = b53_spi_read_reg(spi, reg, &rxbuf, 1); - if (ret) - return ret; - - for (retry_count = 0; retry_count < 10; retry_count++) { - ret = b53_spi_read_reg(spi, B53_SPI_STATUS, &rxbuf, 1); - if (ret) - return ret; - - if (rxbuf & B53_SPI_CMD_RACK) - break; - - mdelay(1); - } - - if (retry_count == 10) - return -EIO; - - return 0; -} - -static int b53_spi_read(struct b53_device *dev, u8 page, u8 reg, u8 *data, - unsigned len) -{ - struct spi_device *spi = dev->priv; - int ret; - - ret = b53_prepare_reg_access(spi, page); - if (ret) - return ret; - - ret = b53_spi_prepare_reg_read(spi, reg); - if (ret) - return ret; - - return b53_spi_read_reg(spi, B53_SPI_DATA, data, len); -} - -static int b53_spi_read8(struct b53_device *dev, u8 page, u8 reg, u8 *val) -{ - return b53_spi_read(dev, page, reg, val, 1); -} - -static int b53_spi_read16(struct b53_device *dev, u8 page, u8 reg, u16 *val) -{ - int ret = b53_spi_read(dev, page, reg, (u8 *)val, 2); - - if (!ret) - *val = le16_to_cpu(*val); - - return ret; -} - -static int b53_spi_read32(struct b53_device *dev, u8 page, u8 reg, u32 *val) -{ - int ret = b53_spi_read(dev, page, reg, (u8 *)val, 4); - - if (!ret) - *val = le32_to_cpu(*val); - - return ret; -} - -static int b53_spi_read48(struct b53_device *dev, u8 page, u8 reg, u64 *val) -{ - int ret; - - *val = 0; - ret = b53_spi_read(dev, page, reg, (u8 *)val, 6); - if (!ret) - *val = le64_to_cpu(*val); - - return ret; -} - -static int b53_spi_read64(struct b53_device *dev, u8 page, u8 reg, u64 *val) -{ - int ret = b53_spi_read(dev, page, reg, (u8 *)val, 8); - - if (!ret) - *val = le64_to_cpu(*val); - - return ret; -} - -static int b53_spi_write8(struct b53_device *dev, u8 page, u8 reg, u8 value) -{ - struct spi_device *spi = dev->priv; - int ret; - u8 txbuf[3]; - - ret = b53_prepare_reg_access(spi, page); - if (ret) - return ret; - - txbuf[0] = B53_SPI_CMD_NORMAL | B53_SPI_CMD_WRITE; - txbuf[1] = reg; - txbuf[2] = value; - - return spi_write(spi, txbuf, sizeof(txbuf)); -} - -static int b53_spi_write16(struct b53_device *dev, u8 page, u8 reg, u16 value) -{ - struct spi_device *spi = dev->priv; - int ret; - u8 txbuf[4]; - - ret = b53_prepare_reg_access(spi, page); - if (ret) - return ret; - - txbuf[0] = B53_SPI_CMD_NORMAL | B53_SPI_CMD_WRITE; - txbuf[1] = reg; - put_unaligned_le16(value, &txbuf[2]); - - return spi_write(spi, txbuf, sizeof(txbuf)); -} - -static int b53_spi_write32(struct b53_device *dev, u8 page, u8 reg, u32 value) -{ - struct spi_device *spi = dev->priv; - int ret; - u8 txbuf[6]; - - ret = b53_prepare_reg_access(spi, page); - if (ret) - return ret; - - txbuf[0] = B53_SPI_CMD_NORMAL | B53_SPI_CMD_WRITE; - txbuf[1] = reg; - put_unaligned_le32(value, &txbuf[2]); - - return spi_write(spi, txbuf, sizeof(txbuf)); -} - -static int b53_spi_write48(struct b53_device *dev, u8 page, u8 reg, u64 value) -{ - struct spi_device *spi = dev->priv; - int ret; - u8 txbuf[10]; - - ret = b53_prepare_reg_access(spi, page); - if (ret) - return ret; - - txbuf[0] = B53_SPI_CMD_NORMAL | B53_SPI_CMD_WRITE; - txbuf[1] = reg; - put_unaligned_le64(value, &txbuf[2]); - - return spi_write(spi, txbuf, sizeof(txbuf) - 2); -} - -static int b53_spi_write64(struct b53_device *dev, u8 page, u8 reg, u64 value) -{ - struct spi_device *spi = dev->priv; - int ret; - u8 txbuf[10]; - - ret = b53_prepare_reg_access(spi, page); - if (ret) - return ret; - - txbuf[0] = B53_SPI_CMD_NORMAL | B53_SPI_CMD_WRITE; - txbuf[1] = reg; - put_unaligned_le64(value, &txbuf[2]); - - return spi_write(spi, txbuf, sizeof(txbuf)); -} - -static struct b53_io_ops b53_spi_ops = { - .read8 = b53_spi_read8, - .read16 = b53_spi_read16, - .read32 = b53_spi_read32, - .read48 = b53_spi_read48, - .read64 = b53_spi_read64, - .write8 = b53_spi_write8, - .write16 = b53_spi_write16, - .write32 = b53_spi_write32, - .write48 = b53_spi_write48, - .write64 = b53_spi_write64, -}; - -static int b53_spi_probe(struct spi_device *spi) -{ - struct b53_device *dev; - int ret; - - dev = b53_swconfig_switch_alloc(&spi->dev, &b53_spi_ops, spi); - if (!dev) - return -ENOMEM; - - if (spi->dev.platform_data) - dev->pdata = spi->dev.platform_data; - - ret = b53_swconfig_switch_register(dev); - if (ret) - return ret; - - spi_set_drvdata(spi, dev); - - return 0; -} - -static int b53_spi_remove(struct spi_device *spi) -{ - struct b53_device *dev = spi_get_drvdata(spi); - - if (dev) - b53_switch_remove(dev); - - return 0; -} - -static const struct of_device_id b53_of_match[] = { - { .compatible = "brcm,bcm5325" }, - { .compatible = "brcm,bcm53115" }, - { .compatible = "brcm,bcm53125" }, - { .compatible = "brcm,bcm53128" }, - { .compatible = "brcm,bcm5365" }, - { .compatible = "brcm,bcm5395" }, - { .compatible = "brcm,bcm5397" }, - { .compatible = "brcm,bcm5398" }, - { /* sentinel */ }, -}; - -static struct spi_driver b53_spi_driver = { - .driver = { - .name = "b53-switch", - .bus = &spi_bus_type, - .owner = THIS_MODULE, - .of_match_table = b53_of_match, - }, - .probe = b53_spi_probe, - .remove = b53_spi_remove, -}; - -module_spi_driver(b53_spi_driver); - -MODULE_AUTHOR("Jonas Gorski "); -MODULE_DESCRIPTION("B53 SPI access driver"); -MODULE_LICENSE("Dual BSD/GPL"); diff --git a/target/linux/generic/files-6.12/drivers/net/phy/b53/b53_srab.c b/target/linux/generic/files-6.12/drivers/net/phy/b53/b53_srab.c deleted file mode 100644 index ead5209cf0b84b..00000000000000 --- a/target/linux/generic/files-6.12/drivers/net/phy/b53/b53_srab.c +++ /dev/null @@ -1,378 +0,0 @@ -/* - * B53 register access through Switch Register Access Bridge Registers - * - * Copyright (C) 2013 Hauke Mehrtens - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include -#include -#include -#include - -#include "b53_priv.h" - -/* command and status register of the SRAB */ -#define B53_SRAB_CMDSTAT 0x2c -#define B53_SRAB_CMDSTAT_RST BIT(2) -#define B53_SRAB_CMDSTAT_WRITE BIT(1) -#define B53_SRAB_CMDSTAT_GORDYN BIT(0) -#define B53_SRAB_CMDSTAT_PAGE 24 -#define B53_SRAB_CMDSTAT_REG 16 - -/* high order word of write data to switch registe */ -#define B53_SRAB_WD_H 0x30 - -/* low order word of write data to switch registe */ -#define B53_SRAB_WD_L 0x34 - -/* high order word of read data from switch register */ -#define B53_SRAB_RD_H 0x38 - -/* low order word of read data from switch register */ -#define B53_SRAB_RD_L 0x3c - -/* command and status register of the SRAB */ -#define B53_SRAB_CTRLS 0x40 -#define B53_SRAB_CTRLS_RCAREQ BIT(3) -#define B53_SRAB_CTRLS_RCAGNT BIT(4) -#define B53_SRAB_CTRLS_SW_INIT_DONE BIT(6) - -/* the register captures interrupt pulses from the switch */ -#define B53_SRAB_INTR 0x44 - -static int b53_srab_request_grant(struct b53_device *dev) -{ - u8 __iomem *regs = dev->priv; - u32 ctrls; - int i; - - ctrls = readl(regs + B53_SRAB_CTRLS); - ctrls |= B53_SRAB_CTRLS_RCAREQ; - writel(ctrls, regs + B53_SRAB_CTRLS); - - for (i = 0; i < 20; i++) { - ctrls = readl(regs + B53_SRAB_CTRLS); - if (ctrls & B53_SRAB_CTRLS_RCAGNT) - break; - usleep_range(10, 100); - } - if (WARN_ON(i == 5)) - return -EIO; - - return 0; -} - -static void b53_srab_release_grant(struct b53_device *dev) -{ - u8 __iomem *regs = dev->priv; - u32 ctrls; - - ctrls = readl(regs + B53_SRAB_CTRLS); - ctrls &= ~B53_SRAB_CTRLS_RCAREQ; - writel(ctrls, regs + B53_SRAB_CTRLS); -} - -static int b53_srab_op(struct b53_device *dev, u8 page, u8 reg, u32 op) -{ - int i; - u32 cmdstat; - u8 __iomem *regs = dev->priv; - - /* set register address */ - cmdstat = (page << B53_SRAB_CMDSTAT_PAGE) | - (reg << B53_SRAB_CMDSTAT_REG) | - B53_SRAB_CMDSTAT_GORDYN | - op; - writel(cmdstat, regs + B53_SRAB_CMDSTAT); - - /* check if operation completed */ - for (i = 0; i < 5; ++i) { - cmdstat = readl(regs + B53_SRAB_CMDSTAT); - if (!(cmdstat & B53_SRAB_CMDSTAT_GORDYN)) - break; - usleep_range(10, 100); - } - - if (WARN_ON(i == 5)) - return -EIO; - - return 0; -} - -static int b53_srab_read8(struct b53_device *dev, u8 page, u8 reg, u8 *val) -{ - u8 __iomem *regs = dev->priv; - int ret = 0; - - ret = b53_srab_request_grant(dev); - if (ret) - goto err; - - ret = b53_srab_op(dev, page, reg, 0); - if (ret) - goto err; - - *val = readl(regs + B53_SRAB_RD_L) & 0xff; - -err: - b53_srab_release_grant(dev); - - return ret; -} - -static int b53_srab_read16(struct b53_device *dev, u8 page, u8 reg, u16 *val) -{ - u8 __iomem *regs = dev->priv; - int ret = 0; - - ret = b53_srab_request_grant(dev); - if (ret) - goto err; - - ret = b53_srab_op(dev, page, reg, 0); - if (ret) - goto err; - - *val = readl(regs + B53_SRAB_RD_L) & 0xffff; - -err: - b53_srab_release_grant(dev); - - return ret; -} - -static int b53_srab_read32(struct b53_device *dev, u8 page, u8 reg, u32 *val) -{ - u8 __iomem *regs = dev->priv; - int ret = 0; - - ret = b53_srab_request_grant(dev); - if (ret) - goto err; - - ret = b53_srab_op(dev, page, reg, 0); - if (ret) - goto err; - - *val = readl(regs + B53_SRAB_RD_L); - -err: - b53_srab_release_grant(dev); - - return ret; -} - -static int b53_srab_read48(struct b53_device *dev, u8 page, u8 reg, u64 *val) -{ - u8 __iomem *regs = dev->priv; - int ret = 0; - - ret = b53_srab_request_grant(dev); - if (ret) - goto err; - - ret = b53_srab_op(dev, page, reg, 0); - if (ret) - goto err; - - *val = readl(regs + B53_SRAB_RD_L); - *val += ((u64)readl(regs + B53_SRAB_RD_H) & 0xffff) << 32; - -err: - b53_srab_release_grant(dev); - - return ret; -} - -static int b53_srab_read64(struct b53_device *dev, u8 page, u8 reg, u64 *val) -{ - u8 __iomem *regs = dev->priv; - int ret = 0; - - ret = b53_srab_request_grant(dev); - if (ret) - goto err; - - ret = b53_srab_op(dev, page, reg, 0); - if (ret) - goto err; - - *val = readl(regs + B53_SRAB_RD_L); - *val += (u64)readl(regs + B53_SRAB_RD_H) << 32; - -err: - b53_srab_release_grant(dev); - - return ret; -} - -static int b53_srab_write8(struct b53_device *dev, u8 page, u8 reg, u8 value) -{ - u8 __iomem *regs = dev->priv; - int ret = 0; - - ret = b53_srab_request_grant(dev); - if (ret) - goto err; - - writel(value, regs + B53_SRAB_WD_L); - - ret = b53_srab_op(dev, page, reg, B53_SRAB_CMDSTAT_WRITE); - -err: - b53_srab_release_grant(dev); - - return ret; -} - -static int b53_srab_write16(struct b53_device *dev, u8 page, u8 reg, - u16 value) -{ - u8 __iomem *regs = dev->priv; - int ret = 0; - - ret = b53_srab_request_grant(dev); - if (ret) - goto err; - - writel(value, regs + B53_SRAB_WD_L); - - ret = b53_srab_op(dev, page, reg, B53_SRAB_CMDSTAT_WRITE); - -err: - b53_srab_release_grant(dev); - - return ret; -} - -static int b53_srab_write32(struct b53_device *dev, u8 page, u8 reg, - u32 value) -{ - u8 __iomem *regs = dev->priv; - int ret = 0; - - ret = b53_srab_request_grant(dev); - if (ret) - goto err; - - writel(value, regs + B53_SRAB_WD_L); - - ret = b53_srab_op(dev, page, reg, B53_SRAB_CMDSTAT_WRITE); - -err: - b53_srab_release_grant(dev); - - return ret; - -} - -static int b53_srab_write48(struct b53_device *dev, u8 page, u8 reg, - u64 value) -{ - u8 __iomem *regs = dev->priv; - int ret = 0; - - ret = b53_srab_request_grant(dev); - if (ret) - goto err; - - writel((u32)value, regs + B53_SRAB_WD_L); - writel((u16)(value >> 32), regs + B53_SRAB_WD_H); - - ret = b53_srab_op(dev, page, reg, B53_SRAB_CMDSTAT_WRITE); - -err: - b53_srab_release_grant(dev); - - return ret; - -} - -static int b53_srab_write64(struct b53_device *dev, u8 page, u8 reg, - u64 value) -{ - u8 __iomem *regs = dev->priv; - int ret = 0; - - ret = b53_srab_request_grant(dev); - if (ret) - goto err; - - writel((u32)value, regs + B53_SRAB_WD_L); - writel((u32)(value >> 32), regs + B53_SRAB_WD_H); - - ret = b53_srab_op(dev, page, reg, B53_SRAB_CMDSTAT_WRITE); - -err: - b53_srab_release_grant(dev); - - return ret; -} - -static struct b53_io_ops b53_srab_ops = { - .read8 = b53_srab_read8, - .read16 = b53_srab_read16, - .read32 = b53_srab_read32, - .read48 = b53_srab_read48, - .read64 = b53_srab_read64, - .write8 = b53_srab_write8, - .write16 = b53_srab_write16, - .write32 = b53_srab_write32, - .write48 = b53_srab_write48, - .write64 = b53_srab_write64, -}; - -static int b53_srab_probe(struct platform_device *pdev) -{ - struct b53_platform_data *pdata = pdev->dev.platform_data; - struct b53_device *dev; - - if (!pdata) - return -EINVAL; - - dev = b53_swconfig_switch_alloc(&pdev->dev, &b53_srab_ops, pdata->regs); - if (!dev) - return -ENOMEM; - - if (pdata) - dev->pdata = pdata; - - platform_set_drvdata(pdev, dev); - - return b53_swconfig_switch_register(dev); -} - -static int b53_srab_remove(struct platform_device *pdev) -{ - struct b53_device *dev = platform_get_drvdata(pdev); - - if (dev) - b53_switch_remove(dev); - - return 0; -} - -static struct platform_driver b53_srab_driver = { - .probe = b53_srab_probe, - .remove = b53_srab_remove, - .driver = { - .name = "b53-srab-switch", - }, -}; - -module_platform_driver(b53_srab_driver); -MODULE_AUTHOR("Hauke Mehrtens "); -MODULE_DESCRIPTION("B53 Switch Register Access Bridge Registers (SRAB) access driver"); -MODULE_LICENSE("Dual BSD/GPL"); diff --git a/target/linux/generic/files-6.12/drivers/net/phy/ip17xx.c b/target/linux/generic/files-6.12/drivers/net/phy/ip17xx.c deleted file mode 100644 index c3698033957803..00000000000000 --- a/target/linux/generic/files-6.12/drivers/net/phy/ip17xx.c +++ /dev/null @@ -1,1370 +0,0 @@ -/* - * ip17xx.c: Swconfig configuration for IC+ IP17xx switch family - * - * Copyright (C) 2008 Patrick Horn - * Copyright (C) 2008, 2010 Martin Mares - * Copyright (C) 2009 Felix Fietkau - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define MAX_VLANS 16 -#define MAX_PORTS 9 -#undef DUMP_MII_IO - -typedef struct ip17xx_reg { - u16 p; // phy - u16 m; // mii -} reg; -typedef char bitnum; - -#define NOTSUPPORTED {-1,-1} - -#define REG_SUPP(x) (((x).m != ((u16)-1)) && ((x).p != (u16)-1)) - -struct ip17xx_state; - -/*********** CONSTANTS ***********/ -struct register_mappings { - char *NAME; - u16 MODEL_NO; // Compare to bits 4-9 of MII register 0,3. - bitnum NUM_PORTS; - bitnum CPU_PORT; - -/* The default VLAN for each port. - Default: 0x0001 for Ports 0,1,2,3 - 0x0002 for Ports 4,5 */ - reg VLAN_DEFAULT_TAG_REG[MAX_PORTS]; - -/* These ports are tagged. - Default: 0x00 */ - reg ADD_TAG_REG; - reg REMOVE_TAG_REG; - bitnum ADD_TAG_BIT[MAX_PORTS]; -/* These ports are untagged. - Default: 0x00 (i.e. do not alter any VLAN tags...) - Maybe set to 0 if user disables VLANs. */ - bitnum REMOVE_TAG_BIT[MAX_PORTS]; - -/* Port M and Port N are on the same VLAN. - Default: All ports on all VLANs. */ -// Use register {29, 19+N/2} - reg VLAN_LOOKUP_REG; -// Port 5 uses register {30, 18} but same as odd bits. - reg VLAN_LOOKUP_REG_5; // in a different register on IP175C. - bitnum VLAN_LOOKUP_EVEN_BIT[MAX_PORTS]; - bitnum VLAN_LOOKUP_ODD_BIT[MAX_PORTS]; - -/* This VLAN corresponds to which ports. - Default: 0x2f,0x30,0x3f,0x3f... */ - reg TAG_VLAN_MASK_REG; - bitnum TAG_VLAN_MASK_EVEN_BIT[MAX_PORTS]; - bitnum TAG_VLAN_MASK_ODD_BIT[MAX_PORTS]; - - int RESET_VAL; - reg RESET_REG; - - reg MODE_REG; - int MODE_VAL; - -/* General flags */ - reg ROUTER_CONTROL_REG; - reg VLAN_CONTROL_REG; - bitnum TAG_VLAN_BIT; - bitnum ROUTER_EN_BIT; - bitnum NUMLAN_GROUPS_MAX; - bitnum NUMLAN_GROUPS_BIT; - - reg MII_REGISTER_EN; - bitnum MII_REGISTER_EN_BIT; - - // set to 1 for 178C, 0 for 175C. - bitnum SIMPLE_VLAN_REGISTERS; // 175C has two vlans per register but 178C has only one. - - // Pointers to functions which manipulate hardware state - int (*update_state)(struct ip17xx_state *state); - int (*set_vlan_mode)(struct ip17xx_state *state); - int (*reset)(struct ip17xx_state *state); -}; - -static int ip175c_update_state(struct ip17xx_state *state); -static int ip175c_set_vlan_mode(struct ip17xx_state *state); -static int ip175c_reset(struct ip17xx_state *state); - -static const struct register_mappings IP178C = { - .NAME = "IP178C", - .MODEL_NO = 0x18, - .VLAN_DEFAULT_TAG_REG = { - {30,3},{30,4},{30,5},{30,6},{30,7},{30,8}, - {30,9},{30,10},{30,11}, - }, - - .ADD_TAG_REG = {30,12}, - .ADD_TAG_BIT = {0,1,2,3,4,5,6,7,8}, - .REMOVE_TAG_REG = {30,13}, - .REMOVE_TAG_BIT = {4,5,6,7,8,9,10,11,12}, - - .SIMPLE_VLAN_REGISTERS = 1, - - .VLAN_LOOKUP_REG = {31,0},// +N - .VLAN_LOOKUP_REG_5 = NOTSUPPORTED, // not used with SIMPLE_VLAN_REGISTERS - .VLAN_LOOKUP_EVEN_BIT = {0,1,2,3,4,5,6,7,8}, - .VLAN_LOOKUP_ODD_BIT = {0,1,2,3,4,5,6,7,8}, - - .TAG_VLAN_MASK_REG = {30,14}, // +N - .TAG_VLAN_MASK_EVEN_BIT = {0,1,2,3,4,5,6,7,8}, - .TAG_VLAN_MASK_ODD_BIT = {0,1,2,3,4,5,6,7,8}, - - .RESET_VAL = 0x55AA, - .RESET_REG = {30,0}, - .MODE_VAL = 0, - .MODE_REG = NOTSUPPORTED, - - .ROUTER_CONTROL_REG = {30,30}, - .ROUTER_EN_BIT = 11, - .NUMLAN_GROUPS_MAX = 8, - .NUMLAN_GROUPS_BIT = 8, // {0-2} - - .VLAN_CONTROL_REG = {30,13}, - .TAG_VLAN_BIT = 3, - - .CPU_PORT = 8, - .NUM_PORTS = 9, - - .MII_REGISTER_EN = NOTSUPPORTED, - - .update_state = ip175c_update_state, - .set_vlan_mode = ip175c_set_vlan_mode, - .reset = ip175c_reset, -}; - -static const struct register_mappings IP175C = { - .NAME = "IP175C", - .MODEL_NO = 0x18, - .VLAN_DEFAULT_TAG_REG = { - {29,24},{29,25},{29,26},{29,27},{29,28},{29,30}, - NOTSUPPORTED,NOTSUPPORTED,NOTSUPPORTED - }, - - .ADD_TAG_REG = {29,23}, - .REMOVE_TAG_REG = {29,23}, - .ADD_TAG_BIT = {11,12,13,14,15,1,-1,-1,-1}, - .REMOVE_TAG_BIT = {6,7,8,9,10,0,-1,-1,-1}, - - .SIMPLE_VLAN_REGISTERS = 0, - - .VLAN_LOOKUP_REG = {29,19},// +N/2 - .VLAN_LOOKUP_REG_5 = {30,18}, - .VLAN_LOOKUP_EVEN_BIT = {8,9,10,11,12,15,-1,-1,-1}, - .VLAN_LOOKUP_ODD_BIT = {0,1,2,3,4,7,-1,-1,-1}, - - .TAG_VLAN_MASK_REG = {30,1}, // +N/2 - .TAG_VLAN_MASK_EVEN_BIT = {0,1,2,3,4,5,-1,-1,-1}, - .TAG_VLAN_MASK_ODD_BIT = {8,9,10,11,12,13,-1,-1,-1}, - - .RESET_VAL = 0x175C, - .RESET_REG = {30,0}, - .MODE_VAL = 0x175C, - .MODE_REG = {29,31}, - - .ROUTER_CONTROL_REG = {30,9}, - .ROUTER_EN_BIT = 3, - .NUMLAN_GROUPS_MAX = 8, - .NUMLAN_GROUPS_BIT = 0, // {0-2} - - .VLAN_CONTROL_REG = {30,9}, - .TAG_VLAN_BIT = 7, - - .NUM_PORTS = 6, - .CPU_PORT = 5, - - .MII_REGISTER_EN = NOTSUPPORTED, - - .update_state = ip175c_update_state, - .set_vlan_mode = ip175c_set_vlan_mode, - .reset = ip175c_reset, -}; - -static const struct register_mappings IP175A = { - .NAME = "IP175A", - .MODEL_NO = 0x05, - .VLAN_DEFAULT_TAG_REG = { - {0,24},{0,25},{0,26},{0,27},{0,28},NOTSUPPORTED, - NOTSUPPORTED,NOTSUPPORTED,NOTSUPPORTED - }, - - .ADD_TAG_REG = {0,23}, - .REMOVE_TAG_REG = {0,23}, - .ADD_TAG_BIT = {11,12,13,14,15,-1,-1,-1,-1}, - .REMOVE_TAG_BIT = {6,7,8,9,10,-1,-1,-1,-1}, - - .SIMPLE_VLAN_REGISTERS = 0, - - // Only programmable via EEPROM - .VLAN_LOOKUP_REG = NOTSUPPORTED,// +N/2 - .VLAN_LOOKUP_REG_5 = NOTSUPPORTED, - .VLAN_LOOKUP_EVEN_BIT = {8,9,10,11,12,-1,-1,-1,-1}, - .VLAN_LOOKUP_ODD_BIT = {0,1,2,3,4,-1,-1,-1,-1}, - - .TAG_VLAN_MASK_REG = NOTSUPPORTED, // +N/2, - .TAG_VLAN_MASK_EVEN_BIT = {-1,-1,-1,-1,-1,-1,-1,-1,-1}, - .TAG_VLAN_MASK_ODD_BIT = {-1,-1,-1,-1,-1,-1,-1,-1,-1}, - - .RESET_VAL = -1, - .RESET_REG = NOTSUPPORTED, - .MODE_VAL = 0, - .MODE_REG = NOTSUPPORTED, - - .ROUTER_CONTROL_REG = NOTSUPPORTED, - .VLAN_CONTROL_REG = NOTSUPPORTED, - .TAG_VLAN_BIT = -1, - .ROUTER_EN_BIT = -1, - .NUMLAN_GROUPS_MAX = -1, - .NUMLAN_GROUPS_BIT = -1, // {0-2} - - .NUM_PORTS = 5, - .CPU_PORT = 4, - - .MII_REGISTER_EN = {0, 18}, - .MII_REGISTER_EN_BIT = 7, - - .update_state = ip175c_update_state, - .set_vlan_mode = ip175c_set_vlan_mode, - .reset = ip175c_reset, -}; - - -static int ip175d_update_state(struct ip17xx_state *state); -static int ip175d_set_vlan_mode(struct ip17xx_state *state); -static int ip175d_reset(struct ip17xx_state *state); - -static const struct register_mappings IP175D = { - .NAME = "IP175D", - .MODEL_NO = 0x18, - - // The IP175D has a completely different interface, so we leave most - // of the registers undefined and switch to different code paths. - - .VLAN_DEFAULT_TAG_REG = { - NOTSUPPORTED,NOTSUPPORTED,NOTSUPPORTED,NOTSUPPORTED, - NOTSUPPORTED,NOTSUPPORTED,NOTSUPPORTED,NOTSUPPORTED, - }, - - .ADD_TAG_REG = NOTSUPPORTED, - .REMOVE_TAG_REG = NOTSUPPORTED, - - .SIMPLE_VLAN_REGISTERS = 0, - - .VLAN_LOOKUP_REG = NOTSUPPORTED, - .VLAN_LOOKUP_REG_5 = NOTSUPPORTED, - .TAG_VLAN_MASK_REG = NOTSUPPORTED, - - .RESET_VAL = 0x175D, - .RESET_REG = {20,2}, - .MODE_REG = NOTSUPPORTED, - - .ROUTER_CONTROL_REG = NOTSUPPORTED, - .ROUTER_EN_BIT = -1, - .NUMLAN_GROUPS_BIT = -1, - - .VLAN_CONTROL_REG = NOTSUPPORTED, - .TAG_VLAN_BIT = -1, - - .NUM_PORTS = 6, - .CPU_PORT = 5, - - .MII_REGISTER_EN = NOTSUPPORTED, - - .update_state = ip175d_update_state, - .set_vlan_mode = ip175d_set_vlan_mode, - .reset = ip175d_reset, -}; - -struct ip17xx_state { - struct switch_dev dev; - struct mii_bus *mii_bus; - bool registered; - - int router_mode; // ROUTER_EN - int vlan_enabled; // TAG_VLAN_EN - struct port_state { - u16 pvid; - unsigned int shareports; - } ports[MAX_PORTS]; - unsigned int add_tag; - unsigned int remove_tag; - int num_vlans; - struct vlan_state { - unsigned int ports; - unsigned int tag; // VLAN tag (IP175D only) - } vlans[MAX_VLANS]; - const struct register_mappings *regs; - reg proc_mii; // phy/reg for the low level register access via swconfig - - char buf[80]; -}; - -#define get_state(_dev) container_of((_dev), struct ip17xx_state, dev) - -static int ip_phy_read(struct ip17xx_state *state, int port, int reg) -{ - int val = mdiobus_read(state->mii_bus, port, reg); - if (val < 0) - pr_warn("IP17xx: Unable to get MII register %d,%d: error %d\n", port, reg, -val); -#ifdef DUMP_MII_IO - else - pr_debug("IP17xx: Read MII(%d,%d) -> %04x\n", port, reg, val); -#endif - return val; -} - -static int ip_phy_write(struct ip17xx_state *state, int port, int reg, u16 val) -{ - int err; - -#ifdef DUMP_MII_IO - pr_debug("IP17xx: Write MII(%d,%d) <- %04x\n", port, reg, val); -#endif - err = mdiobus_write(state->mii_bus, port, reg, val); - if (err < 0) - pr_warn("IP17xx: Unable to write MII register %d,%d: error %d\n", port, reg, -err); - return err; -} - -static int ip_phy_write_masked(struct ip17xx_state *state, int port, int reg, unsigned int mask, unsigned int data) -{ - int val = ip_phy_read(state, port, reg); - if (val < 0) - return 0; - return ip_phy_write(state, port, reg, (val & ~mask) | data); -} - -static int getPhy(struct ip17xx_state *state, reg mii) -{ - if (!REG_SUPP(mii)) - return -EFAULT; - return ip_phy_read(state, mii.p, mii.m); -} - -static int setPhy(struct ip17xx_state *state, reg mii, u16 value) -{ - int err; - - if (!REG_SUPP(mii)) - return -EFAULT; - err = ip_phy_write(state, mii.p, mii.m, value); - if (err < 0) - return err; - mdelay(2); - getPhy(state, mii); - return 0; -} - - -/** - * These two macros are to simplify the mapping of logical bits to the bits in hardware. - * NOTE: these macros will return if there is an error! - */ - -#define GET_PORT_BITS(state, bits, addr, bit_lookup) \ - do { \ - int i, val = getPhy((state), (addr)); \ - if (val < 0) \ - return val; \ - (bits) = 0; \ - for (i = 0; i < MAX_PORTS; i++) { \ - if ((bit_lookup)[i] == -1) continue; \ - if (val & (1<<(bit_lookup)[i])) \ - (bits) |= (1<>i)<<(bit_lookup)[i]); \ - } \ - val = setPhy((state), (addr), val); \ - if (val < 0) \ - return val; \ - } while (0) - - -static int get_model(struct ip17xx_state *state) -{ - int id1, id2; - int oui_id, model_no, rev_no, chip_no; - - id1 = ip_phy_read(state, 0, 2); - id2 = ip_phy_read(state, 0, 3); - oui_id = (id1 << 6) | ((id2 >> 10) & 0x3f); - model_no = (id2 >> 4) & 0x3f; - rev_no = id2 & 0xf; - pr_debug("IP17xx: Identified oui=%06x model=%02x rev=%X\n", oui_id, model_no, rev_no); - - if (oui_id != 0x0090c3) // No other oui_id should have reached us anyway - return -ENODEV; - - if (model_no == IP175A.MODEL_NO) { - state->regs = &IP175A; - } else if (model_no == IP175C.MODEL_NO) { - /* - * Several models share the same model_no: - * 178C has more PHYs, so we try whether the device responds to a read from PHY5 - * 175D has a new chip ID register - * 175C has neither - */ - if (ip_phy_read(state, 5, 2) == 0x0243) { - state->regs = &IP178C; - } else { - chip_no = ip_phy_read(state, 20, 0); - pr_debug("IP17xx: Chip ID register reads %04x\n", chip_no); - if (chip_no == 0x175d) { - state->regs = &IP175D; - } else { - state->regs = &IP175C; - } - } - } else { - pr_warn("IP17xx: Found an unknown IC+ switch with model number %02x, revision %X.\n", model_no, rev_no); - return -EPERM; - } - return 0; -} - -/*** Low-level functions for the older models ***/ - -/** Only set vlan and router flags in the switch **/ -static int ip175c_set_flags(struct ip17xx_state *state) -{ - int val; - - if (!REG_SUPP(state->regs->ROUTER_CONTROL_REG)) { - return 0; - } - - val = getPhy(state, state->regs->ROUTER_CONTROL_REG); - if (val < 0) { - return val; - } - if (state->regs->ROUTER_EN_BIT >= 0) { - if (state->router_mode) { - val |= (1<regs->ROUTER_EN_BIT); - } else { - val &= (~(1<regs->ROUTER_EN_BIT)); - } - } - if (state->regs->TAG_VLAN_BIT >= 0) { - if (state->vlan_enabled) { - val |= (1<regs->TAG_VLAN_BIT); - } else { - val &= (~(1<regs->TAG_VLAN_BIT)); - } - } - if (state->regs->NUMLAN_GROUPS_BIT >= 0) { - val &= (~((state->regs->NUMLAN_GROUPS_MAX-1)<regs->NUMLAN_GROUPS_BIT)); - if (state->num_vlans > state->regs->NUMLAN_GROUPS_MAX) { - val |= state->regs->NUMLAN_GROUPS_MAX << state->regs->NUMLAN_GROUPS_BIT; - } else if (state->num_vlans >= 1) { - val |= (state->num_vlans-1) << state->regs->NUMLAN_GROUPS_BIT; - } - } - return setPhy(state, state->regs->ROUTER_CONTROL_REG, val); -} - -/** Set all VLAN and port state. Usually you should call "correct_vlan_state" first. **/ -static int ip175c_set_state(struct ip17xx_state *state) -{ - int j; - int i; - SET_PORT_BITS(state, state->add_tag, - state->regs->ADD_TAG_REG, state->regs->ADD_TAG_BIT); - SET_PORT_BITS(state, state->remove_tag, - state->regs->REMOVE_TAG_REG, state->regs->REMOVE_TAG_BIT); - - if (REG_SUPP(state->regs->VLAN_LOOKUP_REG)) { - for (j=0; jregs->NUM_PORTS; j++) { - reg addr; - const bitnum *bit_lookup = (j%2==0)? - state->regs->VLAN_LOOKUP_EVEN_BIT: - state->regs->VLAN_LOOKUP_ODD_BIT; - - addr = state->regs->VLAN_LOOKUP_REG; - if (state->regs->SIMPLE_VLAN_REGISTERS) { - addr.m += j; - } else { - switch (j) { - case 0: - case 1: - break; - case 2: - case 3: - addr.m+=1; - break; - case 4: - addr.m+=2; - break; - case 5: - addr = state->regs->VLAN_LOOKUP_REG_5; - break; - default: - addr.m = -1; // shouldn't get here, but... - break; - } - } - //printf("shareports for %d is %02X\n",j,state->ports[j].shareports); - if (REG_SUPP(addr)) { - SET_PORT_BITS(state, state->ports[j].shareports, addr, bit_lookup); - } - } - } - if (REG_SUPP(state->regs->TAG_VLAN_MASK_REG)) { - for (j=0; jregs->TAG_VLAN_MASK_REG; - const bitnum *bit_lookup = (j%2==0)? - state->regs->TAG_VLAN_MASK_EVEN_BIT: - state->regs->TAG_VLAN_MASK_ODD_BIT; - unsigned int vlan_mask; - if (state->regs->SIMPLE_VLAN_REGISTERS) { - addr.m += j; - } else { - addr.m += j/2; - } - vlan_mask = state->vlans[j].ports; - SET_PORT_BITS(state, vlan_mask, addr, bit_lookup); - } - } - - for (i=0; iregs->VLAN_DEFAULT_TAG_REG[i])) { - int err = setPhy(state, state->regs->VLAN_DEFAULT_TAG_REG[i], - state->ports[i].pvid); - if (err < 0) { - return err; - } - } - } - - return ip175c_set_flags(state); -} - -/** - * Uses only the VLAN port mask and the add tag mask to generate the other fields: - * which ports are part of the same VLAN, removing vlan tags, and VLAN tag ids. - */ -static void ip175c_correct_vlan_state(struct ip17xx_state *state) -{ - int i, j; - state->num_vlans = 0; - for (i=0; ivlans[i].ports != 0) { - state->num_vlans = i+1; // Hack -- we need to store the "set" vlans somewhere... - } - } - - for (i=0; iregs->NUM_PORTS; i++) { - unsigned int portmask = (1<vlan_enabled) { - // Share with everybody! - state->ports[i].shareports = (1<regs->NUM_PORTS)-1; - continue; - } - state->ports[i].shareports = portmask; - for (j=0; jvlans[j].ports & portmask) - state->ports[i].shareports |= state->vlans[j].ports; - } - } -} - -static int ip175c_update_state(struct ip17xx_state *state) -{ - ip175c_correct_vlan_state(state); - return ip175c_set_state(state); -} - -static int ip175c_set_vlan_mode(struct ip17xx_state *state) -{ - return ip175c_update_state(state); -} - -static int ip175c_reset(struct ip17xx_state *state) -{ - int err; - - if (REG_SUPP(state->regs->MODE_REG)) { - err = setPhy(state, state->regs->MODE_REG, state->regs->MODE_VAL); - if (err < 0) - return err; - err = getPhy(state, state->regs->MODE_REG); - if (err < 0) - return err; - } - - return ip175c_update_state(state); -} - -/*** Low-level functions for IP175D ***/ - -static int ip175d_update_state(struct ip17xx_state *state) -{ - unsigned int filter_mask = 0; - unsigned int ports[16], add[16], rem[16]; - int i, j; - int err = 0; - - for (i = 0; i < 16; i++) { - ports[i] = 0; - add[i] = 0; - rem[i] = 0; - if (!state->vlan_enabled) { - err |= ip_phy_write(state, 22, 14+i, i+1); // default tags - ports[i] = 0x3f; - continue; - } - if (!state->vlans[i].tag) { - // Reset the filter - err |= ip_phy_write(state, 22, 14+i, 0); // tag - continue; - } - filter_mask |= 1 << i; - err |= ip_phy_write(state, 22, 14+i, state->vlans[i].tag); - ports[i] = state->vlans[i].ports; - for (j = 0; j < 6; j++) { - if (ports[i] & (1 << j)) { - if (state->add_tag & (1 << j)) - add[i] |= 1 << j; - if (state->remove_tag & (1 << j)) - rem[i] |= 1 << j; - } - } - } - - // Port masks, tag adds and removals - for (i = 0; i < 8; i++) { - err |= ip_phy_write(state, 23, i, ports[2*i] | (ports[2*i+1] << 8)); - err |= ip_phy_write(state, 23, 8+i, add[2*i] | (add[2*i+1] << 8)); - err |= ip_phy_write(state, 23, 16+i, rem[2*i] | (rem[2*i+1] << 8)); - } - err |= ip_phy_write(state, 22, 10, filter_mask); - - // Default VLAN tag for each port - for (i = 0; i < 6; i++) - err |= ip_phy_write(state, 22, 4+i, state->vlans[state->ports[i].pvid].tag); - - return (err ? -EIO : 0); -} - -static int ip175d_set_vlan_mode(struct ip17xx_state *state) -{ - int i; - int err = 0; - - if (state->vlan_enabled) { - // VLAN classification rules: tag-based VLANs, use VID to classify, - // drop packets that cannot be classified. - err |= ip_phy_write_masked(state, 22, 0, 0x3fff, 0x003f); - - // Ingress rules: CFI=1 dropped, null VID is untagged, VID=1 passed, - // VID=0xfff discarded, admin both tagged and untagged, ingress - // filters enabled. - err |= ip_phy_write_masked(state, 22, 1, 0x0fff, 0x0c3f); - - // Egress rules: IGMP processing off, keep VLAN header off - err |= ip_phy_write_masked(state, 22, 2, 0x0fff, 0x0000); - } else { - // VLAN classification rules: everything off & clear table - err |= ip_phy_write_masked(state, 22, 0, 0xbfff, 0x8000); - - // Ingress and egress rules: set to defaults - err |= ip_phy_write_masked(state, 22, 1, 0x0fff, 0x0c3f); - err |= ip_phy_write_masked(state, 22, 2, 0x0fff, 0x0000); - } - - // Reset default VLAN for each port to 0 - for (i = 0; i < 6; i++) - state->ports[i].pvid = 0; - - err |= ip175d_update_state(state); - - return (err ? -EIO : 0); -} - -static int ip175d_reset(struct ip17xx_state *state) -{ - int err = 0; - - // Disable the special tagging mode - err |= ip_phy_write_masked(state, 21, 22, 0x0003, 0x0000); - - // Set 802.1q protocol type - err |= ip_phy_write(state, 22, 3, 0x8100); - - state->vlan_enabled = 0; - err |= ip175d_set_vlan_mode(state); - - return (err ? -EIO : 0); -} - -/*** High-level functions ***/ - -static int ip17xx_get_enable_vlan(struct switch_dev *dev, const struct switch_attr *attr, struct switch_val *val) -{ - struct ip17xx_state *state = get_state(dev); - - val->value.i = state->vlan_enabled; - return 0; -} - -static void ip17xx_reset_vlan_config(struct ip17xx_state *state) -{ - int i; - - state->remove_tag = (state->vlan_enabled ? ((1<regs->NUM_PORTS)-1) : 0x0000); - state->add_tag = 0x0000; - for (i = 0; i < MAX_VLANS; i++) { - state->vlans[i].ports = 0x0000; - state->vlans[i].tag = (i ? i : 16); - } - for (i = 0; i < MAX_PORTS; i++) - state->ports[i].pvid = 0; -} - -static int ip17xx_set_enable_vlan(struct switch_dev *dev, const struct switch_attr *attr, struct switch_val *val) -{ - struct ip17xx_state *state = get_state(dev); - int enable; - - enable = val->value.i; - if (state->vlan_enabled == enable) { - // Do not change any state. - return 0; - } - state->vlan_enabled = enable; - - // Otherwise, if we are switching state, set fields to a known default. - ip17xx_reset_vlan_config(state); - - return state->regs->set_vlan_mode(state); -} - -static int ip17xx_get_ports(struct switch_dev *dev, struct switch_val *val) -{ - struct ip17xx_state *state = get_state(dev); - int b; - int ind; - unsigned int ports; - - if (val->port_vlan >= dev->vlans || val->port_vlan < 0) - return -EINVAL; - - ports = state->vlans[val->port_vlan].ports; - b = 0; - ind = 0; - while (b < MAX_PORTS) { - if (ports&1) { - int istagged = ((state->add_tag >> b) & 1); - val->value.ports[ind].id = b; - val->value.ports[ind].flags = (istagged << SWITCH_PORT_FLAG_TAGGED); - ind++; - } - b++; - ports >>= 1; - } - val->len = ind; - - return 0; -} - -static int ip17xx_set_ports(struct switch_dev *dev, struct switch_val *val) -{ - struct ip17xx_state *state = get_state(dev); - int i; - - if (val->port_vlan >= dev->vlans || val->port_vlan < 0) - return -EINVAL; - - state->vlans[val->port_vlan].ports = 0; - for (i = 0; i < val->len; i++) { - unsigned int bitmask = (1<value.ports[i].id); - state->vlans[val->port_vlan].ports |= bitmask; - if (val->value.ports[i].flags & (1<add_tag |= bitmask; - state->remove_tag &= (~bitmask); - } else { - state->add_tag &= (~bitmask); - state->remove_tag |= bitmask; - } - } - - return state->regs->update_state(state); -} - -static int ip17xx_apply(struct switch_dev *dev) -{ - struct ip17xx_state *state = get_state(dev); - - if (REG_SUPP(state->regs->MII_REGISTER_EN)) { - int val = getPhy(state, state->regs->MII_REGISTER_EN); - if (val < 0) { - return val; - } - val |= (1<regs->MII_REGISTER_EN_BIT); - return setPhy(state, state->regs->MII_REGISTER_EN, val); - } - return 0; -} - -static int ip17xx_reset(struct switch_dev *dev) -{ - struct ip17xx_state *state = get_state(dev); - int i, err; - - if (REG_SUPP(state->regs->RESET_REG)) { - err = setPhy(state, state->regs->RESET_REG, state->regs->RESET_VAL); - if (err < 0) - return err; - err = getPhy(state, state->regs->RESET_REG); - - /* - * Data sheet specifies reset period to be 2 msec. - * (I don't see any mention of the 2ms delay in the IP178C spec, only - * in IP175C, but it can't hurt.) - */ - mdelay(2); - } - - /* reset switch ports */ - for (i = 0; i < state->regs->NUM_PORTS-1; i++) { - err = ip_phy_write(state, i, MII_BMCR, BMCR_RESET); - if (err < 0) - return err; - } - - state->router_mode = 0; - state->vlan_enabled = 0; - ip17xx_reset_vlan_config(state); - - return state->regs->reset(state); -} - -static int ip17xx_get_tagged(struct switch_dev *dev, const struct switch_attr *attr, struct switch_val *val) -{ - struct ip17xx_state *state = get_state(dev); - - if (state->add_tag & (1<port_vlan)) { - if (state->remove_tag & (1<port_vlan)) - val->value.i = 3; // shouldn't ever happen. - else - val->value.i = 1; - } else { - if (state->remove_tag & (1<port_vlan)) - val->value.i = 0; - else - val->value.i = 2; - } - return 0; -} - -static int ip17xx_set_tagged(struct switch_dev *dev, const struct switch_attr *attr, struct switch_val *val) -{ - struct ip17xx_state *state = get_state(dev); - - state->add_tag &= ~(1<port_vlan); - state->remove_tag &= ~(1<port_vlan); - - if (val->value.i == 0) - state->remove_tag |= (1<port_vlan); - if (val->value.i == 1) - state->add_tag |= (1<port_vlan); - - return state->regs->update_state(state); -} - -/** Get the current phy address */ -static int ip17xx_get_phy(struct switch_dev *dev, const struct switch_attr *attr, struct switch_val *val) -{ - struct ip17xx_state *state = get_state(dev); - - val->value.i = state->proc_mii.p; - return 0; -} - -/** Set a new phy address for low level access to registers */ -static int ip17xx_set_phy(struct switch_dev *dev, const struct switch_attr *attr, struct switch_val *val) -{ - struct ip17xx_state *state = get_state(dev); - int new_reg = val->value.i; - - if (new_reg < 0 || new_reg > 31) - state->proc_mii.p = (u16)-1; - else - state->proc_mii.p = (u16)new_reg; - return 0; -} - -/** Get the current register number */ -static int ip17xx_get_reg(struct switch_dev *dev, const struct switch_attr *attr, struct switch_val *val) -{ - struct ip17xx_state *state = get_state(dev); - - val->value.i = state->proc_mii.m; - return 0; -} - -/** Set a new register address for low level access to registers */ -static int ip17xx_set_reg(struct switch_dev *dev, const struct switch_attr *attr, struct switch_val *val) -{ - struct ip17xx_state *state = get_state(dev); - int new_reg = val->value.i; - - if (new_reg < 0 || new_reg > 31) - state->proc_mii.m = (u16)-1; - else - state->proc_mii.m = (u16)new_reg; - return 0; -} - -/** Get the register content of state->proc_mii */ -static int ip17xx_get_val(struct switch_dev *dev, const struct switch_attr *attr, struct switch_val *val) -{ - struct ip17xx_state *state = get_state(dev); - int retval = -EINVAL; - if (REG_SUPP(state->proc_mii)) - retval = getPhy(state, state->proc_mii); - - if (retval < 0) { - return retval; - } else { - val->value.i = retval; - return 0; - } -} - -/** Write a value to the register defined by phy/reg above */ -static int ip17xx_set_val(struct switch_dev *dev, const struct switch_attr *attr, struct switch_val *val) -{ - struct ip17xx_state *state = get_state(dev); - int myval, err = -EINVAL; - - myval = val->value.i; - if (myval <= 0xffff && myval >= 0 && REG_SUPP(state->proc_mii)) { - err = setPhy(state, state->proc_mii, (u16)myval); - } - return err; -} - -static int ip17xx_read_name(struct switch_dev *dev, const struct switch_attr *attr, struct switch_val *val) -{ - struct ip17xx_state *state = get_state(dev); - val->value.s = state->regs->NAME; // Just a const pointer, won't be freed by swconfig. - return 0; -} - -static int ip17xx_get_tag(struct switch_dev *dev, const struct switch_attr *attr, struct switch_val *val) -{ - struct ip17xx_state *state = get_state(dev); - int vlan = val->port_vlan; - - if (vlan < 0 || vlan >= MAX_VLANS) - return -EINVAL; - - val->value.i = state->vlans[vlan].tag; - return 0; -} - -static int ip17xx_set_tag(struct switch_dev *dev, const struct switch_attr *attr, struct switch_val *val) -{ - struct ip17xx_state *state = get_state(dev); - int vlan = val->port_vlan; - int tag = val->value.i; - - if (vlan < 0 || vlan >= MAX_VLANS) - return -EINVAL; - - if (tag < 0 || tag > 4095) - return -EINVAL; - - state->vlans[vlan].tag = tag; - return state->regs->update_state(state); -} - -static int ip17xx_set_port_speed(struct switch_dev *dev, const struct switch_attr *attr, struct switch_val *val) -{ - struct ip17xx_state *state = get_state(dev); - int nr = val->port_vlan; - int ctrl; - int autoneg; - int speed; - if (val->value.i == 100) { - speed = 1; - autoneg = 0; - } else if (val->value.i == 10) { - speed = 0; - autoneg = 0; - } else { - autoneg = 1; - speed = 1; - } - - /* Can't set speed for cpu port */ - if (nr == state->regs->CPU_PORT) - return -EINVAL; - - if (nr >= dev->ports || nr < 0) - return -EINVAL; - - ctrl = ip_phy_read(state, nr, 0); - if (ctrl < 0) - return -EIO; - - ctrl &= (~(1<<12)); - ctrl &= (~(1<<13)); - ctrl |= (autoneg<<12); - ctrl |= (speed<<13); - - return ip_phy_write(state, nr, 0, ctrl); -} - -static int ip17xx_get_port_speed(struct switch_dev *dev, const struct switch_attr *attr, struct switch_val *val) -{ - struct ip17xx_state *state = get_state(dev); - int nr = val->port_vlan; - int speed, status; - - if (nr == state->regs->CPU_PORT) { - val->value.i = 100; - return 0; - } - - if (nr >= dev->ports || nr < 0) - return -EINVAL; - - status = ip_phy_read(state, nr, 1); - speed = ip_phy_read(state, nr, 18); - if (status < 0 || speed < 0) - return -EIO; - - if (status & 4) - val->value.i = ((speed & (1<<11)) ? 100 : 10); - else - val->value.i = 0; - - return 0; -} - -static int ip17xx_get_port_status(struct switch_dev *dev, const struct switch_attr *attr, struct switch_val *val) -{ - struct ip17xx_state *state = get_state(dev); - int ctrl, speed, status; - int nr = val->port_vlan; - int len; - char *buf = state->buf; // fixed-length at 80. - - if (nr == state->regs->CPU_PORT) { - sprintf(buf, "up, 100 Mbps, cpu port"); - val->value.s = buf; - return 0; - } - - if (nr >= dev->ports || nr < 0) - return -EINVAL; - - ctrl = ip_phy_read(state, nr, 0); - status = ip_phy_read(state, nr, 1); - speed = ip_phy_read(state, nr, 18); - if (ctrl < 0 || status < 0 || speed < 0) - return -EIO; - - if (status & 4) - len = sprintf(buf, "up, %d Mbps, %s duplex", - ((speed & (1<<11)) ? 100 : 10), - ((speed & (1<<10)) ? "full" : "half")); - else - len = sprintf(buf, "down"); - - if (ctrl & (1<<12)) { - len += sprintf(buf+len, ", auto-negotiate"); - if (!(status & (1<<5))) - len += sprintf(buf+len, " (in progress)"); - } else { - len += sprintf(buf+len, ", fixed speed (%d)", - ((ctrl & (1<<13)) ? 100 : 10)); - } - - buf[len] = '\0'; - val->value.s = buf; - return 0; -} - -static int ip17xx_get_pvid(struct switch_dev *dev, int port, int *val) -{ - struct ip17xx_state *state = get_state(dev); - - *val = state->ports[port].pvid; - return 0; -} - -static int ip17xx_set_pvid(struct switch_dev *dev, int port, int val) -{ - struct ip17xx_state *state = get_state(dev); - - if (val < 0 || val >= MAX_VLANS) - return -EINVAL; - - state->ports[port].pvid = val; - return state->regs->update_state(state); -} - - -enum Ports { - IP17XX_PORT_STATUS, - IP17XX_PORT_LINK, - IP17XX_PORT_TAGGED, - IP17XX_PORT_PVID, -}; - -enum Globals { - IP17XX_ENABLE_VLAN, - IP17XX_GET_NAME, - IP17XX_REGISTER_PHY, - IP17XX_REGISTER_MII, - IP17XX_REGISTER_VALUE, - IP17XX_REGISTER_ERRNO, -}; - -enum Vlans { - IP17XX_VLAN_TAG, -}; - -static const struct switch_attr ip17xx_global[] = { - [IP17XX_ENABLE_VLAN] = { - .id = IP17XX_ENABLE_VLAN, - .type = SWITCH_TYPE_INT, - .name = "enable_vlan", - .description = "Flag to enable or disable VLANs and tagging", - .get = ip17xx_get_enable_vlan, - .set = ip17xx_set_enable_vlan, - }, - [IP17XX_GET_NAME] = { - .id = IP17XX_GET_NAME, - .type = SWITCH_TYPE_STRING, - .description = "Returns the type of IC+ chip.", - .name = "name", - .get = ip17xx_read_name, - .set = NULL, - }, - /* jal: added for low level debugging etc. */ - [IP17XX_REGISTER_PHY] = { - .id = IP17XX_REGISTER_PHY, - .type = SWITCH_TYPE_INT, - .description = "Direct register access: set PHY (0-4, or 29,30,31)", - .name = "phy", - .get = ip17xx_get_phy, - .set = ip17xx_set_phy, - }, - [IP17XX_REGISTER_MII] = { - .id = IP17XX_REGISTER_MII, - .type = SWITCH_TYPE_INT, - .description = "Direct register access: set MII register number (0-31)", - .name = "reg", - .get = ip17xx_get_reg, - .set = ip17xx_set_reg, - }, - [IP17XX_REGISTER_VALUE] = { - .id = IP17XX_REGISTER_VALUE, - .type = SWITCH_TYPE_INT, - .description = "Direct register access: read/write to register (0-65535)", - .name = "val", - .get = ip17xx_get_val, - .set = ip17xx_set_val, - }, -}; - -static const struct switch_attr ip17xx_vlan[] = { - [IP17XX_VLAN_TAG] = { - .id = IP17XX_VLAN_TAG, - .type = SWITCH_TYPE_INT, - .description = "VLAN ID (0-4095) [IP175D only]", - .name = "vid", - .get = ip17xx_get_tag, - .set = ip17xx_set_tag, - } -}; - -static const struct switch_attr ip17xx_port[] = { - [IP17XX_PORT_STATUS] = { - .id = IP17XX_PORT_STATUS, - .type = SWITCH_TYPE_STRING, - .description = "Returns Detailed port status", - .name = "status", - .get = ip17xx_get_port_status, - .set = NULL, - }, - [IP17XX_PORT_LINK] = { - .id = IP17XX_PORT_LINK, - .type = SWITCH_TYPE_INT, - .description = "Link speed. Can write 0 for auto-negotiate, or 10 or 100", - .name = "link", - .get = ip17xx_get_port_speed, - .set = ip17xx_set_port_speed, - }, - [IP17XX_PORT_TAGGED] = { - .id = IP17XX_PORT_LINK, - .type = SWITCH_TYPE_INT, - .description = "0 = untag, 1 = add tags, 2 = do not alter (This value is reset if vlans are altered)", - .name = "tagged", - .get = ip17xx_get_tagged, - .set = ip17xx_set_tagged, - }, -}; - -static const struct switch_dev_ops ip17xx_ops = { - .attr_global = { - .attr = ip17xx_global, - .n_attr = ARRAY_SIZE(ip17xx_global), - }, - .attr_port = { - .attr = ip17xx_port, - .n_attr = ARRAY_SIZE(ip17xx_port), - }, - .attr_vlan = { - .attr = ip17xx_vlan, - .n_attr = ARRAY_SIZE(ip17xx_vlan), - }, - - .get_port_pvid = ip17xx_get_pvid, - .set_port_pvid = ip17xx_set_pvid, - .get_vlan_ports = ip17xx_get_ports, - .set_vlan_ports = ip17xx_set_ports, - .apply_config = ip17xx_apply, - .reset_switch = ip17xx_reset, -}; - -static int ip17xx_probe(struct phy_device *pdev) -{ - struct ip17xx_state *state; - struct switch_dev *dev; - int err; - - /* We only attach to PHY 0, but use all available PHYs */ - if (pdev->mdio.addr != 0) - return -ENODEV; - - state = kzalloc(sizeof(*state), GFP_KERNEL); - if (!state) - return -ENOMEM; - - dev = &state->dev; - - pdev->priv = state; - state->mii_bus = pdev->mdio.bus; - - err = get_model(state); - if (err < 0) - goto error; - - dev->vlans = MAX_VLANS; - dev->cpu_port = state->regs->CPU_PORT; - dev->ports = state->regs->NUM_PORTS; - dev->name = state->regs->NAME; - dev->ops = &ip17xx_ops; - - pr_info("IP17xx: Found %s at %s\n", dev->name, dev_name(&pdev->mdio.dev)); - return 0; - -error: - kfree(state); - return err; -} - -static int ip17xx_config_init(struct phy_device *pdev) -{ - struct ip17xx_state *state = pdev->priv; - struct net_device *dev = pdev->attached_dev; - int err; - - err = register_switch(&state->dev, dev); - if (err < 0) - return err; - - state->registered = true; - ip17xx_reset(&state->dev); - return 0; -} - -static void ip17xx_remove(struct phy_device *pdev) -{ - struct ip17xx_state *state = pdev->priv; - - if (state->registered) - unregister_switch(&state->dev); - kfree(state); -} - -static int ip17xx_config_aneg(struct phy_device *pdev) -{ - return 0; -} - -static int ip17xx_aneg_done(struct phy_device *pdev) -{ - return 1; /* Return any positive value */ -} - -static int ip17xx_read_status(struct phy_device *pdev) -{ - pdev->speed = SPEED_100; - pdev->duplex = DUPLEX_FULL; - pdev->pause = pdev->asym_pause = 0; - pdev->link = 1; - - return 0; -} - -static struct phy_driver ip17xx_driver[] = { - { - .name = "IC+ IP17xx", - .phy_id = 0x02430c00, - .phy_id_mask = 0x0ffffc00, - .features = PHY_BASIC_FEATURES, - .probe = ip17xx_probe, - .remove = ip17xx_remove, - .config_init = ip17xx_config_init, - .config_aneg = ip17xx_config_aneg, - .aneg_done = ip17xx_aneg_done, - .read_status = ip17xx_read_status, - } -}; - -module_phy_driver(ip17xx_driver); - -MODULE_AUTHOR("Patrick Horn "); -MODULE_AUTHOR("Felix Fietkau "); -MODULE_AUTHOR("Martin Mares "); -MODULE_LICENSE("GPL"); diff --git a/target/linux/generic/files-6.12/drivers/net/phy/psb6970.c b/target/linux/generic/files-6.12/drivers/net/phy/psb6970.c deleted file mode 100644 index 2587b999138474..00000000000000 --- a/target/linux/generic/files-6.12/drivers/net/phy/psb6970.c +++ /dev/null @@ -1,443 +0,0 @@ -/* - * Lantiq PSB6970 (Tantos) Switch driver - * - * Copyright (c) 2009,2010 Team Embedded. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License v2 as published by the - * Free Software Foundation. - * - * The switch programming done in this driver follows the - * "Ethernet Traffic Separation using VLAN" Application Note as - * published by Lantiq. - */ - -#include -#include -#include -#include -#include - -#define PSB6970_MAX_VLANS 16 -#define PSB6970_NUM_PORTS 7 -#define PSB6970_DEFAULT_PORT_CPU 6 -#define PSB6970_IS_CPU_PORT(x) ((x) > 4) - -#define PHYADDR(_reg) ((_reg >> 5) & 0xff), (_reg & 0x1f) - -/* --- Identification --- */ -#define PSB6970_CI0 0x0100 -#define PSB6970_CI0_MASK 0x000f -#define PSB6970_CI1 0x0101 -#define PSB6970_CI1_VAL 0x2599 -#define PSB6970_CI1_MASK 0xffff - -/* --- VLAN filter table --- */ -#define PSB6970_VFxL(i) ((i)*2+0x10) /* VLAN Filter Low */ -#define PSB6970_VFxL_VV (1 << 15) /* VLAN_Valid */ - -#define PSB6970_VFxH(i) ((i)*2+0x11) /* VLAN Filter High */ -#define PSB6970_VFxH_TM_SHIFT 7 /* Tagged Member */ - -/* --- Port registers --- */ -#define PSB6970_EC(p) ((p)*0x20+2) /* Extended Control */ -#define PSB6970_EC_IFNTE (1 << 1) /* Input Force No Tag Enable */ - -#define PSB6970_PBVM(p) ((p)*0x20+3) /* Port Base VLAN Map */ -#define PSB6970_PBVM_VMCE (1 << 8) -#define PSB6970_PBVM_AOVTP (1 << 9) -#define PSB6970_PBVM_VSD (1 << 10) -#define PSB6970_PBVM_VC (1 << 11) /* VID Check with VID table */ -#define PSB6970_PBVM_TBVE (1 << 13) /* Tag-Based VLAN enable */ - -#define PSB6970_DVID(p) ((p)*0x20+4) /* Default VLAN ID & Priority */ - -struct psb6970_priv { - struct switch_dev dev; - struct phy_device *phy; - u16 (*read) (struct phy_device* phydev, int reg); - void (*write) (struct phy_device* phydev, int reg, u16 val); - struct mutex reg_mutex; - - /* all fields below are cleared on reset */ - struct_group(psb6970_priv_volatile, - bool vlan; - u16 vlan_id[PSB6970_MAX_VLANS]; - u8 vlan_table[PSB6970_MAX_VLANS]; - u8 vlan_tagged; - u16 pvid[PSB6970_NUM_PORTS]; - ); -}; - -#define to_psb6970(_dev) container_of(_dev, struct psb6970_priv, dev) - -static u16 psb6970_mii_read(struct phy_device *phydev, int reg) -{ - struct mii_bus *bus = phydev->mdio.bus; - - return bus->read(bus, PHYADDR(reg)); -} - -static void psb6970_mii_write(struct phy_device *phydev, int reg, u16 val) -{ - struct mii_bus *bus = phydev->mdio.bus; - - bus->write(bus, PHYADDR(reg), val); -} - -static int -psb6970_set_vlan(struct switch_dev *dev, const struct switch_attr *attr, - struct switch_val *val) -{ - struct psb6970_priv *priv = to_psb6970(dev); - priv->vlan = !!val->value.i; - return 0; -} - -static int -psb6970_get_vlan(struct switch_dev *dev, const struct switch_attr *attr, - struct switch_val *val) -{ - struct psb6970_priv *priv = to_psb6970(dev); - val->value.i = priv->vlan; - return 0; -} - -static int psb6970_set_pvid(struct switch_dev *dev, int port, int vlan) -{ - struct psb6970_priv *priv = to_psb6970(dev); - - /* make sure no invalid PVIDs get set */ - if (vlan >= dev->vlans) - return -EINVAL; - - priv->pvid[port] = vlan; - return 0; -} - -static int psb6970_get_pvid(struct switch_dev *dev, int port, int *vlan) -{ - struct psb6970_priv *priv = to_psb6970(dev); - *vlan = priv->pvid[port]; - return 0; -} - -static int -psb6970_set_vid(struct switch_dev *dev, const struct switch_attr *attr, - struct switch_val *val) -{ - struct psb6970_priv *priv = to_psb6970(dev); - priv->vlan_id[val->port_vlan] = val->value.i; - return 0; -} - -static int -psb6970_get_vid(struct switch_dev *dev, const struct switch_attr *attr, - struct switch_val *val) -{ - struct psb6970_priv *priv = to_psb6970(dev); - val->value.i = priv->vlan_id[val->port_vlan]; - return 0; -} - -static struct switch_attr psb6970_globals[] = { - { - .type = SWITCH_TYPE_INT, - .name = "enable_vlan", - .description = "Enable VLAN mode", - .set = psb6970_set_vlan, - .get = psb6970_get_vlan, - .max = 1}, -}; - -static struct switch_attr psb6970_port[] = { -}; - -static struct switch_attr psb6970_vlan[] = { - { - .type = SWITCH_TYPE_INT, - .name = "vid", - .description = "VLAN ID (0-4094)", - .set = psb6970_set_vid, - .get = psb6970_get_vid, - .max = 4094, - }, -}; - -static int psb6970_get_ports(struct switch_dev *dev, struct switch_val *val) -{ - struct psb6970_priv *priv = to_psb6970(dev); - u8 ports = priv->vlan_table[val->port_vlan]; - int i; - - val->len = 0; - for (i = 0; i < PSB6970_NUM_PORTS; i++) { - struct switch_port *p; - - if (!(ports & (1 << i))) - continue; - - p = &val->value.ports[val->len++]; - p->id = i; - if (priv->vlan_tagged & (1 << i)) - p->flags = (1 << SWITCH_PORT_FLAG_TAGGED); - else - p->flags = 0; - } - return 0; -} - -static int psb6970_set_ports(struct switch_dev *dev, struct switch_val *val) -{ - struct psb6970_priv *priv = to_psb6970(dev); - u8 *vt = &priv->vlan_table[val->port_vlan]; - int i, j; - - *vt = 0; - for (i = 0; i < val->len; i++) { - struct switch_port *p = &val->value.ports[i]; - - if (p->flags & (1 << SWITCH_PORT_FLAG_TAGGED)) - priv->vlan_tagged |= (1 << p->id); - else { - priv->vlan_tagged &= ~(1 << p->id); - priv->pvid[p->id] = val->port_vlan; - - /* make sure that an untagged port does not - * appear in other vlans */ - for (j = 0; j < PSB6970_MAX_VLANS; j++) { - if (j == val->port_vlan) - continue; - priv->vlan_table[j] &= ~(1 << p->id); - } - } - - *vt |= 1 << p->id; - } - return 0; -} - -static int psb6970_hw_apply(struct switch_dev *dev) -{ - struct psb6970_priv *priv = to_psb6970(dev); - int i, j; - - mutex_lock(&priv->reg_mutex); - - if (priv->vlan) { - /* into the vlan translation unit */ - for (j = 0; j < PSB6970_MAX_VLANS; j++) { - u8 vp = priv->vlan_table[j]; - - if (vp) { - priv->write(priv->phy, PSB6970_VFxL(j), - PSB6970_VFxL_VV | priv->vlan_id[j]); - priv->write(priv->phy, PSB6970_VFxH(j), - ((vp & priv-> - vlan_tagged) << - PSB6970_VFxH_TM_SHIFT) | vp); - } else /* clear VLAN Valid flag for unused vlans */ - priv->write(priv->phy, PSB6970_VFxL(j), 0); - - } - } - - /* update the port destination mask registers and tag settings */ - for (i = 0; i < PSB6970_NUM_PORTS; i++) { - int dvid = 1, pbvm = 0x7f | PSB6970_PBVM_VSD, ec = 0; - - if (priv->vlan) { - ec = PSB6970_EC_IFNTE; - dvid = priv->vlan_id[priv->pvid[i]]; - pbvm |= PSB6970_PBVM_TBVE | PSB6970_PBVM_VMCE; - - if ((i << 1) & priv->vlan_tagged) - pbvm |= PSB6970_PBVM_AOVTP | PSB6970_PBVM_VC; - } - - priv->write(priv->phy, PSB6970_PBVM(i), pbvm); - - if (!PSB6970_IS_CPU_PORT(i)) { - priv->write(priv->phy, PSB6970_EC(i), ec); - priv->write(priv->phy, PSB6970_DVID(i), dvid); - } - } - - mutex_unlock(&priv->reg_mutex); - return 0; -} - -static int psb6970_reset_switch(struct switch_dev *dev) -{ - struct psb6970_priv *priv = to_psb6970(dev); - int i; - - mutex_lock(&priv->reg_mutex); - - memset(&priv->psb6970_priv_volatile, 0, - sizeof(priv->psb6970_priv_volatile)); - - for (i = 0; i < PSB6970_MAX_VLANS; i++) - priv->vlan_id[i] = i; - - mutex_unlock(&priv->reg_mutex); - - return psb6970_hw_apply(dev); -} - -static const struct switch_dev_ops psb6970_ops = { - .attr_global = { - .attr = psb6970_globals, - .n_attr = ARRAY_SIZE(psb6970_globals), - }, - .attr_port = { - .attr = psb6970_port, - .n_attr = ARRAY_SIZE(psb6970_port), - }, - .attr_vlan = { - .attr = psb6970_vlan, - .n_attr = ARRAY_SIZE(psb6970_vlan), - }, - .get_port_pvid = psb6970_get_pvid, - .set_port_pvid = psb6970_set_pvid, - .get_vlan_ports = psb6970_get_ports, - .set_vlan_ports = psb6970_set_ports, - .apply_config = psb6970_hw_apply, - .reset_switch = psb6970_reset_switch, -}; - -static int psb6970_config_init(struct phy_device *pdev) -{ - struct psb6970_priv *priv; - struct switch_dev *swdev; - int ret; - - priv = kzalloc(sizeof(struct psb6970_priv), GFP_KERNEL); - if (priv == NULL) - return -ENOMEM; - - priv->phy = pdev; - - if (pdev->mdio.addr == 0) - printk(KERN_INFO "%s: psb6970 switch driver attached.\n", - pdev->attached_dev->name); - - if (pdev->mdio.addr != 0) { - kfree(priv); - return 0; - } - - linkmode_zero(pdev->supported); - linkmode_set_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT, pdev->supported); - linkmode_copy(pdev->advertising, pdev->supported); - - mutex_init(&priv->reg_mutex); - priv->read = psb6970_mii_read; - priv->write = psb6970_mii_write; - - pdev->priv = priv; - - swdev = &priv->dev; - swdev->cpu_port = PSB6970_DEFAULT_PORT_CPU; - swdev->ops = &psb6970_ops; - - swdev->name = "Lantiq PSB6970"; - swdev->vlans = PSB6970_MAX_VLANS; - swdev->ports = PSB6970_NUM_PORTS; - - if ((ret = register_switch(&priv->dev, pdev->attached_dev)) < 0) { - kfree(priv); - goto done; - } - - ret = psb6970_reset_switch(&priv->dev); - if (ret) { - kfree(priv); - goto done; - } - -done: - return ret; -} - -static int psb6970_read_status(struct phy_device *phydev) -{ - phydev->speed = SPEED_100; - phydev->duplex = DUPLEX_FULL; - phydev->link = 1; - - phydev->state = PHY_RUNNING; - netif_carrier_on(phydev->attached_dev); - phydev->adjust_link(phydev->attached_dev); - - return 0; -} - -static int psb6970_config_aneg(struct phy_device *phydev) -{ - return 0; -} - -static int psb6970_probe(struct phy_device *pdev) -{ - return 0; -} - -static void psb6970_remove(struct phy_device *pdev) -{ - struct psb6970_priv *priv = pdev->priv; - - if (!priv) - return; - - if (pdev->mdio.addr == 0) - unregister_switch(&priv->dev); - kfree(priv); -} - -static int psb6970_fixup(struct phy_device *dev) -{ - struct mii_bus *bus = dev->mdio.bus; - u16 reg; - - /* look for the switch on the bus */ - reg = bus->read(bus, PHYADDR(PSB6970_CI1)) & PSB6970_CI1_MASK; - if (reg != PSB6970_CI1_VAL) - return 0; - - dev->phy_id = (reg << 16); - dev->phy_id |= bus->read(bus, PHYADDR(PSB6970_CI0)) & PSB6970_CI0_MASK; - - return 0; -} - -static struct phy_driver psb6970_driver = { - .name = "Lantiq PSB6970", - .phy_id = PSB6970_CI1_VAL << 16, - .phy_id_mask = 0xffff0000, - .features = PHY_BASIC_FEATURES, - .probe = psb6970_probe, - .remove = psb6970_remove, - .config_init = &psb6970_config_init, - .config_aneg = &psb6970_config_aneg, - .read_status = &psb6970_read_status, -}; - -int __init psb6970_init(void) -{ - phy_register_fixup_for_id(PHY_ANY_ID, psb6970_fixup); - return phy_driver_register(&psb6970_driver, THIS_MODULE); -} - -module_init(psb6970_init); - -void __exit psb6970_exit(void) -{ - phy_driver_unregister(&psb6970_driver); -} - -module_exit(psb6970_exit); - -MODULE_DESCRIPTION("Lantiq PSB6970 Switch"); -MODULE_AUTHOR("Ithamar R. Adema "); -MODULE_LICENSE("GPL"); diff --git a/target/linux/generic/files-6.12/drivers/net/phy/rtl8306.c b/target/linux/generic/files-6.12/drivers/net/phy/rtl8306.c deleted file mode 100644 index 31bc7589c4b193..00000000000000 --- a/target/linux/generic/files-6.12/drivers/net/phy/rtl8306.c +++ /dev/null @@ -1,1063 +0,0 @@ -/* - * rtl8306.c: RTL8306S switch driver - * - * Copyright (C) 2009 Felix Fietkau - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * 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. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -//#define DEBUG 1 - -/* Global (PHY0) */ -#define RTL8306_REG_PAGE 16 -#define RTL8306_REG_PAGE_LO (1 << 15) -#define RTL8306_REG_PAGE_HI (1 << 1) /* inverted */ - -#define RTL8306_NUM_VLANS 16 -#define RTL8306_NUM_PORTS 6 -#define RTL8306_PORT_CPU 5 -#define RTL8306_NUM_PAGES 4 -#define RTL8306_NUM_REGS 32 - -#define RTL_NAME_S "RTL8306S" -#define RTL_NAME_SD "RTL8306SD" -#define RTL_NAME_SDM "RTL8306SDM" -#define RTL_NAME_UNKNOWN "RTL8306(unknown)" - -#define RTL8306_MAGIC 0x8306 - -static LIST_HEAD(phydevs); - -struct rtl_priv { - struct list_head list; - struct switch_dev dev; - int page; - int type; - int do_cpu; - struct mii_bus *bus; - char hwname[sizeof(RTL_NAME_UNKNOWN)]; - bool fixup; -}; - -struct rtl_phyregs { - int nway; - int speed; - int duplex; -}; - -#define to_rtl(_dev) container_of(_dev, struct rtl_priv, dev) - -enum { - RTL_TYPE_S, - RTL_TYPE_SD, - RTL_TYPE_SDM, -}; - -struct rtl_reg { - int page; - int phy; - int reg; - int bits; - int shift; - int inverted; -}; - -#define RTL_VLAN_REGOFS(name) \ - (RTL_REG_VLAN1_##name - RTL_REG_VLAN0_##name) - -#define RTL_PORT_REGOFS(name) \ - (RTL_REG_PORT1_##name - RTL_REG_PORT0_##name) - -#define RTL_PORT_REG(id, reg) \ - (RTL_REG_PORT0_##reg + (id * RTL_PORT_REGOFS(reg))) - -#define RTL_VLAN_REG(id, reg) \ - (RTL_REG_VLAN0_##reg + (id * RTL_VLAN_REGOFS(reg))) - -#define RTL_GLOBAL_REGATTR(reg) \ - .id = RTL_REG_##reg, \ - .type = SWITCH_TYPE_INT, \ - .ofs = 0, \ - .set = rtl_attr_set_int, \ - .get = rtl_attr_get_int - -#define RTL_PORT_REGATTR(reg) \ - .id = RTL_REG_PORT0_##reg, \ - .type = SWITCH_TYPE_INT, \ - .ofs = RTL_PORT_REGOFS(reg), \ - .set = rtl_attr_set_port_int, \ - .get = rtl_attr_get_port_int - -#define RTL_VLAN_REGATTR(reg) \ - .id = RTL_REG_VLAN0_##reg, \ - .type = SWITCH_TYPE_INT, \ - .ofs = RTL_VLAN_REGOFS(reg), \ - .set = rtl_attr_set_vlan_int, \ - .get = rtl_attr_get_vlan_int - -enum rtl_regidx { - RTL_REG_CHIPID, - RTL_REG_CHIPVER, - RTL_REG_CHIPTYPE, - RTL_REG_CPUPORT, - - RTL_REG_EN_CPUPORT, - RTL_REG_EN_TAG_OUT, - RTL_REG_EN_TAG_CLR, - RTL_REG_EN_TAG_IN, - RTL_REG_TRAP_CPU, - RTL_REG_CPU_LINKUP, - RTL_REG_TRUNK_PORTSEL, - RTL_REG_EN_TRUNK, - RTL_REG_RESET, - - RTL_REG_VLAN_ENABLE, - RTL_REG_VLAN_FILTER, - RTL_REG_VLAN_TAG_ONLY, - RTL_REG_VLAN_TAG_AWARE, -#define RTL_VLAN_ENUM(id) \ - RTL_REG_VLAN##id##_VID, \ - RTL_REG_VLAN##id##_PORTMASK - RTL_VLAN_ENUM(0), - RTL_VLAN_ENUM(1), - RTL_VLAN_ENUM(2), - RTL_VLAN_ENUM(3), - RTL_VLAN_ENUM(4), - RTL_VLAN_ENUM(5), - RTL_VLAN_ENUM(6), - RTL_VLAN_ENUM(7), - RTL_VLAN_ENUM(8), - RTL_VLAN_ENUM(9), - RTL_VLAN_ENUM(10), - RTL_VLAN_ENUM(11), - RTL_VLAN_ENUM(12), - RTL_VLAN_ENUM(13), - RTL_VLAN_ENUM(14), - RTL_VLAN_ENUM(15), -#define RTL_PORT_ENUM(id) \ - RTL_REG_PORT##id##_PVID, \ - RTL_REG_PORT##id##_NULL_VID_REPLACE, \ - RTL_REG_PORT##id##_NON_PVID_DISCARD, \ - RTL_REG_PORT##id##_VID_INSERT, \ - RTL_REG_PORT##id##_TAG_INSERT, \ - RTL_REG_PORT##id##_LINK, \ - RTL_REG_PORT##id##_SPEED, \ - RTL_REG_PORT##id##_NWAY, \ - RTL_REG_PORT##id##_NRESTART, \ - RTL_REG_PORT##id##_DUPLEX, \ - RTL_REG_PORT##id##_RXEN, \ - RTL_REG_PORT##id##_TXEN - RTL_PORT_ENUM(0), - RTL_PORT_ENUM(1), - RTL_PORT_ENUM(2), - RTL_PORT_ENUM(3), - RTL_PORT_ENUM(4), - RTL_PORT_ENUM(5), -}; - -static const struct rtl_reg rtl_regs[] = { - [RTL_REG_CHIPID] = { 0, 4, 30, 16, 0, 0 }, - [RTL_REG_CHIPVER] = { 0, 4, 31, 8, 0, 0 }, - [RTL_REG_CHIPTYPE] = { 0, 4, 31, 2, 8, 0 }, - - /* CPU port number */ - [RTL_REG_CPUPORT] = { 2, 4, 21, 3, 0, 0 }, - /* Enable CPU port function */ - [RTL_REG_EN_CPUPORT] = { 3, 2, 21, 1, 15, 1 }, - /* Enable CPU port tag insertion */ - [RTL_REG_EN_TAG_OUT] = { 3, 2, 21, 1, 12, 0 }, - /* Enable CPU port tag removal */ - [RTL_REG_EN_TAG_CLR] = { 3, 2, 21, 1, 11, 0 }, - /* Enable CPU port tag checking */ - [RTL_REG_EN_TAG_IN] = { 0, 4, 21, 1, 7, 0 }, - [RTL_REG_EN_TRUNK] = { 0, 0, 19, 1, 11, 1 }, - [RTL_REG_TRUNK_PORTSEL] = { 0, 0, 16, 1, 6, 1 }, - [RTL_REG_RESET] = { 0, 0, 16, 1, 12, 0 }, - - [RTL_REG_TRAP_CPU] = { 3, 2, 22, 1, 6, 0 }, - [RTL_REG_CPU_LINKUP] = { 0, 6, 22, 1, 15, 0 }, - - [RTL_REG_VLAN_TAG_ONLY] = { 0, 0, 16, 1, 8, 1 }, - [RTL_REG_VLAN_FILTER] = { 0, 0, 16, 1, 9, 1 }, - [RTL_REG_VLAN_TAG_AWARE] = { 0, 0, 16, 1, 10, 1 }, - [RTL_REG_VLAN_ENABLE] = { 0, 0, 18, 1, 8, 1 }, - -#define RTL_VLAN_REGS(id, phy, page, regofs) \ - [RTL_REG_VLAN##id##_VID] = { page, phy, 25 + regofs, 12, 0, 0 }, \ - [RTL_REG_VLAN##id##_PORTMASK] = { page, phy, 24 + regofs, 6, 0, 0 } - RTL_VLAN_REGS( 0, 0, 0, 0), - RTL_VLAN_REGS( 1, 1, 0, 0), - RTL_VLAN_REGS( 2, 2, 0, 0), - RTL_VLAN_REGS( 3, 3, 0, 0), - RTL_VLAN_REGS( 4, 4, 0, 0), - RTL_VLAN_REGS( 5, 0, 1, 2), - RTL_VLAN_REGS( 6, 1, 1, 2), - RTL_VLAN_REGS( 7, 2, 1, 2), - RTL_VLAN_REGS( 8, 3, 1, 2), - RTL_VLAN_REGS( 9, 4, 1, 2), - RTL_VLAN_REGS(10, 0, 1, 4), - RTL_VLAN_REGS(11, 1, 1, 4), - RTL_VLAN_REGS(12, 2, 1, 4), - RTL_VLAN_REGS(13, 3, 1, 4), - RTL_VLAN_REGS(14, 4, 1, 4), - RTL_VLAN_REGS(15, 0, 1, 6), - -#define REG_PORT_SETTING(port, phy) \ - [RTL_REG_PORT##port##_SPEED] = { 0, phy, 0, 1, 13, 0 }, \ - [RTL_REG_PORT##port##_NWAY] = { 0, phy, 0, 1, 12, 0 }, \ - [RTL_REG_PORT##port##_NRESTART] = { 0, phy, 0, 1, 9, 0 }, \ - [RTL_REG_PORT##port##_DUPLEX] = { 0, phy, 0, 1, 8, 0 }, \ - [RTL_REG_PORT##port##_TXEN] = { 0, phy, 24, 1, 11, 0 }, \ - [RTL_REG_PORT##port##_RXEN] = { 0, phy, 24, 1, 10, 0 }, \ - [RTL_REG_PORT##port##_LINK] = { 0, phy, 1, 1, 2, 0 }, \ - [RTL_REG_PORT##port##_NULL_VID_REPLACE] = { 0, phy, 22, 1, 12, 0 }, \ - [RTL_REG_PORT##port##_NON_PVID_DISCARD] = { 0, phy, 22, 1, 11, 0 }, \ - [RTL_REG_PORT##port##_VID_INSERT] = { 0, phy, 22, 2, 9, 0 }, \ - [RTL_REG_PORT##port##_TAG_INSERT] = { 0, phy, 22, 2, 0, 0 } - - REG_PORT_SETTING(0, 0), - REG_PORT_SETTING(1, 1), - REG_PORT_SETTING(2, 2), - REG_PORT_SETTING(3, 3), - REG_PORT_SETTING(4, 4), - REG_PORT_SETTING(5, 6), - -#define REG_PORT_PVID(phy, page, regofs) \ - { page, phy, 24 + regofs, 4, 12, 0 } - [RTL_REG_PORT0_PVID] = REG_PORT_PVID(0, 0, 0), - [RTL_REG_PORT1_PVID] = REG_PORT_PVID(1, 0, 0), - [RTL_REG_PORT2_PVID] = REG_PORT_PVID(2, 0, 0), - [RTL_REG_PORT3_PVID] = REG_PORT_PVID(3, 0, 0), - [RTL_REG_PORT4_PVID] = REG_PORT_PVID(4, 0, 0), - [RTL_REG_PORT5_PVID] = REG_PORT_PVID(0, 1, 2), -}; - - -static inline void -rtl_set_page(struct rtl_priv *priv, unsigned int page) -{ - struct mii_bus *bus = priv->bus; - u16 pgsel; - - if (priv->fixup) - return; - - if (priv->page == page) - return; - - BUG_ON(page > RTL8306_NUM_PAGES); - pgsel = bus->read(bus, 0, RTL8306_REG_PAGE); - pgsel &= ~(RTL8306_REG_PAGE_LO | RTL8306_REG_PAGE_HI); - if (page & (1 << 0)) - pgsel |= RTL8306_REG_PAGE_LO; - if (!(page & (1 << 1))) /* bit is inverted */ - pgsel |= RTL8306_REG_PAGE_HI; - bus->write(bus, 0, RTL8306_REG_PAGE, pgsel); -} - -static inline int -rtl_w16(struct switch_dev *dev, unsigned int page, unsigned int phy, unsigned int reg, u16 val) -{ - struct rtl_priv *priv = to_rtl(dev); - struct mii_bus *bus = priv->bus; - - rtl_set_page(priv, page); - bus->write(bus, phy, reg, val); - bus->read(bus, phy, reg); /* flush */ - return 0; -} - -static inline int -rtl_r16(struct switch_dev *dev, unsigned int page, unsigned int phy, unsigned int reg) -{ - struct rtl_priv *priv = to_rtl(dev); - struct mii_bus *bus = priv->bus; - - rtl_set_page(priv, page); - return bus->read(bus, phy, reg); -} - -static inline u16 -rtl_rmw(struct switch_dev *dev, unsigned int page, unsigned int phy, unsigned int reg, u16 mask, u16 val) -{ - struct rtl_priv *priv = to_rtl(dev); - struct mii_bus *bus = priv->bus; - u16 r; - - rtl_set_page(priv, page); - r = bus->read(bus, phy, reg); - r &= ~mask; - r |= val; - bus->write(bus, phy, reg, r); - return bus->read(bus, phy, reg); /* flush */ -} - - -static inline int -rtl_get(struct switch_dev *dev, enum rtl_regidx s) -{ - const struct rtl_reg *r = &rtl_regs[s]; - u16 val; - - BUG_ON(s >= ARRAY_SIZE(rtl_regs)); - if (r->bits == 0) /* unimplemented */ - return 0; - - val = rtl_r16(dev, r->page, r->phy, r->reg); - - if (r->shift > 0) - val >>= r->shift; - - if (r->inverted) - val = ~val; - - val &= (1 << r->bits) - 1; - - return val; -} - -static int -rtl_set(struct switch_dev *dev, enum rtl_regidx s, unsigned int val) -{ - const struct rtl_reg *r = &rtl_regs[s]; - u16 mask = 0xffff; - - BUG_ON(s >= ARRAY_SIZE(rtl_regs)); - - if (r->bits == 0) /* unimplemented */ - return 0; - - if (r->shift > 0) - val <<= r->shift; - - if (r->inverted) - val = ~val; - - if (r->bits != 16) { - mask = (1 << r->bits) - 1; - mask <<= r->shift; - } - val &= mask; - return rtl_rmw(dev, r->page, r->phy, r->reg, mask, val); -} - -static void -rtl_phy_save(struct switch_dev *dev, int port, struct rtl_phyregs *regs) -{ - regs->nway = rtl_get(dev, RTL_PORT_REG(port, NWAY)); - regs->speed = rtl_get(dev, RTL_PORT_REG(port, SPEED)); - regs->duplex = rtl_get(dev, RTL_PORT_REG(port, DUPLEX)); -} - -static void -rtl_phy_restore(struct switch_dev *dev, int port, struct rtl_phyregs *regs) -{ - rtl_set(dev, RTL_PORT_REG(port, NWAY), regs->nway); - rtl_set(dev, RTL_PORT_REG(port, SPEED), regs->speed); - rtl_set(dev, RTL_PORT_REG(port, DUPLEX), regs->duplex); -} - -static void -rtl_port_set_enable(struct switch_dev *dev, int port, int enabled) -{ - rtl_set(dev, RTL_PORT_REG(port, RXEN), enabled); - rtl_set(dev, RTL_PORT_REG(port, TXEN), enabled); - - if ((port >= 5) || !enabled) - return; - - /* restart autonegotiation if enabled */ - rtl_set(dev, RTL_PORT_REG(port, NRESTART), 1); -} - -static int -rtl_hw_apply(struct switch_dev *dev) -{ - int i; - int trunk_en, trunk_psel; - struct rtl_phyregs port5; - - rtl_phy_save(dev, 5, &port5); - - /* disable rx/tx from PHYs */ - for (i = 0; i < RTL8306_NUM_PORTS - 1; i++) { - rtl_port_set_enable(dev, i, 0); - } - - /* save trunking status */ - trunk_en = rtl_get(dev, RTL_REG_EN_TRUNK); - trunk_psel = rtl_get(dev, RTL_REG_TRUNK_PORTSEL); - - /* trunk port 3 and 4 - * XXX: Big WTF, but RealTek seems to do it */ - rtl_set(dev, RTL_REG_EN_TRUNK, 1); - rtl_set(dev, RTL_REG_TRUNK_PORTSEL, 1); - - /* execute the software reset */ - rtl_set(dev, RTL_REG_RESET, 1); - - /* wait for the reset to complete, - * but don't wait for too long */ - for (i = 0; i < 10; i++) { - if (rtl_get(dev, RTL_REG_RESET) == 0) - break; - - msleep(1); - } - - /* enable rx/tx from PHYs */ - for (i = 0; i < RTL8306_NUM_PORTS - 1; i++) { - rtl_port_set_enable(dev, i, 1); - } - - /* restore trunking settings */ - rtl_set(dev, RTL_REG_EN_TRUNK, trunk_en); - rtl_set(dev, RTL_REG_TRUNK_PORTSEL, trunk_psel); - rtl_phy_restore(dev, 5, &port5); - - rtl_set(dev, RTL_REG_CPU_LINKUP, 1); - - return 0; -} - -static void -rtl_hw_init(struct switch_dev *dev) -{ - struct rtl_priv *priv = to_rtl(dev); - int cpu_mask = 1 << dev->cpu_port; - int i; - - rtl_set(dev, RTL_REG_VLAN_ENABLE, 0); - rtl_set(dev, RTL_REG_VLAN_FILTER, 0); - rtl_set(dev, RTL_REG_EN_TRUNK, 0); - rtl_set(dev, RTL_REG_TRUNK_PORTSEL, 0); - - /* initialize cpu port settings */ - if (priv->do_cpu) { - rtl_set(dev, RTL_REG_CPUPORT, dev->cpu_port); - rtl_set(dev, RTL_REG_EN_CPUPORT, 1); - } else { - rtl_set(dev, RTL_REG_CPUPORT, 7); - rtl_set(dev, RTL_REG_EN_CPUPORT, 0); - } - rtl_set(dev, RTL_REG_EN_TAG_OUT, 0); - rtl_set(dev, RTL_REG_EN_TAG_IN, 0); - rtl_set(dev, RTL_REG_EN_TAG_CLR, 0); - - /* reset all vlans */ - for (i = 0; i < RTL8306_NUM_VLANS; i++) { - rtl_set(dev, RTL_VLAN_REG(i, VID), i); - rtl_set(dev, RTL_VLAN_REG(i, PORTMASK), 0); - } - - /* default to port isolation */ - for (i = 0; i < RTL8306_NUM_PORTS; i++) { - unsigned long mask; - - if ((1 << i) == cpu_mask) - mask = ((1 << RTL8306_NUM_PORTS) - 1) & ~cpu_mask; /* all bits set */ - else - mask = cpu_mask | (1 << i); - - rtl_set(dev, RTL_VLAN_REG(i, PORTMASK), mask); - rtl_set(dev, RTL_PORT_REG(i, PVID), i); - rtl_set(dev, RTL_PORT_REG(i, NULL_VID_REPLACE), 1); - rtl_set(dev, RTL_PORT_REG(i, VID_INSERT), 1); - rtl_set(dev, RTL_PORT_REG(i, TAG_INSERT), 3); - } - rtl_hw_apply(dev); -} - -#ifdef DEBUG -static int -rtl_set_use_cpuport(struct switch_dev *dev, const struct switch_attr *attr, struct switch_val *val) -{ - struct rtl_priv *priv = to_rtl(dev); - priv->do_cpu = val->value.i; - rtl_hw_init(dev); - return 0; -} - -static int -rtl_get_use_cpuport(struct switch_dev *dev, const struct switch_attr *attr, struct switch_val *val) -{ - struct rtl_priv *priv = to_rtl(dev); - val->value.i = priv->do_cpu; - return 0; -} - -static int -rtl_set_cpuport(struct switch_dev *dev, const struct switch_attr *attr, struct switch_val *val) -{ - dev->cpu_port = val->value.i; - rtl_hw_init(dev); - return 0; -} - -static int -rtl_get_cpuport(struct switch_dev *dev, const struct switch_attr *attr, struct switch_val *val) -{ - val->value.i = dev->cpu_port; - return 0; -} -#endif - -static int -rtl_reset(struct switch_dev *dev) -{ - rtl_hw_init(dev); - return 0; -} - -static int -rtl_attr_set_int(struct switch_dev *dev, const struct switch_attr *attr, struct switch_val *val) -{ - int idx = attr->id + (val->port_vlan * attr->ofs); - struct rtl_phyregs port; - - if (attr->id >= ARRAY_SIZE(rtl_regs)) - return -EINVAL; - - if ((attr->max > 0) && (val->value.i > attr->max)) - return -EINVAL; - - /* access to phy register 22 on port 4/5 - * needs phy status save/restore */ - if ((val->port_vlan > 3) && - (rtl_regs[idx].reg == 22) && - (rtl_regs[idx].page == 0)) { - - rtl_phy_save(dev, val->port_vlan, &port); - rtl_set(dev, idx, val->value.i); - rtl_phy_restore(dev, val->port_vlan, &port); - } else { - rtl_set(dev, idx, val->value.i); - } - - return 0; -} - -static int -rtl_attr_get_int(struct switch_dev *dev, const struct switch_attr *attr, struct switch_val *val) -{ - int idx = attr->id + (val->port_vlan * attr->ofs); - - if (idx >= ARRAY_SIZE(rtl_regs)) - return -EINVAL; - - val->value.i = rtl_get(dev, idx); - return 0; -} - -static int -rtl_attr_set_port_int(struct switch_dev *dev, const struct switch_attr *attr, struct switch_val *val) -{ - if (val->port_vlan >= RTL8306_NUM_PORTS) - return -EINVAL; - - return rtl_attr_set_int(dev, attr, val); -} - -static int -rtl_attr_get_port_int(struct switch_dev *dev, const struct switch_attr *attr, struct switch_val *val) -{ - if (val->port_vlan >= RTL8306_NUM_PORTS) - return -EINVAL; - return rtl_attr_get_int(dev, attr, val); -} - -static int -rtl_get_port_link(struct switch_dev *dev, int port, struct switch_port_link *link) -{ - if (port >= RTL8306_NUM_PORTS) - return -EINVAL; - - /* in case the link changes from down to up, the register is only updated on read */ - link->link = rtl_get(dev, RTL_PORT_REG(port, LINK)); - if (!link->link) - link->link = rtl_get(dev, RTL_PORT_REG(port, LINK)); - - if (!link->link) - return 0; - - link->duplex = rtl_get(dev, RTL_PORT_REG(port, DUPLEX)); - link->aneg = rtl_get(dev, RTL_PORT_REG(port, NWAY)); - - if (rtl_get(dev, RTL_PORT_REG(port, SPEED))) - link->speed = SWITCH_PORT_SPEED_100; - else - link->speed = SWITCH_PORT_SPEED_10; - - return 0; -} - -static int -rtl_attr_set_vlan_int(struct switch_dev *dev, const struct switch_attr *attr, struct switch_val *val) -{ - if (val->port_vlan >= dev->vlans) - return -EINVAL; - - return rtl_attr_set_int(dev, attr, val); -} - -static int -rtl_attr_get_vlan_int(struct switch_dev *dev, const struct switch_attr *attr, struct switch_val *val) -{ - if (val->port_vlan >= dev->vlans) - return -EINVAL; - - return rtl_attr_get_int(dev, attr, val); -} - -static int -rtl_get_ports(struct switch_dev *dev, struct switch_val *val) -{ - unsigned int i, mask; - - mask = rtl_get(dev, RTL_VLAN_REG(val->port_vlan, PORTMASK)); - for (i = 0; i < RTL8306_NUM_PORTS; i++) { - struct switch_port *port; - - if (!(mask & (1 << i))) - continue; - - port = &val->value.ports[val->len]; - port->id = i; - if (rtl_get(dev, RTL_PORT_REG(i, TAG_INSERT)) == 2 || i == dev->cpu_port) - port->flags = (1 << SWITCH_PORT_FLAG_TAGGED); - val->len++; - } - - return 0; -} - -static int -rtl_set_vlan(struct switch_dev *dev, const struct switch_attr *attr, struct switch_val *val) -{ - struct rtl_priv *priv = to_rtl(dev); - struct rtl_phyregs port; - int en = val->value.i; - int i; - - rtl_set(dev, RTL_REG_EN_TAG_OUT, en && priv->do_cpu); - rtl_set(dev, RTL_REG_EN_TAG_IN, en && priv->do_cpu); - rtl_set(dev, RTL_REG_EN_TAG_CLR, en && priv->do_cpu); - rtl_set(dev, RTL_REG_VLAN_TAG_AWARE, en); - if (en) - rtl_set(dev, RTL_REG_VLAN_FILTER, en); - - for (i = 0; i < RTL8306_NUM_PORTS; i++) { - if (i > 3) - rtl_phy_save(dev, val->port_vlan, &port); - rtl_set(dev, RTL_PORT_REG(i, NULL_VID_REPLACE), 1); - rtl_set(dev, RTL_PORT_REG(i, VID_INSERT), (en ? (i == dev->cpu_port ? 0 : 1) : 1)); - rtl_set(dev, RTL_PORT_REG(i, TAG_INSERT), (en ? (i == dev->cpu_port ? 2 : 1) : 3)); - if (i > 3) - rtl_phy_restore(dev, val->port_vlan, &port); - } - rtl_set(dev, RTL_REG_VLAN_ENABLE, en); - - return 0; -} - -static int -rtl_get_vlan(struct switch_dev *dev, const struct switch_attr *attr, struct switch_val *val) -{ - val->value.i = rtl_get(dev, RTL_REG_VLAN_ENABLE); - return 0; -} - -static int -rtl_set_ports(struct switch_dev *dev, struct switch_val *val) -{ - unsigned int mask = 0; - unsigned int oldmask; - int i; - - for(i = 0; i < val->len; i++) - { - struct switch_port *port = &val->value.ports[i]; - bool tagged = false; - - mask |= (1 << port->id); - - if (port->id == dev->cpu_port) - continue; - - if ((i == dev->cpu_port) || - (port->flags & (1 << SWITCH_PORT_FLAG_TAGGED))) - tagged = true; - - /* fix up PVIDs for added ports */ - if (!tagged) - rtl_set(dev, RTL_PORT_REG(port->id, PVID), val->port_vlan); - - rtl_set(dev, RTL_PORT_REG(port->id, NON_PVID_DISCARD), (tagged ? 0 : 1)); - rtl_set(dev, RTL_PORT_REG(port->id, VID_INSERT), (tagged ? 0 : 1)); - rtl_set(dev, RTL_PORT_REG(port->id, TAG_INSERT), (tagged ? 2 : 1)); - } - - oldmask = rtl_get(dev, RTL_VLAN_REG(val->port_vlan, PORTMASK)); - rtl_set(dev, RTL_VLAN_REG(val->port_vlan, PORTMASK), mask); - - /* fix up PVIDs for removed ports, default to last vlan */ - oldmask &= ~mask; - for (i = 0; i < RTL8306_NUM_PORTS; i++) { - if (!(oldmask & (1 << i))) - continue; - - if (i == dev->cpu_port) - continue; - - if (rtl_get(dev, RTL_PORT_REG(i, PVID)) == val->port_vlan) - rtl_set(dev, RTL_PORT_REG(i, PVID), dev->vlans - 1); - } - - return 0; -} - -static struct switch_attr rtl_globals[] = { - { - .type = SWITCH_TYPE_INT, - .name = "enable_vlan", - .description = "Enable VLAN mode", - .max = 1, - .set = rtl_set_vlan, - .get = rtl_get_vlan, - }, - { - RTL_GLOBAL_REGATTR(EN_TRUNK), - .name = "trunk", - .description = "Enable port trunking", - .max = 1, - }, - { - RTL_GLOBAL_REGATTR(TRUNK_PORTSEL), - .name = "trunk_sel", - .description = "Select ports for trunking (0: 0,1 - 1: 3,4)", - .max = 1, - }, -#ifdef DEBUG - { - RTL_GLOBAL_REGATTR(VLAN_FILTER), - .name = "vlan_filter", - .description = "Filter incoming packets for allowed VLANS", - .max = 1, - }, - { - .type = SWITCH_TYPE_INT, - .name = "cpuport", - .description = "CPU Port", - .set = rtl_set_cpuport, - .get = rtl_get_cpuport, - .max = RTL8306_NUM_PORTS, - }, - { - .type = SWITCH_TYPE_INT, - .name = "use_cpuport", - .description = "CPU Port handling flag", - .set = rtl_set_use_cpuport, - .get = rtl_get_use_cpuport, - .max = RTL8306_NUM_PORTS, - }, - { - RTL_GLOBAL_REGATTR(TRAP_CPU), - .name = "trap_cpu", - .description = "VLAN trap to CPU", - .max = 1, - }, - { - RTL_GLOBAL_REGATTR(VLAN_TAG_AWARE), - .name = "vlan_tag_aware", - .description = "Enable VLAN tag awareness", - .max = 1, - }, - { - RTL_GLOBAL_REGATTR(VLAN_TAG_ONLY), - .name = "tag_only", - .description = "Only accept tagged packets", - .max = 1, - }, -#endif -}; -static struct switch_attr rtl_port[] = { - { - RTL_PORT_REGATTR(PVID), - .name = "pvid", - .description = "Port VLAN ID", - .max = RTL8306_NUM_VLANS - 1, - }, -#ifdef DEBUG - { - RTL_PORT_REGATTR(NULL_VID_REPLACE), - .name = "null_vid", - .description = "NULL VID gets replaced by port default vid", - .max = 1, - }, - { - RTL_PORT_REGATTR(NON_PVID_DISCARD), - .name = "non_pvid_discard", - .description = "discard packets with VID != PVID", - .max = 1, - }, - { - RTL_PORT_REGATTR(VID_INSERT), - .name = "vid_insert_remove", - .description = "how should the switch insert and remove vids ?", - .max = 3, - }, - { - RTL_PORT_REGATTR(TAG_INSERT), - .name = "tag_insert", - .description = "tag insertion handling", - .max = 3, - }, -#endif -}; - -static struct switch_attr rtl_vlan[] = { - { - RTL_VLAN_REGATTR(VID), - .name = "vid", - .description = "VLAN ID (1-4095)", - .max = 4095, - }, -}; - -static const struct switch_dev_ops rtl8306_ops = { - .attr_global = { - .attr = rtl_globals, - .n_attr = ARRAY_SIZE(rtl_globals), - }, - .attr_port = { - .attr = rtl_port, - .n_attr = ARRAY_SIZE(rtl_port), - }, - .attr_vlan = { - .attr = rtl_vlan, - .n_attr = ARRAY_SIZE(rtl_vlan), - }, - - .get_vlan_ports = rtl_get_ports, - .set_vlan_ports = rtl_set_ports, - .apply_config = rtl_hw_apply, - .reset_switch = rtl_reset, - .get_port_link = rtl_get_port_link, -}; - -static int -rtl8306_config_init(struct phy_device *pdev) -{ - struct net_device *netdev = pdev->attached_dev; - struct rtl_priv *priv = pdev->priv; - struct switch_dev *dev = &priv->dev; - struct switch_val val; - unsigned int chipid, chipver, chiptype; - int err; - - /* Only init the switch for the primary PHY */ - if (pdev->mdio.addr != 0) - return 0; - - val.value.i = 1; - priv->dev.cpu_port = RTL8306_PORT_CPU; - priv->dev.ports = RTL8306_NUM_PORTS; - priv->dev.vlans = RTL8306_NUM_VLANS; - priv->dev.ops = &rtl8306_ops; - priv->do_cpu = 0; - priv->page = -1; - priv->bus = pdev->mdio.bus; - - chipid = rtl_get(dev, RTL_REG_CHIPID); - chipver = rtl_get(dev, RTL_REG_CHIPVER); - chiptype = rtl_get(dev, RTL_REG_CHIPTYPE); - switch(chiptype) { - case 0: - case 2: - strncpy(priv->hwname, RTL_NAME_S, sizeof(priv->hwname)); - priv->type = RTL_TYPE_S; - break; - case 1: - strncpy(priv->hwname, RTL_NAME_SD, sizeof(priv->hwname)); - priv->type = RTL_TYPE_SD; - break; - case 3: - strncpy(priv->hwname, RTL_NAME_SDM, sizeof(priv->hwname)); - priv->type = RTL_TYPE_SDM; - break; - default: - strncpy(priv->hwname, RTL_NAME_UNKNOWN, sizeof(priv->hwname)); - break; - } - - dev->name = priv->hwname; - rtl_hw_init(dev); - - printk(KERN_INFO "Registering %s switch with Chip ID: 0x%04x, version: 0x%04x\n", priv->hwname, chipid, chipver); - - err = register_switch(dev, netdev); - if (err < 0) { - kfree(priv); - return err; - } - - return 0; -} - - -static int -rtl8306_fixup(struct phy_device *pdev) -{ - struct rtl_priv priv; - u16 chipid; - - /* Attach to primary LAN port and WAN port */ - if (pdev->mdio.addr != 0 && pdev->mdio.addr != 4) - return 0; - - memset(&priv, 0, sizeof(priv)); - priv.fixup = true; - priv.page = -1; - priv.bus = pdev->mdio.bus; - chipid = rtl_get(&priv.dev, RTL_REG_CHIPID); - if (chipid == 0x5988) - pdev->phy_id = RTL8306_MAGIC; - - return 0; -} - -static int -rtl8306_probe(struct phy_device *pdev) -{ - struct rtl_priv *priv; - - list_for_each_entry(priv, &phydevs, list) { - /* - * share one rtl_priv instance between virtual phy - * devices on the same bus - */ - if (priv->bus == pdev->mdio.bus) - goto found; - } - priv = kzalloc(sizeof(struct rtl_priv), GFP_KERNEL); - if (!priv) - return -ENOMEM; - - priv->bus = pdev->mdio.bus; - -found: - pdev->priv = priv; - return 0; -} - -static void -rtl8306_remove(struct phy_device *pdev) -{ - struct rtl_priv *priv = pdev->priv; - unregister_switch(&priv->dev); - kfree(priv); -} - -static int -rtl8306_config_aneg(struct phy_device *pdev) -{ - struct rtl_priv *priv = pdev->priv; - - /* Only for WAN */ - if (pdev->mdio.addr == 0) - return 0; - - /* Restart autonegotiation */ - rtl_set(&priv->dev, RTL_PORT_REG(4, NWAY), 1); - rtl_set(&priv->dev, RTL_PORT_REG(4, NRESTART), 1); - - return 0; -} - -static int -rtl8306_read_status(struct phy_device *pdev) -{ - struct rtl_priv *priv = pdev->priv; - struct switch_dev *dev = &priv->dev; - - if (pdev->mdio.addr == 4) { - /* WAN */ - pdev->speed = rtl_get(dev, RTL_PORT_REG(4, SPEED)) ? SPEED_100 : SPEED_10; - pdev->duplex = rtl_get(dev, RTL_PORT_REG(4, DUPLEX)) ? DUPLEX_FULL : DUPLEX_HALF; - pdev->link = !!rtl_get(dev, RTL_PORT_REG(4, LINK)); - } else { - /* LAN */ - pdev->speed = SPEED_100; - pdev->duplex = DUPLEX_FULL; - pdev->link = 1; - } - - /* - * Bypass generic PHY status read, - * it doesn't work with this switch - */ - if (pdev->link) { - pdev->state = PHY_RUNNING; - netif_carrier_on(pdev->attached_dev); - pdev->adjust_link(pdev->attached_dev); - } else { - pdev->state = PHY_NOLINK; - netif_carrier_off(pdev->attached_dev); - pdev->adjust_link(pdev->attached_dev); - } - - return 0; -} - - -static struct phy_driver rtl8306_driver = { - .name = "Realtek RTL8306S", - .phy_id = RTL8306_MAGIC, - .phy_id_mask = 0xffffffff, - .features = PHY_BASIC_FEATURES, - .probe = &rtl8306_probe, - .remove = &rtl8306_remove, - .config_init = &rtl8306_config_init, - .config_aneg = &rtl8306_config_aneg, - .read_status = &rtl8306_read_status, -}; - - -static int __init -rtl_init(void) -{ - phy_register_fixup_for_id(PHY_ANY_ID, rtl8306_fixup); - return phy_driver_register(&rtl8306_driver, THIS_MODULE); -} - -static void __exit -rtl_exit(void) -{ - phy_driver_unregister(&rtl8306_driver); -} - -module_init(rtl_init); -module_exit(rtl_exit); -MODULE_LICENSE("GPL"); - diff --git a/target/linux/generic/files-6.12/drivers/net/phy/rtl8366_smi.c b/target/linux/generic/files-6.12/drivers/net/phy/rtl8366_smi.c deleted file mode 100644 index a26fd204cb25db..00000000000000 --- a/target/linux/generic/files-6.12/drivers/net/phy/rtl8366_smi.c +++ /dev/null @@ -1,1625 +0,0 @@ -/* - * Realtek RTL8366 SMI interface driver - * - * Copyright (C) 2009-2010 Gabor Juhos - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published - * by the Free Software Foundation. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef CONFIG_RTL8366_SMI_DEBUG_FS -#include -#endif - -#include "rtl8366_smi.h" - -#define RTL8366_SMI_ACK_RETRY_COUNT 5 - -#define RTL8366_SMI_HW_STOP_DELAY 25 /* msecs */ -#define RTL8366_SMI_HW_START_DELAY 100 /* msecs */ - -static inline void rtl8366_smi_clk_delay(struct rtl8366_smi *smi) -{ - ndelay(smi->clk_delay); -} - -static void rtl8366_smi_start(struct rtl8366_smi *smi) -{ - unsigned int sda = smi->gpio_sda; - unsigned int sck = smi->gpio_sck; - - /* - * Set GPIO pins to output mode, with initial state: - * SCK = 0, SDA = 1 - */ - gpio_direction_output(sck, 0); - gpio_direction_output(sda, 1); - rtl8366_smi_clk_delay(smi); - - /* CLK 1: 0 -> 1, 1 -> 0 */ - gpio_set_value(sck, 1); - rtl8366_smi_clk_delay(smi); - gpio_set_value(sck, 0); - rtl8366_smi_clk_delay(smi); - - /* CLK 2: */ - gpio_set_value(sck, 1); - rtl8366_smi_clk_delay(smi); - gpio_set_value(sda, 0); - rtl8366_smi_clk_delay(smi); - gpio_set_value(sck, 0); - rtl8366_smi_clk_delay(smi); - gpio_set_value(sda, 1); -} - -static void rtl8366_smi_stop(struct rtl8366_smi *smi) -{ - unsigned int sda = smi->gpio_sda; - unsigned int sck = smi->gpio_sck; - - rtl8366_smi_clk_delay(smi); - gpio_set_value(sda, 0); - gpio_set_value(sck, 1); - rtl8366_smi_clk_delay(smi); - gpio_set_value(sda, 1); - rtl8366_smi_clk_delay(smi); - gpio_set_value(sck, 1); - rtl8366_smi_clk_delay(smi); - gpio_set_value(sck, 0); - rtl8366_smi_clk_delay(smi); - gpio_set_value(sck, 1); - - /* add a click */ - rtl8366_smi_clk_delay(smi); - gpio_set_value(sck, 0); - rtl8366_smi_clk_delay(smi); - gpio_set_value(sck, 1); - - /* set GPIO pins to input mode */ - gpio_direction_input(sda); - gpio_direction_input(sck); -} - -static void rtl8366_smi_write_bits(struct rtl8366_smi *smi, u32 data, u32 len) -{ - unsigned int sda = smi->gpio_sda; - unsigned int sck = smi->gpio_sck; - - for (; len > 0; len--) { - rtl8366_smi_clk_delay(smi); - - /* prepare data */ - gpio_set_value(sda, !!(data & ( 1 << (len - 1)))); - rtl8366_smi_clk_delay(smi); - - /* clocking */ - gpio_set_value(sck, 1); - rtl8366_smi_clk_delay(smi); - gpio_set_value(sck, 0); - } -} - -static void rtl8366_smi_read_bits(struct rtl8366_smi *smi, u32 len, u32 *data) -{ - unsigned int sda = smi->gpio_sda; - unsigned int sck = smi->gpio_sck; - - gpio_direction_input(sda); - - for (*data = 0; len > 0; len--) { - u32 u; - - rtl8366_smi_clk_delay(smi); - - /* clocking */ - gpio_set_value(sck, 1); - rtl8366_smi_clk_delay(smi); - u = !!gpio_get_value(sda); - gpio_set_value(sck, 0); - - *data |= (u << (len - 1)); - } - - gpio_direction_output(sda, 0); -} - -static int rtl8366_smi_wait_for_ack(struct rtl8366_smi *smi) -{ - int retry_cnt; - - retry_cnt = 0; - do { - u32 ack; - - rtl8366_smi_read_bits(smi, 1, &ack); - if (ack == 0) - break; - - if (++retry_cnt > RTL8366_SMI_ACK_RETRY_COUNT) { - dev_err(smi->parent, "ACK timeout\n"); - return -ETIMEDOUT; - } - } while (1); - - return 0; -} - -static int rtl8366_smi_write_byte(struct rtl8366_smi *smi, u8 data) -{ - rtl8366_smi_write_bits(smi, data, 8); - return rtl8366_smi_wait_for_ack(smi); -} - -static int rtl8366_smi_write_byte_noack(struct rtl8366_smi *smi, u8 data) -{ - rtl8366_smi_write_bits(smi, data, 8); - return 0; -} - -static int rtl8366_smi_read_byte0(struct rtl8366_smi *smi, u8 *data) -{ - u32 t; - - /* read data */ - rtl8366_smi_read_bits(smi, 8, &t); - *data = (t & 0xff); - - /* send an ACK */ - rtl8366_smi_write_bits(smi, 0x00, 1); - - return 0; -} - -static int rtl8366_smi_read_byte1(struct rtl8366_smi *smi, u8 *data) -{ - u32 t; - - /* read data */ - rtl8366_smi_read_bits(smi, 8, &t); - *data = (t & 0xff); - - /* send an ACK */ - rtl8366_smi_write_bits(smi, 0x01, 1); - - return 0; -} - -static int __rtl8366_smi_read_reg(struct rtl8366_smi *smi, u32 addr, u32 *data) -{ - unsigned long flags; - u8 lo = 0; - u8 hi = 0; - int ret; - - spin_lock_irqsave(&smi->lock, flags); - - rtl8366_smi_start(smi); - - /* send READ command */ - ret = rtl8366_smi_write_byte(smi, smi->cmd_read); - if (ret) - goto out; - - /* set ADDR[7:0] */ - ret = rtl8366_smi_write_byte(smi, addr & 0xff); - if (ret) - goto out; - - /* set ADDR[15:8] */ - ret = rtl8366_smi_write_byte(smi, addr >> 8); - if (ret) - goto out; - - /* read DATA[7:0] */ - rtl8366_smi_read_byte0(smi, &lo); - /* read DATA[15:8] */ - rtl8366_smi_read_byte1(smi, &hi); - - *data = ((u32) lo) | (((u32) hi) << 8); - - ret = 0; - - out: - rtl8366_smi_stop(smi); - spin_unlock_irqrestore(&smi->lock, flags); - - return ret; -} -/* Read/write via mdiobus */ -#define MDC_MDIO_CTRL0_REG 31 -#define MDC_MDIO_START_REG 29 -#define MDC_MDIO_CTRL1_REG 21 -#define MDC_MDIO_ADDRESS_REG 23 -#define MDC_MDIO_DATA_WRITE_REG 24 -#define MDC_MDIO_DATA_READ_REG 25 - -#define MDC_MDIO_START_OP 0xFFFF -#define MDC_MDIO_ADDR_OP 0x000E -#define MDC_MDIO_READ_OP 0x0001 -#define MDC_MDIO_WRITE_OP 0x0003 -#define MDC_REALTEK_PHY_ADDR 0x0 - -int __rtl8366_mdio_read_reg(struct rtl8366_smi *smi, u32 addr, u32 *data) -{ - u32 phy_id = smi->phy_id; - struct mii_bus *mbus = smi->ext_mbus; - - BUG_ON(in_interrupt()); - - mutex_lock(&mbus->mdio_lock); - /* Write Start command to register 29 */ - mbus->write(mbus, phy_id, MDC_MDIO_START_REG, MDC_MDIO_START_OP); - - /* Write address control code to register 31 */ - mbus->write(mbus, phy_id, MDC_MDIO_CTRL0_REG, MDC_MDIO_ADDR_OP); - - /* Write Start command to register 29 */ - mbus->write(mbus, phy_id, MDC_MDIO_START_REG, MDC_MDIO_START_OP); - - /* Write address to register 23 */ - mbus->write(mbus, phy_id, MDC_MDIO_ADDRESS_REG, addr); - - /* Write Start command to register 29 */ - mbus->write(mbus, phy_id, MDC_MDIO_START_REG, MDC_MDIO_START_OP); - - /* Write read control code to register 21 */ - mbus->write(mbus, phy_id, MDC_MDIO_CTRL1_REG, MDC_MDIO_READ_OP); - - /* Write Start command to register 29 */ - mbus->write(smi->ext_mbus, phy_id, MDC_MDIO_START_REG, MDC_MDIO_START_OP); - - /* Read data from register 25 */ - *data = mbus->read(mbus, phy_id, MDC_MDIO_DATA_READ_REG); - - mutex_unlock(&mbus->mdio_lock); - - return 0; -} - -static int __rtl8366_mdio_write_reg(struct rtl8366_smi *smi, u32 addr, u32 data) -{ - u32 phy_id = smi->phy_id; - struct mii_bus *mbus = smi->ext_mbus; - - BUG_ON(in_interrupt()); - - mutex_lock(&mbus->mdio_lock); - - /* Write Start command to register 29 */ - mbus->write(mbus, phy_id, MDC_MDIO_START_REG, MDC_MDIO_START_OP); - - /* Write address control code to register 31 */ - mbus->write(mbus, phy_id, MDC_MDIO_CTRL0_REG, MDC_MDIO_ADDR_OP); - - /* Write Start command to register 29 */ - mbus->write(mbus, phy_id, MDC_MDIO_START_REG, MDC_MDIO_START_OP); - - /* Write address to register 23 */ - mbus->write(mbus, phy_id, MDC_MDIO_ADDRESS_REG, addr); - - /* Write Start command to register 29 */ - mbus->write(mbus, phy_id, MDC_MDIO_START_REG, MDC_MDIO_START_OP); - - /* Write data to register 24 */ - mbus->write(mbus, phy_id, MDC_MDIO_DATA_WRITE_REG, data); - - /* Write Start command to register 29 */ - mbus->write(mbus, phy_id, MDC_MDIO_START_REG, MDC_MDIO_START_OP); - - /* Write data control code to register 21 */ - mbus->write(mbus, phy_id, MDC_MDIO_CTRL1_REG, MDC_MDIO_WRITE_OP); - - mutex_unlock(&mbus->mdio_lock); - return 0; -} - -int rtl8366_smi_read_reg(struct rtl8366_smi *smi, u32 addr, u32 *data) -{ - if (smi->ext_mbus) - return __rtl8366_mdio_read_reg(smi, addr, data); - else - return __rtl8366_smi_read_reg(smi, addr, data); -} -EXPORT_SYMBOL_GPL(rtl8366_smi_read_reg); - -static int __rtl8366_smi_write_reg(struct rtl8366_smi *smi, - u32 addr, u32 data, bool ack) -{ - unsigned long flags; - int ret; - - spin_lock_irqsave(&smi->lock, flags); - - rtl8366_smi_start(smi); - - /* send WRITE command */ - ret = rtl8366_smi_write_byte(smi, smi->cmd_write); - if (ret) - goto out; - - /* set ADDR[7:0] */ - ret = rtl8366_smi_write_byte(smi, addr & 0xff); - if (ret) - goto out; - - /* set ADDR[15:8] */ - ret = rtl8366_smi_write_byte(smi, addr >> 8); - if (ret) - goto out; - - /* write DATA[7:0] */ - ret = rtl8366_smi_write_byte(smi, data & 0xff); - if (ret) - goto out; - - /* write DATA[15:8] */ - if (ack) - ret = rtl8366_smi_write_byte(smi, data >> 8); - else - ret = rtl8366_smi_write_byte_noack(smi, data >> 8); - if (ret) - goto out; - - ret = 0; - - out: - rtl8366_smi_stop(smi); - spin_unlock_irqrestore(&smi->lock, flags); - - return ret; -} - -int rtl8366_smi_write_reg(struct rtl8366_smi *smi, u32 addr, u32 data) -{ - if (smi->ext_mbus) - return __rtl8366_mdio_write_reg(smi, addr, data); - else - return __rtl8366_smi_write_reg(smi, addr, data, true); -} -EXPORT_SYMBOL_GPL(rtl8366_smi_write_reg); - -int rtl8366_smi_write_reg_noack(struct rtl8366_smi *smi, u32 addr, u32 data) -{ - return __rtl8366_smi_write_reg(smi, addr, data, false); -} -EXPORT_SYMBOL_GPL(rtl8366_smi_write_reg_noack); - -int rtl8366_smi_rmwr(struct rtl8366_smi *smi, u32 addr, u32 mask, u32 data) -{ - u32 t; - int err; - - err = rtl8366_smi_read_reg(smi, addr, &t); - if (err) - return err; - - err = rtl8366_smi_write_reg(smi, addr, (t & ~mask) | data); - return err; - -} -EXPORT_SYMBOL_GPL(rtl8366_smi_rmwr); - -static int rtl8366_reset(struct rtl8366_smi *smi) -{ - if (smi->hw_reset) { - smi->hw_reset(smi, true); - msleep(RTL8366_SMI_HW_STOP_DELAY); - smi->hw_reset(smi, false); - msleep(RTL8366_SMI_HW_START_DELAY); - return 0; - } - - return smi->ops->reset_chip(smi); -} - -static int rtl8366_mc_is_used(struct rtl8366_smi *smi, int mc_index, int *used) -{ - int err; - int i; - - *used = 0; - for (i = 0; i < smi->num_ports; i++) { - int index = 0; - - err = smi->ops->get_mc_index(smi, i, &index); - if (err) - return err; - - if (mc_index == index) { - *used = 1; - break; - } - } - - return 0; -} - -static int rtl8366_set_vlan(struct rtl8366_smi *smi, int vid, u32 member, - u32 untag, u32 fid) -{ - struct rtl8366_vlan_4k vlan4k; - int err; - int i; - - /* Update the 4K table */ - err = smi->ops->get_vlan_4k(smi, vid, &vlan4k); - if (err) - return err; - - vlan4k.member = member; - vlan4k.untag = untag; - vlan4k.fid = fid; - err = smi->ops->set_vlan_4k(smi, &vlan4k); - if (err) - return err; - - /* Try to find an existing MC entry for this VID */ - for (i = 0; i < smi->num_vlan_mc; i++) { - struct rtl8366_vlan_mc vlanmc; - - err = smi->ops->get_vlan_mc(smi, i, &vlanmc); - if (err) - return err; - - if (vid == vlanmc.vid) { - /* update the MC entry */ - vlanmc.member = member; - vlanmc.untag = untag; - vlanmc.fid = fid; - - err = smi->ops->set_vlan_mc(smi, i, &vlanmc); - break; - } - } - - return err; -} - -static int rtl8366_get_pvid(struct rtl8366_smi *smi, int port, int *val) -{ - struct rtl8366_vlan_mc vlanmc; - int err; - int index; - - err = smi->ops->get_mc_index(smi, port, &index); - if (err) - return err; - - err = smi->ops->get_vlan_mc(smi, index, &vlanmc); - if (err) - return err; - - *val = vlanmc.vid; - return 0; -} - -static int rtl8366_set_pvid(struct rtl8366_smi *smi, unsigned port, - unsigned vid) -{ - struct rtl8366_vlan_mc vlanmc; - struct rtl8366_vlan_4k vlan4k; - int err; - int i; - - /* Try to find an existing MC entry for this VID */ - for (i = 0; i < smi->num_vlan_mc; i++) { - err = smi->ops->get_vlan_mc(smi, i, &vlanmc); - if (err) - return err; - - if (vid == vlanmc.vid) { - err = smi->ops->set_vlan_mc(smi, i, &vlanmc); - if (err) - return err; - - err = smi->ops->set_mc_index(smi, port, i); - return err; - } - } - - /* We have no MC entry for this VID, try to find an empty one */ - for (i = 0; i < smi->num_vlan_mc; i++) { - err = smi->ops->get_vlan_mc(smi, i, &vlanmc); - if (err) - return err; - - if (vlanmc.vid == 0 && vlanmc.member == 0) { - /* Update the entry from the 4K table */ - err = smi->ops->get_vlan_4k(smi, vid, &vlan4k); - if (err) - return err; - - vlanmc.vid = vid; - vlanmc.member = vlan4k.member; - vlanmc.untag = vlan4k.untag; - vlanmc.fid = vlan4k.fid; - err = smi->ops->set_vlan_mc(smi, i, &vlanmc); - if (err) - return err; - - err = smi->ops->set_mc_index(smi, port, i); - return err; - } - } - - /* MC table is full, try to find an unused entry and replace it */ - for (i = 0; i < smi->num_vlan_mc; i++) { - int used; - - err = rtl8366_mc_is_used(smi, i, &used); - if (err) - return err; - - if (!used) { - /* Update the entry from the 4K table */ - err = smi->ops->get_vlan_4k(smi, vid, &vlan4k); - if (err) - return err; - - vlanmc.vid = vid; - vlanmc.member = vlan4k.member; - vlanmc.untag = vlan4k.untag; - vlanmc.fid = vlan4k.fid; - err = smi->ops->set_vlan_mc(smi, i, &vlanmc); - if (err) - return err; - - err = smi->ops->set_mc_index(smi, port, i); - return err; - } - } - - dev_err(smi->parent, - "all VLAN member configurations are in use\n"); - - return -ENOSPC; -} - -static int rtl8366_smi_enable_vlan(struct rtl8366_smi *smi, int enable) -{ - int err; - - err = smi->ops->enable_vlan(smi, enable); - if (err) - return err; - - smi->vlan_enabled = enable; - - if (!enable) { - smi->vlan4k_enabled = 0; - err = smi->ops->enable_vlan4k(smi, enable); - } - - return err; -} - -static int rtl8366_smi_enable_vlan4k(struct rtl8366_smi *smi, int enable) -{ - int err; - - if (enable) { - err = smi->ops->enable_vlan(smi, enable); - if (err) - return err; - - smi->vlan_enabled = enable; - } - - err = smi->ops->enable_vlan4k(smi, enable); - if (err) - return err; - - smi->vlan4k_enabled = enable; - return 0; -} - -static int rtl8366_smi_enable_all_ports(struct rtl8366_smi *smi, int enable) -{ - int port; - int err; - - for (port = 0; port < smi->num_ports; port++) { - err = smi->ops->enable_port(smi, port, enable); - if (err) - return err; - } - - return 0; -} - -static int rtl8366_smi_reset_vlan(struct rtl8366_smi *smi) -{ - struct rtl8366_vlan_mc vlanmc; - int err; - int i; - - rtl8366_smi_enable_vlan(smi, 0); - rtl8366_smi_enable_vlan4k(smi, 0); - - /* clear VLAN member configurations */ - vlanmc.vid = 0; - vlanmc.priority = 0; - vlanmc.member = 0; - vlanmc.untag = 0; - vlanmc.fid = 0; - for (i = 0; i < smi->num_vlan_mc; i++) { - err = smi->ops->set_vlan_mc(smi, i, &vlanmc); - if (err) - return err; - } - - return 0; -} - -static int rtl8366_init_vlan(struct rtl8366_smi *smi) -{ - int port; - int err; - - err = rtl8366_smi_reset_vlan(smi); - if (err) - return err; - - for (port = 0; port < smi->num_ports; port++) { - u32 mask; - - if (port == smi->cpu_port) - mask = (1 << smi->num_ports) - 1; - else - mask = (1 << port) | (1 << smi->cpu_port); - - err = rtl8366_set_vlan(smi, (port + 1), mask, mask, 0); - if (err) - return err; - - err = rtl8366_set_pvid(smi, port, (port + 1)); - if (err) - return err; - } - - return rtl8366_smi_enable_vlan(smi, 1); -} - -#ifdef CONFIG_RTL8366_SMI_DEBUG_FS -int rtl8366_debugfs_open(struct inode *inode, struct file *file) -{ - file->private_data = inode->i_private; - return 0; -} -EXPORT_SYMBOL_GPL(rtl8366_debugfs_open); - -static ssize_t rtl8366_read_debugfs_vlan_mc(struct file *file, - char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct rtl8366_smi *smi = (struct rtl8366_smi *)file->private_data; - int i, len = 0; - char *buf = smi->buf; - - len += snprintf(buf + len, sizeof(smi->buf) - len, - "%2s %6s %4s %6s %6s %3s\n", - "id", "vid","prio", "member", "untag", "fid"); - - for (i = 0; i < smi->num_vlan_mc; ++i) { - struct rtl8366_vlan_mc vlanmc; - - smi->ops->get_vlan_mc(smi, i, &vlanmc); - - len += snprintf(buf + len, sizeof(smi->buf) - len, - "%2d %6d %4d 0x%04x 0x%04x %3d\n", - i, vlanmc.vid, vlanmc.priority, - vlanmc.member, vlanmc.untag, vlanmc.fid); - } - - return simple_read_from_buffer(user_buf, count, ppos, buf, len); -} - -#define RTL8366_VLAN4K_PAGE_SIZE 64 -#define RTL8366_VLAN4K_NUM_PAGES (4096 / RTL8366_VLAN4K_PAGE_SIZE) - -static ssize_t rtl8366_read_debugfs_vlan_4k(struct file *file, - char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct rtl8366_smi *smi = (struct rtl8366_smi *)file->private_data; - int i, len = 0; - int offset; - char *buf = smi->buf; - - if (smi->dbg_vlan_4k_page >= RTL8366_VLAN4K_NUM_PAGES) { - len += snprintf(buf + len, sizeof(smi->buf) - len, - "invalid page: %u\n", smi->dbg_vlan_4k_page); - return simple_read_from_buffer(user_buf, count, ppos, buf, len); - } - - len += snprintf(buf + len, sizeof(smi->buf) - len, - "%4s %6s %6s %3s\n", - "vid", "member", "untag", "fid"); - - offset = RTL8366_VLAN4K_PAGE_SIZE * smi->dbg_vlan_4k_page; - for (i = 0; i < RTL8366_VLAN4K_PAGE_SIZE; i++) { - struct rtl8366_vlan_4k vlan4k; - - smi->ops->get_vlan_4k(smi, offset + i, &vlan4k); - - len += snprintf(buf + len, sizeof(smi->buf) - len, - "%4d 0x%04x 0x%04x %3d\n", - vlan4k.vid, vlan4k.member, - vlan4k.untag, vlan4k.fid); - } - - return simple_read_from_buffer(user_buf, count, ppos, buf, len); -} - -static ssize_t rtl8366_read_debugfs_pvid(struct file *file, - char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct rtl8366_smi *smi = (struct rtl8366_smi *)file->private_data; - char *buf = smi->buf; - int len = 0; - int i; - - len += snprintf(buf + len, sizeof(smi->buf) - len, "%4s %4s\n", - "port", "pvid"); - - for (i = 0; i < smi->num_ports; i++) { - int pvid; - int err; - - err = rtl8366_get_pvid(smi, i, &pvid); - if (err) - len += snprintf(buf + len, sizeof(smi->buf) - len, - "%4d error\n", i); - else - len += snprintf(buf + len, sizeof(smi->buf) - len, - "%4d %4d\n", i, pvid); - } - - return simple_read_from_buffer(user_buf, count, ppos, buf, len); -} - -static ssize_t rtl8366_read_debugfs_reg(struct file *file, - char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct rtl8366_smi *smi = (struct rtl8366_smi *)file->private_data; - u32 t, reg = smi->dbg_reg; - int err, len = 0; - char *buf = smi->buf; - - memset(buf, '\0', sizeof(smi->buf)); - - err = rtl8366_smi_read_reg(smi, reg, &t); - if (err) { - len += snprintf(buf, sizeof(smi->buf), - "Read failed (reg: 0x%04x)\n", reg); - return simple_read_from_buffer(user_buf, count, ppos, buf, len); - } - - len += snprintf(buf, sizeof(smi->buf), "reg = 0x%04x, val = 0x%04x\n", - reg, t); - - return simple_read_from_buffer(user_buf, count, ppos, buf, len); -} - -static ssize_t rtl8366_write_debugfs_reg(struct file *file, - const char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct rtl8366_smi *smi = (struct rtl8366_smi *)file->private_data; - unsigned long data; - u32 reg = smi->dbg_reg; - int err; - size_t len; - char *buf = smi->buf; - - len = min(count, sizeof(smi->buf) - 1); - if (copy_from_user(buf, user_buf, len)) { - dev_err(smi->parent, "copy from user failed\n"); - return -EFAULT; - } - - buf[len] = '\0'; - if (len > 0 && buf[len - 1] == '\n') - buf[len - 1] = '\0'; - - - if (kstrtoul(buf, 16, &data)) { - dev_err(smi->parent, "Invalid reg value %s\n", buf); - } else { - err = rtl8366_smi_write_reg(smi, reg, data); - if (err) { - dev_err(smi->parent, - "writing reg 0x%04x val 0x%04lx failed\n", - reg, data); - } - } - - return count; -} - -static ssize_t rtl8366_read_debugfs_mibs(struct file *file, - char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct rtl8366_smi *smi = file->private_data; - int i, j, len = 0; - char *buf = smi->buf; - - len += snprintf(buf + len, sizeof(smi->buf) - len, "%-36s", - "Counter"); - - for (i = 0; i < smi->num_ports; i++) { - char port_buf[10]; - - snprintf(port_buf, sizeof(port_buf), "Port %d", i); - len += snprintf(buf + len, sizeof(smi->buf) - len, " %12s", - port_buf); - } - len += snprintf(buf + len, sizeof(smi->buf) - len, "\n"); - - for (i = 0; i < smi->num_mib_counters; i++) { - len += snprintf(buf + len, sizeof(smi->buf) - len, "%-36s ", - smi->mib_counters[i].name); - for (j = 0; j < smi->num_ports; j++) { - unsigned long long counter = 0; - - if (!smi->ops->get_mib_counter(smi, i, j, &counter)) - len += snprintf(buf + len, - sizeof(smi->buf) - len, - "%12llu ", counter); - else - len += snprintf(buf + len, - sizeof(smi->buf) - len, - "%12s ", "error"); - } - len += snprintf(buf + len, sizeof(smi->buf) - len, "\n"); - } - - return simple_read_from_buffer(user_buf, count, ppos, buf, len); -} - -static const struct file_operations fops_rtl8366_regs = { - .read = rtl8366_read_debugfs_reg, - .write = rtl8366_write_debugfs_reg, - .open = rtl8366_debugfs_open, - .owner = THIS_MODULE -}; - -static const struct file_operations fops_rtl8366_vlan_mc = { - .read = rtl8366_read_debugfs_vlan_mc, - .open = rtl8366_debugfs_open, - .owner = THIS_MODULE -}; - -static const struct file_operations fops_rtl8366_vlan_4k = { - .read = rtl8366_read_debugfs_vlan_4k, - .open = rtl8366_debugfs_open, - .owner = THIS_MODULE -}; - -static const struct file_operations fops_rtl8366_pvid = { - .read = rtl8366_read_debugfs_pvid, - .open = rtl8366_debugfs_open, - .owner = THIS_MODULE -}; - -static const struct file_operations fops_rtl8366_mibs = { - .read = rtl8366_read_debugfs_mibs, - .open = rtl8366_debugfs_open, - .owner = THIS_MODULE -}; - -static void rtl8366_debugfs_init(struct rtl8366_smi *smi) -{ - struct dentry *node; - struct dentry *root; - - if (!smi->debugfs_root) - smi->debugfs_root = debugfs_create_dir(dev_name(smi->parent), - NULL); - - if (!smi->debugfs_root) { - dev_err(smi->parent, "Unable to create debugfs dir\n"); - return; - } - root = smi->debugfs_root; - - node = debugfs_create_x16("reg", S_IRUGO | S_IWUSR, root, - &smi->dbg_reg); - if (!node) { - dev_err(smi->parent, "Creating debugfs file '%s' failed\n", - "reg"); - return; - } - - node = debugfs_create_file("val", S_IRUGO | S_IWUSR, root, smi, - &fops_rtl8366_regs); - if (!node) { - dev_err(smi->parent, "Creating debugfs file '%s' failed\n", - "val"); - return; - } - - node = debugfs_create_file("vlan_mc", S_IRUSR, root, smi, - &fops_rtl8366_vlan_mc); - if (!node) { - dev_err(smi->parent, "Creating debugfs file '%s' failed\n", - "vlan_mc"); - return; - } - - node = debugfs_create_u8("vlan_4k_page", S_IRUGO | S_IWUSR, root, - &smi->dbg_vlan_4k_page); - if (!node) { - dev_err(smi->parent, "Creating debugfs file '%s' failed\n", - "vlan_4k_page"); - return; - } - - node = debugfs_create_file("vlan_4k", S_IRUSR, root, smi, - &fops_rtl8366_vlan_4k); - if (!node) { - dev_err(smi->parent, "Creating debugfs file '%s' failed\n", - "vlan_4k"); - return; - } - - node = debugfs_create_file("pvid", S_IRUSR, root, smi, - &fops_rtl8366_pvid); - if (!node) { - dev_err(smi->parent, "Creating debugfs file '%s' failed\n", - "pvid"); - return; - } - - node = debugfs_create_file("mibs", S_IRUSR, smi->debugfs_root, smi, - &fops_rtl8366_mibs); - if (!node) - dev_err(smi->parent, "Creating debugfs file '%s' failed\n", - "mibs"); -} - -static void rtl8366_debugfs_remove(struct rtl8366_smi *smi) -{ - if (smi->debugfs_root) { - debugfs_remove_recursive(smi->debugfs_root); - smi->debugfs_root = NULL; - } -} -#else -static inline void rtl8366_debugfs_init(struct rtl8366_smi *smi) {} -static inline void rtl8366_debugfs_remove(struct rtl8366_smi *smi) {} -#endif /* CONFIG_RTL8366_SMI_DEBUG_FS */ - -static int rtl8366_smi_mii_init(struct rtl8366_smi *smi) -{ - int ret; - -#ifdef CONFIG_OF - struct device_node *np = NULL; - - np = of_get_child_by_name(smi->parent->of_node, "mdio-bus"); -#endif - - smi->mii_bus = mdiobus_alloc(); - if (smi->mii_bus == NULL) { - ret = -ENOMEM; - goto err; - } - - smi->mii_bus->priv = (void *) smi; - smi->mii_bus->name = dev_name(smi->parent); - smi->mii_bus->read = smi->ops->mii_read; - smi->mii_bus->write = smi->ops->mii_write; - snprintf(smi->mii_bus->id, MII_BUS_ID_SIZE, "%s", - dev_name(smi->parent)); - smi->mii_bus->parent = smi->parent; - smi->mii_bus->phy_mask = ~(0x1f); - -#ifdef CONFIG_OF - if (np) - ret = of_mdiobus_register(smi->mii_bus, np); - else -#endif - ret = mdiobus_register(smi->mii_bus); - - if (ret) - goto err_free; - - return 0; - - err_free: - mdiobus_free(smi->mii_bus); - err: - return ret; -} - -static void rtl8366_smi_mii_cleanup(struct rtl8366_smi *smi) -{ - mdiobus_unregister(smi->mii_bus); - mdiobus_free(smi->mii_bus); -} - -int rtl8366_sw_reset_switch(struct switch_dev *dev) -{ - struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev); - int err; - - err = rtl8366_reset(smi); - if (err) - return err; - - err = smi->ops->setup(smi); - if (err) - return err; - - err = rtl8366_smi_reset_vlan(smi); - if (err) - return err; - - err = rtl8366_smi_enable_vlan(smi, 1); - if (err) - return err; - - return rtl8366_smi_enable_all_ports(smi, 1); -} -EXPORT_SYMBOL_GPL(rtl8366_sw_reset_switch); - -int rtl8366_sw_get_port_pvid(struct switch_dev *dev, int port, int *val) -{ - struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev); - return rtl8366_get_pvid(smi, port, val); -} -EXPORT_SYMBOL_GPL(rtl8366_sw_get_port_pvid); - -int rtl8366_sw_set_port_pvid(struct switch_dev *dev, int port, int val) -{ - struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev); - return rtl8366_set_pvid(smi, port, val); -} -EXPORT_SYMBOL_GPL(rtl8366_sw_set_port_pvid); - -int rtl8366_sw_get_port_mib(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val) -{ - struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev); - int i, len = 0; - unsigned long long counter = 0; - char *buf = smi->buf; - - if (val->port_vlan >= smi->num_ports) - return -EINVAL; - - len += snprintf(buf + len, sizeof(smi->buf) - len, - "Port %d MIB counters\n", - val->port_vlan); - - for (i = 0; i < smi->num_mib_counters; ++i) { - len += snprintf(buf + len, sizeof(smi->buf) - len, - "%-36s: ", smi->mib_counters[i].name); - if (!smi->ops->get_mib_counter(smi, i, val->port_vlan, - &counter)) - len += snprintf(buf + len, sizeof(smi->buf) - len, - "%llu\n", counter); - else - len += snprintf(buf + len, sizeof(smi->buf) - len, - "%s\n", "error"); - } - - val->value.s = buf; - val->len = len; - return 0; -} -EXPORT_SYMBOL_GPL(rtl8366_sw_get_port_mib); - -int rtl8366_sw_get_port_stats(struct switch_dev *dev, int port, - struct switch_port_stats *stats, - int txb_id, int rxb_id) -{ - struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev); - unsigned long long counter = 0; - int ret; - - if (port >= smi->num_ports) - return -EINVAL; - - ret = smi->ops->get_mib_counter(smi, txb_id, port, &counter); - if (ret) - return ret; - - stats->tx_bytes = counter; - - ret = smi->ops->get_mib_counter(smi, rxb_id, port, &counter); - if (ret) - return ret; - - stats->rx_bytes = counter; - - return 0; -} -EXPORT_SYMBOL_GPL(rtl8366_sw_get_port_stats); - -int rtl8366_sw_get_vlan_info(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val) -{ - int i; - u32 len = 0; - struct rtl8366_vlan_4k vlan4k; - struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev); - char *buf = smi->buf; - int err; - - if (!smi->ops->is_vlan_valid(smi, val->port_vlan)) - return -EINVAL; - - memset(buf, '\0', sizeof(smi->buf)); - - err = smi->ops->get_vlan_4k(smi, val->port_vlan, &vlan4k); - if (err) - return err; - - len += snprintf(buf + len, sizeof(smi->buf) - len, - "VLAN %d: Ports: '", vlan4k.vid); - - for (i = 0; i < smi->num_ports; i++) { - if (!(vlan4k.member & (1 << i))) - continue; - - len += snprintf(buf + len, sizeof(smi->buf) - len, "%d%s", i, - (vlan4k.untag & (1 << i)) ? "" : "t"); - } - - len += snprintf(buf + len, sizeof(smi->buf) - len, - "', members=%04x, untag=%04x, fid=%u", - vlan4k.member, vlan4k.untag, vlan4k.fid); - - val->value.s = buf; - val->len = len; - - return 0; -} -EXPORT_SYMBOL_GPL(rtl8366_sw_get_vlan_info); - -int rtl8366_sw_get_vlan_ports(struct switch_dev *dev, struct switch_val *val) -{ - struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev); - struct switch_port *port; - struct rtl8366_vlan_4k vlan4k; - int i; - - if (!smi->ops->is_vlan_valid(smi, val->port_vlan)) - return -EINVAL; - - smi->ops->get_vlan_4k(smi, val->port_vlan, &vlan4k); - - port = &val->value.ports[0]; - val->len = 0; - for (i = 0; i < smi->num_ports; i++) { - if (!(vlan4k.member & BIT(i))) - continue; - - port->id = i; - port->flags = (vlan4k.untag & BIT(i)) ? - 0 : BIT(SWITCH_PORT_FLAG_TAGGED); - val->len++; - port++; - } - return 0; -} -EXPORT_SYMBOL_GPL(rtl8366_sw_get_vlan_ports); - -int rtl8366_sw_set_vlan_ports(struct switch_dev *dev, struct switch_val *val) -{ - struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev); - struct switch_port *port; - u32 member = 0; - u32 untag = 0; - int err; - int i; - - if (!smi->ops->is_vlan_valid(smi, val->port_vlan)) - return -EINVAL; - - port = &val->value.ports[0]; - for (i = 0; i < val->len; i++, port++) { - int pvid = 0; - member |= BIT(port->id); - - if (!(port->flags & BIT(SWITCH_PORT_FLAG_TAGGED))) - untag |= BIT(port->id); - - /* - * To ensure that we have a valid MC entry for this VLAN, - * initialize the port VLAN ID here. - */ - err = rtl8366_get_pvid(smi, port->id, &pvid); - if (err < 0) - return err; - if (pvid == 0) { - err = rtl8366_set_pvid(smi, port->id, val->port_vlan); - if (err < 0) - return err; - } - } - - return rtl8366_set_vlan(smi, val->port_vlan, member, untag, 0); -} -EXPORT_SYMBOL_GPL(rtl8366_sw_set_vlan_ports); - -int rtl8366_sw_get_vlan_fid(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val) -{ - struct rtl8366_vlan_4k vlan4k; - struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev); - int err; - - if (!smi->ops->is_vlan_valid(smi, val->port_vlan)) - return -EINVAL; - - err = smi->ops->get_vlan_4k(smi, val->port_vlan, &vlan4k); - if (err) - return err; - - val->value.i = vlan4k.fid; - - return 0; -} -EXPORT_SYMBOL_GPL(rtl8366_sw_get_vlan_fid); - -int rtl8366_sw_set_vlan_fid(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val) -{ - struct rtl8366_vlan_4k vlan4k; - struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev); - int err; - - if (!smi->ops->is_vlan_valid(smi, val->port_vlan)) - return -EINVAL; - - if (val->value.i < 0 || val->value.i > attr->max) - return -EINVAL; - - err = smi->ops->get_vlan_4k(smi, val->port_vlan, &vlan4k); - if (err) - return err; - - return rtl8366_set_vlan(smi, val->port_vlan, - vlan4k.member, - vlan4k.untag, - val->value.i); -} -EXPORT_SYMBOL_GPL(rtl8366_sw_set_vlan_fid); - -int rtl8366_sw_get_vlan_enable(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val) -{ - struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev); - - if (attr->ofs > 2) - return -EINVAL; - - if (attr->ofs == 1) - val->value.i = smi->vlan_enabled; - else - val->value.i = smi->vlan4k_enabled; - - return 0; -} -EXPORT_SYMBOL_GPL(rtl8366_sw_get_vlan_enable); - -int rtl8366_sw_set_vlan_enable(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val) -{ - struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev); - int err; - - if (attr->ofs > 2) - return -EINVAL; - - if (attr->ofs == 1) - err = rtl8366_smi_enable_vlan(smi, val->value.i); - else - err = rtl8366_smi_enable_vlan4k(smi, val->value.i); - - return err; -} -EXPORT_SYMBOL_GPL(rtl8366_sw_set_vlan_enable); - -struct rtl8366_smi *rtl8366_smi_alloc(struct device *parent) -{ - struct rtl8366_smi *smi; - - BUG_ON(!parent); - - smi = kzalloc(sizeof(*smi), GFP_KERNEL); - if (!smi) { - dev_err(parent, "no memory for private data\n"); - return NULL; - } - - smi->parent = parent; - return smi; -} -EXPORT_SYMBOL_GPL(rtl8366_smi_alloc); - -static int __rtl8366_smi_init(struct rtl8366_smi *smi, const char *name) -{ - int err; - - if (!smi->ext_mbus) { - err = gpio_request(smi->gpio_sda, name); - if (err) { - printk(KERN_ERR "rtl8366_smi: gpio_request failed for %u, err=%d\n", - smi->gpio_sda, err); - goto err_out; - } - - err = gpio_request(smi->gpio_sck, name); - if (err) { - printk(KERN_ERR "rtl8366_smi: gpio_request failed for %u, err=%d\n", - smi->gpio_sck, err); - goto err_free_sda; - } - } - - spin_lock_init(&smi->lock); - - /* start the switch */ - if (smi->hw_reset) { - smi->hw_reset(smi, false); - msleep(RTL8366_SMI_HW_START_DELAY); - } - - return 0; - - err_free_sda: - gpio_free(smi->gpio_sda); - err_out: - return err; -} - -static void __rtl8366_smi_cleanup(struct rtl8366_smi *smi) -{ - if (smi->hw_reset) - smi->hw_reset(smi, true); - - if (!smi->ext_mbus) { - gpio_free(smi->gpio_sck); - gpio_free(smi->gpio_sda); - } -} - -enum rtl8366_type rtl8366_smi_detect(struct rtl8366_platform_data *pdata) -{ - static struct rtl8366_smi smi; - enum rtl8366_type type = RTL8366_TYPE_UNKNOWN; - u32 reg = 0; - - memset(&smi, 0, sizeof(smi)); - smi.gpio_sda = pdata->gpio_sda; - smi.gpio_sck = pdata->gpio_sck; - smi.clk_delay = 10; - smi.cmd_read = 0xa9; - smi.cmd_write = 0xa8; - - if (__rtl8366_smi_init(&smi, "rtl8366")) - goto out; - - if (rtl8366_smi_read_reg(&smi, 0x5c, ®)) - goto cleanup; - - switch(reg) { - case 0x6027: - printk("Found an RTL8366S switch\n"); - type = RTL8366_TYPE_S; - break; - case 0x5937: - printk("Found an RTL8366RB switch\n"); - type = RTL8366_TYPE_RB; - break; - default: - printk("Found an Unknown RTL8366 switch (id=0x%04x)\n", reg); - break; - } - -cleanup: - __rtl8366_smi_cleanup(&smi); -out: - return type; -} - -int rtl8366_smi_init(struct rtl8366_smi *smi) -{ - int err; - - if (!smi->ops) - return -EINVAL; - - err = __rtl8366_smi_init(smi, dev_name(smi->parent)); - if (err) - goto err_out; - - if (!smi->ext_mbus) - dev_info(smi->parent, "using GPIO pins %u (SDA) and %u (SCK)\n", - smi->gpio_sda, smi->gpio_sck); - else - dev_info(smi->parent, "using MDIO bus '%s'\n", smi->ext_mbus->name); - - err = smi->ops->detect(smi); - if (err) { - dev_err(smi->parent, "chip detection failed, err=%d\n", err); - goto err_free_sck; - } - - err = rtl8366_reset(smi); - if (err) - goto err_free_sck; - - err = smi->ops->setup(smi); - if (err) { - dev_err(smi->parent, "chip setup failed, err=%d\n", err); - goto err_free_sck; - } - - err = rtl8366_init_vlan(smi); - if (err) { - dev_err(smi->parent, "VLAN initialization failed, err=%d\n", - err); - goto err_free_sck; - } - - err = rtl8366_smi_enable_all_ports(smi, 1); - if (err) - goto err_free_sck; - - err = rtl8366_smi_mii_init(smi); - if (err) - goto err_free_sck; - - rtl8366_debugfs_init(smi); - - return 0; - - err_free_sck: - __rtl8366_smi_cleanup(smi); - err_out: - return err; -} -EXPORT_SYMBOL_GPL(rtl8366_smi_init); - -void rtl8366_smi_cleanup(struct rtl8366_smi *smi) -{ - rtl8366_debugfs_remove(smi); - rtl8366_smi_mii_cleanup(smi); - __rtl8366_smi_cleanup(smi); -} -EXPORT_SYMBOL_GPL(rtl8366_smi_cleanup); - -#ifdef CONFIG_OF -static void rtl8366_smi_reset(struct rtl8366_smi *smi, bool active) -{ - if (active) - reset_control_assert(smi->reset); - else - reset_control_deassert(smi->reset); -} - -int rtl8366_smi_probe_of(struct platform_device *pdev, struct rtl8366_smi *smi) -{ - int sck = of_get_named_gpio(pdev->dev.of_node, "gpio-sck", 0); - int sda = of_get_named_gpio(pdev->dev.of_node, "gpio-sda", 0); - struct device_node *np = pdev->dev.of_node; - struct device_node *mdio_node; - - mdio_node = of_parse_phandle(np, "mii-bus", 0); - if (!mdio_node) { - dev_err(&pdev->dev, "cannot find mdio node phandle"); - goto try_gpio; - } - - smi->ext_mbus = of_mdio_find_bus(mdio_node); - if (!smi->ext_mbus) { - dev_info(&pdev->dev, - "cannot find mdio bus from bus handle (yet)"); - goto try_gpio; - } - - if (of_property_read_u32(np, "phy-id", &smi->phy_id)) - smi->phy_id = MDC_REALTEK_PHY_ADDR; - - return 0; - -try_gpio: - if (!gpio_is_valid(sck) || !gpio_is_valid(sda)) { - if (!mdio_node) { - dev_err(&pdev->dev, "gpios missing in devictree\n"); - return -EINVAL; - } else { - return -EPROBE_DEFER; - } - } - - smi->gpio_sda = sda; - smi->gpio_sck = sck; - smi->reset = devm_reset_control_get(&pdev->dev, "switch"); - if (!IS_ERR(smi->reset)) - smi->hw_reset = rtl8366_smi_reset; - - return 0; -} -#else -static inline int rtl8366_smi_probe_of(struct platform_device *pdev, struct rtl8366_smi *smi) -{ - return -ENODEV; -} -#endif - -int rtl8366_smi_probe_plat(struct platform_device *pdev, struct rtl8366_smi *smi) -{ - struct rtl8366_platform_data *pdata = pdev->dev.platform_data; - - if (!pdev->dev.platform_data) { - dev_err(&pdev->dev, "no platform data specified\n"); - return -EINVAL; - } - - smi->gpio_sda = pdata->gpio_sda; - smi->gpio_sck = pdata->gpio_sck; - smi->hw_reset = pdata->hw_reset; - smi->phy_id = MDC_REALTEK_PHY_ADDR; - - return 0; -} - - -struct rtl8366_smi *rtl8366_smi_probe(struct platform_device *pdev) -{ - struct rtl8366_smi *smi; - int err; - - smi = rtl8366_smi_alloc(&pdev->dev); - if (!smi) - return NULL; - - if (pdev->dev.of_node) - err = rtl8366_smi_probe_of(pdev, smi); - else - err = rtl8366_smi_probe_plat(pdev, smi); - - if (err) - goto free_smi; - - return smi; - -free_smi: - kfree(smi); - return ERR_PTR(err); -} -EXPORT_SYMBOL_GPL(rtl8366_smi_probe); - -MODULE_DESCRIPTION("Realtek RTL8366 SMI interface driver"); -MODULE_AUTHOR("Gabor Juhos "); -MODULE_LICENSE("GPL v2"); diff --git a/target/linux/generic/files-6.12/drivers/net/phy/rtl8366_smi.h b/target/linux/generic/files-6.12/drivers/net/phy/rtl8366_smi.h deleted file mode 100644 index 2608240bb083b7..00000000000000 --- a/target/linux/generic/files-6.12/drivers/net/phy/rtl8366_smi.h +++ /dev/null @@ -1,171 +0,0 @@ -/* - * Realtek RTL8366 SMI interface driver defines - * - * Copyright (C) 2009-2010 Gabor Juhos - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published - * by the Free Software Foundation. - */ - -#ifndef _RTL8366_SMI_H -#define _RTL8366_SMI_H - -#include -#include -#include -#include - -struct rtl8366_smi_ops; -struct rtl8366_vlan_ops; -struct mii_bus; -struct dentry; -struct inode; -struct file; - -typedef enum rtl8367b_chip_e { - RTL8367B_CHIP_UNKNOWN, - /* Family B */ - RTL8367B_CHIP_RTL8367RB, - RTL8367B_CHIP_RTL8367R_VB, /* chip with exception in extif assignment */ -/* Family C */ - RTL8367B_CHIP_RTL8367RB_VB, - RTL8367B_CHIP_RTL8367S, -/* Family D */ - RTL8367B_CHIP_RTL8367S_VB /* chip with exception in extif assignment */ -} rtl8367b_chip_t; - -struct rtl8366_mib_counter { - unsigned base; - unsigned offset; - unsigned length; - const char *name; -}; - -struct rtl8366_smi { - struct device *parent; - unsigned int gpio_sda; - unsigned int gpio_sck; - void (*hw_reset)(struct rtl8366_smi *smi, bool active); - unsigned int clk_delay; /* ns */ - u8 cmd_read; - u8 cmd_write; - spinlock_t lock; - struct mii_bus *mii_bus; - int mii_irq[PHY_MAX_ADDR]; - struct switch_dev sw_dev; - - unsigned int cpu_port; - unsigned int num_ports; - unsigned int num_vlan_mc; - unsigned int num_mib_counters; - struct rtl8366_mib_counter *mib_counters; - - struct rtl8366_smi_ops *ops; - - int vlan_enabled; - int vlan4k_enabled; - - char buf[4096]; - - struct reset_control *reset; - -#ifdef CONFIG_RTL8366_SMI_DEBUG_FS - struct dentry *debugfs_root; - u16 dbg_reg; - u8 dbg_vlan_4k_page; -#endif - u32 phy_id; - rtl8367b_chip_t rtl8367b_chip; - struct mii_bus *ext_mbus; - struct rtl8366_vlan_mc *emu_vlanmc; -}; - -struct rtl8366_vlan_mc { - u16 vid; - u16 untag; - u16 member; - u8 fid; - u8 priority; -}; - -struct rtl8366_vlan_4k { - u16 vid; - u16 untag; - u16 member; - u8 fid; -}; - -struct rtl8366_smi_ops { - int (*detect)(struct rtl8366_smi *smi); - int (*reset_chip)(struct rtl8366_smi *smi); - int (*setup)(struct rtl8366_smi *smi); - - int (*mii_read)(struct mii_bus *bus, int addr, int reg); - int (*mii_write)(struct mii_bus *bus, int addr, int reg, u16 val); - - int (*get_vlan_mc)(struct rtl8366_smi *smi, u32 index, - struct rtl8366_vlan_mc *vlanmc); - int (*set_vlan_mc)(struct rtl8366_smi *smi, u32 index, - const struct rtl8366_vlan_mc *vlanmc); - int (*get_vlan_4k)(struct rtl8366_smi *smi, u32 vid, - struct rtl8366_vlan_4k *vlan4k); - int (*set_vlan_4k)(struct rtl8366_smi *smi, - const struct rtl8366_vlan_4k *vlan4k); - int (*get_mc_index)(struct rtl8366_smi *smi, int port, int *val); - int (*set_mc_index)(struct rtl8366_smi *smi, int port, int index); - int (*get_mib_counter)(struct rtl8366_smi *smi, int counter, - int port, unsigned long long *val); - int (*is_vlan_valid)(struct rtl8366_smi *smi, unsigned vlan); - int (*enable_vlan)(struct rtl8366_smi *smi, int enable); - int (*enable_vlan4k)(struct rtl8366_smi *smi, int enable); - int (*enable_port)(struct rtl8366_smi *smi, int port, int enable); -}; - -struct rtl8366_smi *rtl8366_smi_alloc(struct device *parent); -int rtl8366_smi_init(struct rtl8366_smi *smi); -void rtl8366_smi_cleanup(struct rtl8366_smi *smi); -int rtl8366_smi_write_reg(struct rtl8366_smi *smi, u32 addr, u32 data); -int rtl8366_smi_write_reg_noack(struct rtl8366_smi *smi, u32 addr, u32 data); -int rtl8366_smi_read_reg(struct rtl8366_smi *smi, u32 addr, u32 *data); -int rtl8366_smi_rmwr(struct rtl8366_smi *smi, u32 addr, u32 mask, u32 data); - -#ifdef CONFIG_RTL8366_SMI_DEBUG_FS -int rtl8366_debugfs_open(struct inode *inode, struct file *file); -#endif - -static inline struct rtl8366_smi *sw_to_rtl8366_smi(struct switch_dev *sw) -{ - return container_of(sw, struct rtl8366_smi, sw_dev); -} - -int rtl8366_sw_reset_switch(struct switch_dev *dev); -int rtl8366_sw_get_port_pvid(struct switch_dev *dev, int port, int *val); -int rtl8366_sw_set_port_pvid(struct switch_dev *dev, int port, int val); -int rtl8366_sw_get_port_mib(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val); -int rtl8366_sw_get_vlan_info(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val); -int rtl8366_sw_get_vlan_fid(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val); -int rtl8366_sw_set_vlan_fid(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val); -int rtl8366_sw_get_vlan_ports(struct switch_dev *dev, struct switch_val *val); -int rtl8366_sw_set_vlan_ports(struct switch_dev *dev, struct switch_val *val); -int rtl8366_sw_get_vlan_enable(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val); -int rtl8366_sw_set_vlan_enable(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val); -int rtl8366_sw_get_port_stats(struct switch_dev *dev, int port, - struct switch_port_stats *stats, - int txb_id, int rxb_id); - -struct rtl8366_smi* rtl8366_smi_probe(struct platform_device *pdev); - -#endif /* _RTL8366_SMI_H */ diff --git a/target/linux/generic/files-6.12/drivers/net/phy/rtl8366rb.c b/target/linux/generic/files-6.12/drivers/net/phy/rtl8366rb.c deleted file mode 100644 index 0e0116051a8cb3..00000000000000 --- a/target/linux/generic/files-6.12/drivers/net/phy/rtl8366rb.c +++ /dev/null @@ -1,1532 +0,0 @@ -/* - * Platform driver for the Realtek RTL8366RB ethernet switch - * - * Copyright (C) 2009-2010 Gabor Juhos - * Copyright (C) 2010 Antti Seppälä - * Copyright (C) 2010 Roman Yeryomin - * Copyright (C) 2011 Colin Leitner - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published - * by the Free Software Foundation. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "rtl8366_smi.h" - -#define RTL8366RB_DRIVER_DESC "Realtek RTL8366RB ethernet switch driver" -#define RTL8366RB_DRIVER_VER "0.2.4" - -#define RTL8366RB_PHY_NO_MAX 4 -#define RTL8366RB_PHY_PAGE_MAX 7 -#define RTL8366RB_PHY_ADDR_MAX 31 - -/* Switch Global Configuration register */ -#define RTL8366RB_SGCR 0x0000 -#define RTL8366RB_SGCR_EN_BC_STORM_CTRL BIT(0) -#define RTL8366RB_SGCR_MAX_LENGTH(_x) (_x << 4) -#define RTL8366RB_SGCR_MAX_LENGTH_MASK RTL8366RB_SGCR_MAX_LENGTH(0x3) -#define RTL8366RB_SGCR_MAX_LENGTH_1522 RTL8366RB_SGCR_MAX_LENGTH(0x0) -#define RTL8366RB_SGCR_MAX_LENGTH_1536 RTL8366RB_SGCR_MAX_LENGTH(0x1) -#define RTL8366RB_SGCR_MAX_LENGTH_1552 RTL8366RB_SGCR_MAX_LENGTH(0x2) -#define RTL8366RB_SGCR_MAX_LENGTH_9216 RTL8366RB_SGCR_MAX_LENGTH(0x3) -#define RTL8366RB_SGCR_EN_VLAN BIT(13) -#define RTL8366RB_SGCR_EN_VLAN_4KTB BIT(14) - -/* Port Enable Control register */ -#define RTL8366RB_PECR 0x0001 - -/* Port Mirror Control Register */ -#define RTL8366RB_PMCR 0x0007 -#define RTL8366RB_PMCR_SOURCE_PORT(_x) (_x) -#define RTL8366RB_PMCR_SOURCE_PORT_MASK 0x000f -#define RTL8366RB_PMCR_MONITOR_PORT(_x) ((_x) << 4) -#define RTL8366RB_PMCR_MONITOR_PORT_MASK 0x00f0 -#define RTL8366RB_PMCR_MIRROR_RX BIT(8) -#define RTL8366RB_PMCR_MIRROR_TX BIT(9) -#define RTL8366RB_PMCR_MIRROR_SPC BIT(10) -#define RTL8366RB_PMCR_MIRROR_ISO BIT(11) - -/* Switch Security Control registers */ -#define RTL8366RB_SSCR0 0x0002 -#define RTL8366RB_SSCR1 0x0003 -#define RTL8366RB_SSCR2 0x0004 -#define RTL8366RB_SSCR2_DROP_UNKNOWN_DA BIT(0) - -#define RTL8366RB_RESET_CTRL_REG 0x0100 -#define RTL8366RB_CHIP_CTRL_RESET_HW 1 -#define RTL8366RB_CHIP_CTRL_RESET_SW (1 << 1) - -#define RTL8366RB_CHIP_VERSION_CTRL_REG 0x050A -#define RTL8366RB_CHIP_VERSION_MASK 0xf -#define RTL8366RB_CHIP_ID_REG 0x0509 -#define RTL8366RB_CHIP_ID_8366 0x5937 - -/* PHY registers control */ -#define RTL8366RB_PHY_ACCESS_CTRL_REG 0x8000 -#define RTL8366RB_PHY_ACCESS_DATA_REG 0x8002 - -#define RTL8366RB_PHY_CTRL_READ 1 -#define RTL8366RB_PHY_CTRL_WRITE 0 - -#define RTL8366RB_PHY_REG_MASK 0x1f -#define RTL8366RB_PHY_PAGE_OFFSET 5 -#define RTL8366RB_PHY_PAGE_MASK (0xf << 5) -#define RTL8366RB_PHY_NO_OFFSET 9 -#define RTL8366RB_PHY_NO_MASK (0x1f << 9) - -#define RTL8366RB_VLAN_INGRESS_CTRL2_REG 0x037f - -/* LED control registers */ -#define RTL8366RB_LED_BLINKRATE_REG 0x0430 -#define RTL8366RB_LED_BLINKRATE_BIT 0 -#define RTL8366RB_LED_BLINKRATE_MASK 0x0007 - -#define RTL8366RB_LED_CTRL_REG 0x0431 -#define RTL8366RB_LED_0_1_CTRL_REG 0x0432 -#define RTL8366RB_LED_2_3_CTRL_REG 0x0433 - -#define RTL8366RB_MIB_COUNT 33 -#define RTL8366RB_GLOBAL_MIB_COUNT 1 -#define RTL8366RB_MIB_COUNTER_PORT_OFFSET 0x0050 -#define RTL8366RB_MIB_COUNTER_BASE 0x1000 -#define RTL8366RB_MIB_CTRL_REG 0x13F0 -#define RTL8366RB_MIB_CTRL_USER_MASK 0x0FFC -#define RTL8366RB_MIB_CTRL_BUSY_MASK BIT(0) -#define RTL8366RB_MIB_CTRL_RESET_MASK BIT(1) -#define RTL8366RB_MIB_CTRL_PORT_RESET(_p) BIT(2 + (_p)) -#define RTL8366RB_MIB_CTRL_GLOBAL_RESET BIT(11) - -#define RTL8366RB_PORT_VLAN_CTRL_BASE 0x0063 -#define RTL8366RB_PORT_VLAN_CTRL_REG(_p) \ - (RTL8366RB_PORT_VLAN_CTRL_BASE + (_p) / 4) -#define RTL8366RB_PORT_VLAN_CTRL_MASK 0xf -#define RTL8366RB_PORT_VLAN_CTRL_SHIFT(_p) (4 * ((_p) % 4)) - - -#define RTL8366RB_VLAN_TABLE_READ_BASE 0x018C -#define RTL8366RB_VLAN_TABLE_WRITE_BASE 0x0185 - - -#define RTL8366RB_TABLE_ACCESS_CTRL_REG 0x0180 -#define RTL8366RB_TABLE_VLAN_READ_CTRL 0x0E01 -#define RTL8366RB_TABLE_VLAN_WRITE_CTRL 0x0F01 - -#define RTL8366RB_VLAN_MC_BASE(_x) (0x0020 + (_x) * 3) - - -#define RTL8366RB_PORT_LINK_STATUS_BASE 0x0014 -#define RTL8366RB_PORT_STATUS_SPEED_MASK 0x0003 -#define RTL8366RB_PORT_STATUS_DUPLEX_MASK 0x0004 -#define RTL8366RB_PORT_STATUS_LINK_MASK 0x0010 -#define RTL8366RB_PORT_STATUS_TXPAUSE_MASK 0x0020 -#define RTL8366RB_PORT_STATUS_RXPAUSE_MASK 0x0040 -#define RTL8366RB_PORT_STATUS_AN_MASK 0x0080 - - -#define RTL8366RB_PORT_NUM_CPU 5 -#define RTL8366RB_NUM_PORTS 6 -#define RTL8366RB_NUM_VLANS 16 -#define RTL8366RB_NUM_LEDGROUPS 4 -#define RTL8366RB_NUM_VIDS 4096 -#define RTL8366RB_PRIORITYMAX 7 -#define RTL8366RB_FIDMAX 7 - - -#define RTL8366RB_PORT_1 (1 << 0) /* In userspace port 0 */ -#define RTL8366RB_PORT_2 (1 << 1) /* In userspace port 1 */ -#define RTL8366RB_PORT_3 (1 << 2) /* In userspace port 2 */ -#define RTL8366RB_PORT_4 (1 << 3) /* In userspace port 3 */ -#define RTL8366RB_PORT_5 (1 << 4) /* In userspace port 4 */ - -#define RTL8366RB_PORT_CPU (1 << 5) /* CPU port */ - -#define RTL8366RB_PORT_ALL (RTL8366RB_PORT_1 | \ - RTL8366RB_PORT_2 | \ - RTL8366RB_PORT_3 | \ - RTL8366RB_PORT_4 | \ - RTL8366RB_PORT_5 | \ - RTL8366RB_PORT_CPU) - -#define RTL8366RB_PORT_ALL_BUT_CPU (RTL8366RB_PORT_1 | \ - RTL8366RB_PORT_2 | \ - RTL8366RB_PORT_3 | \ - RTL8366RB_PORT_4 | \ - RTL8366RB_PORT_5) - -#define RTL8366RB_PORT_ALL_EXTERNAL (RTL8366RB_PORT_1 | \ - RTL8366RB_PORT_2 | \ - RTL8366RB_PORT_3 | \ - RTL8366RB_PORT_4) - -#define RTL8366RB_PORT_ALL_INTERNAL RTL8366RB_PORT_CPU - -#define RTL8366RB_VLAN_VID_MASK 0xfff -#define RTL8366RB_VLAN_PRIORITY_SHIFT 12 -#define RTL8366RB_VLAN_PRIORITY_MASK 0x7 -#define RTL8366RB_VLAN_UNTAG_SHIFT 8 -#define RTL8366RB_VLAN_UNTAG_MASK 0xff -#define RTL8366RB_VLAN_MEMBER_MASK 0xff -#define RTL8366RB_VLAN_FID_MASK 0x7 - - -/* Port ingress bandwidth control */ -#define RTL8366RB_IB_BASE 0x0200 -#define RTL8366RB_IB_REG(pnum) (RTL8366RB_IB_BASE + pnum) -#define RTL8366RB_IB_BDTH_MASK 0x3fff -#define RTL8366RB_IB_PREIFG_OFFSET 14 -#define RTL8366RB_IB_PREIFG_MASK (1 << RTL8366RB_IB_PREIFG_OFFSET) - -/* Port egress bandwidth control */ -#define RTL8366RB_EB_BASE 0x02d1 -#define RTL8366RB_EB_REG(pnum) (RTL8366RB_EB_BASE + pnum) -#define RTL8366RB_EB_BDTH_MASK 0x3fff -#define RTL8366RB_EB_PREIFG_REG 0x02f8 -#define RTL8366RB_EB_PREIFG_OFFSET 9 -#define RTL8366RB_EB_PREIFG_MASK (1 << RTL8366RB_EB_PREIFG_OFFSET) - -#define RTL8366RB_BDTH_SW_MAX 1048512 -#define RTL8366RB_BDTH_UNIT 64 -#define RTL8366RB_BDTH_REG_DEFAULT 16383 - -/* QOS */ -#define RTL8366RB_QOS_BIT 15 -#define RTL8366RB_QOS_MASK (1 << RTL8366RB_QOS_BIT) -/* Include/Exclude Preamble and IFG (20 bytes). 0:Exclude, 1:Include. */ -#define RTL8366RB_QOS_DEFAULT_PREIFG 1 - - -#define RTL8366RB_MIB_RXB_ID 0 /* IfInOctets */ -#define RTL8366RB_MIB_TXB_ID 20 /* IfOutOctets */ - -static struct rtl8366_mib_counter rtl8366rb_mib_counters[] = { - { 0, 0, 4, "IfInOctets" }, - { 0, 4, 4, "EtherStatsOctets" }, - { 0, 8, 2, "EtherStatsUnderSizePkts" }, - { 0, 10, 2, "EtherFragments" }, - { 0, 12, 2, "EtherStatsPkts64Octets" }, - { 0, 14, 2, "EtherStatsPkts65to127Octets" }, - { 0, 16, 2, "EtherStatsPkts128to255Octets" }, - { 0, 18, 2, "EtherStatsPkts256to511Octets" }, - { 0, 20, 2, "EtherStatsPkts512to1023Octets" }, - { 0, 22, 2, "EtherStatsPkts1024to1518Octets" }, - { 0, 24, 2, "EtherOversizeStats" }, - { 0, 26, 2, "EtherStatsJabbers" }, - { 0, 28, 2, "IfInUcastPkts" }, - { 0, 30, 2, "EtherStatsMulticastPkts" }, - { 0, 32, 2, "EtherStatsBroadcastPkts" }, - { 0, 34, 2, "EtherStatsDropEvents" }, - { 0, 36, 2, "Dot3StatsFCSErrors" }, - { 0, 38, 2, "Dot3StatsSymbolErrors" }, - { 0, 40, 2, "Dot3InPauseFrames" }, - { 0, 42, 2, "Dot3ControlInUnknownOpcodes" }, - { 0, 44, 4, "IfOutOctets" }, - { 0, 48, 2, "Dot3StatsSingleCollisionFrames" }, - { 0, 50, 2, "Dot3StatMultipleCollisionFrames" }, - { 0, 52, 2, "Dot3sDeferredTransmissions" }, - { 0, 54, 2, "Dot3StatsLateCollisions" }, - { 0, 56, 2, "EtherStatsCollisions" }, - { 0, 58, 2, "Dot3StatsExcessiveCollisions" }, - { 0, 60, 2, "Dot3OutPauseFrames" }, - { 0, 62, 2, "Dot1dBasePortDelayExceededDiscards" }, - { 0, 64, 2, "Dot1dTpPortInDiscards" }, - { 0, 66, 2, "IfOutUcastPkts" }, - { 0, 68, 2, "IfOutMulticastPkts" }, - { 0, 70, 2, "IfOutBroadcastPkts" }, -}; - -#define REG_WR(_smi, _reg, _val) \ - do { \ - err = rtl8366_smi_write_reg(_smi, _reg, _val); \ - if (err) \ - return err; \ - } while (0) - -#define REG_RMW(_smi, _reg, _mask, _val) \ - do { \ - err = rtl8366_smi_rmwr(_smi, _reg, _mask, _val); \ - if (err) \ - return err; \ - } while (0) - -static int rtl8366rb_reset_chip(struct rtl8366_smi *smi) -{ - int timeout = 10; - u32 data; - - rtl8366_smi_write_reg_noack(smi, RTL8366RB_RESET_CTRL_REG, - RTL8366RB_CHIP_CTRL_RESET_HW); - do { - msleep(1); - if (rtl8366_smi_read_reg(smi, RTL8366RB_RESET_CTRL_REG, &data)) - return -EIO; - - if (!(data & RTL8366RB_CHIP_CTRL_RESET_HW)) - break; - } while (--timeout); - - if (!timeout) { - printk("Timeout waiting for the switch to reset\n"); - return -EIO; - } - - return 0; -} - -static int rtl8366rb_setup(struct rtl8366_smi *smi) -{ - int err; -#ifdef CONFIG_OF - unsigned i; - struct device_node *np; - unsigned num_initvals; - const __be32 *paddr; - - np = smi->parent->of_node; - - paddr = of_get_property(np, "realtek,initvals", &num_initvals); - if (paddr) { - dev_info(smi->parent, "applying initvals from DTS\n"); - - if (num_initvals < (2 * sizeof(*paddr))) - return -EINVAL; - - num_initvals /= sizeof(*paddr); - - for (i = 0; i < num_initvals - 1; i += 2) { - u32 reg = be32_to_cpup(paddr + i); - u32 val = be32_to_cpup(paddr + i + 1); - - REG_WR(smi, reg, val); - } - } -#endif - - /* set maximum packet length to 1536 bytes */ - REG_RMW(smi, RTL8366RB_SGCR, RTL8366RB_SGCR_MAX_LENGTH_MASK, - RTL8366RB_SGCR_MAX_LENGTH_1536); - - /* enable learning for all ports */ - REG_WR(smi, RTL8366RB_SSCR0, 0); - - /* enable auto ageing for all ports */ - REG_WR(smi, RTL8366RB_SSCR1, 0); - - /* - * discard VLAN tagged packets if the port is not a member of - * the VLAN with which the packets is associated. - */ - REG_WR(smi, RTL8366RB_VLAN_INGRESS_CTRL2_REG, RTL8366RB_PORT_ALL); - - /* don't drop packets whose DA has not been learned */ - REG_RMW(smi, RTL8366RB_SSCR2, RTL8366RB_SSCR2_DROP_UNKNOWN_DA, 0); - - return 0; -} - -static int rtl8366rb_read_phy_reg(struct rtl8366_smi *smi, - u32 phy_no, u32 page, u32 addr, u32 *data) -{ - u32 reg; - int ret; - - if (phy_no > RTL8366RB_PHY_NO_MAX) - return -EINVAL; - - if (page > RTL8366RB_PHY_PAGE_MAX) - return -EINVAL; - - if (addr > RTL8366RB_PHY_ADDR_MAX) - return -EINVAL; - - ret = rtl8366_smi_write_reg(smi, RTL8366RB_PHY_ACCESS_CTRL_REG, - RTL8366RB_PHY_CTRL_READ); - if (ret) - return ret; - - reg = 0x8000 | (1 << (phy_no + RTL8366RB_PHY_NO_OFFSET)) | - ((page << RTL8366RB_PHY_PAGE_OFFSET) & RTL8366RB_PHY_PAGE_MASK) | - (addr & RTL8366RB_PHY_REG_MASK); - - ret = rtl8366_smi_write_reg(smi, reg, 0); - if (ret) - return ret; - - ret = rtl8366_smi_read_reg(smi, RTL8366RB_PHY_ACCESS_DATA_REG, data); - if (ret) - return ret; - - return 0; -} - -static int rtl8366rb_write_phy_reg(struct rtl8366_smi *smi, - u32 phy_no, u32 page, u32 addr, u32 data) -{ - u32 reg; - int ret; - - if (phy_no > RTL8366RB_PHY_NO_MAX) - return -EINVAL; - - if (page > RTL8366RB_PHY_PAGE_MAX) - return -EINVAL; - - if (addr > RTL8366RB_PHY_ADDR_MAX) - return -EINVAL; - - ret = rtl8366_smi_write_reg(smi, RTL8366RB_PHY_ACCESS_CTRL_REG, - RTL8366RB_PHY_CTRL_WRITE); - if (ret) - return ret; - - reg = 0x8000 | (1 << (phy_no + RTL8366RB_PHY_NO_OFFSET)) | - ((page << RTL8366RB_PHY_PAGE_OFFSET) & RTL8366RB_PHY_PAGE_MASK) | - (addr & RTL8366RB_PHY_REG_MASK); - - ret = rtl8366_smi_write_reg(smi, reg, data); - if (ret) - return ret; - - return 0; -} - -static int rtl8366rb_get_mib_counter(struct rtl8366_smi *smi, int counter, - int port, unsigned long long *val) -{ - int i; - int err; - u32 addr, data; - u64 mibvalue; - - if (port > RTL8366RB_NUM_PORTS || counter >= RTL8366RB_MIB_COUNT) - return -EINVAL; - - addr = RTL8366RB_MIB_COUNTER_BASE + - RTL8366RB_MIB_COUNTER_PORT_OFFSET * (port) + - rtl8366rb_mib_counters[counter].offset; - - /* - * Writing access counter address first - * then ASIC will prepare 64bits counter wait for being retrived - */ - data = 0; /* writing data will be discard by ASIC */ - err = rtl8366_smi_write_reg(smi, addr, data); - if (err) - return err; - - /* read MIB control register */ - err = rtl8366_smi_read_reg(smi, RTL8366RB_MIB_CTRL_REG, &data); - if (err) - return err; - - if (data & RTL8366RB_MIB_CTRL_BUSY_MASK) - return -EBUSY; - - if (data & RTL8366RB_MIB_CTRL_RESET_MASK) - return -EIO; - - mibvalue = 0; - for (i = rtl8366rb_mib_counters[counter].length; i > 0; i--) { - err = rtl8366_smi_read_reg(smi, addr + (i - 1), &data); - if (err) - return err; - - mibvalue = (mibvalue << 16) | (data & 0xFFFF); - } - - *val = mibvalue; - return 0; -} - -static int rtl8366rb_get_vlan_4k(struct rtl8366_smi *smi, u32 vid, - struct rtl8366_vlan_4k *vlan4k) -{ - u32 data[3]; - int err; - int i; - - memset(vlan4k, '\0', sizeof(struct rtl8366_vlan_4k)); - - if (vid >= RTL8366RB_NUM_VIDS) - return -EINVAL; - - /* write VID */ - err = rtl8366_smi_write_reg(smi, RTL8366RB_VLAN_TABLE_WRITE_BASE, - vid & RTL8366RB_VLAN_VID_MASK); - if (err) - return err; - - /* write table access control word */ - err = rtl8366_smi_write_reg(smi, RTL8366RB_TABLE_ACCESS_CTRL_REG, - RTL8366RB_TABLE_VLAN_READ_CTRL); - if (err) - return err; - - for (i = 0; i < 3; i++) { - err = rtl8366_smi_read_reg(smi, - RTL8366RB_VLAN_TABLE_READ_BASE + i, - &data[i]); - if (err) - return err; - } - - vlan4k->vid = vid; - vlan4k->untag = (data[1] >> RTL8366RB_VLAN_UNTAG_SHIFT) & - RTL8366RB_VLAN_UNTAG_MASK; - vlan4k->member = data[1] & RTL8366RB_VLAN_MEMBER_MASK; - vlan4k->fid = data[2] & RTL8366RB_VLAN_FID_MASK; - - return 0; -} - -static int rtl8366rb_set_vlan_4k(struct rtl8366_smi *smi, - const struct rtl8366_vlan_4k *vlan4k) -{ - u32 data[3]; - int err; - int i; - - if (vlan4k->vid >= RTL8366RB_NUM_VIDS || - vlan4k->member > RTL8366RB_VLAN_MEMBER_MASK || - vlan4k->untag > RTL8366RB_VLAN_UNTAG_MASK || - vlan4k->fid > RTL8366RB_FIDMAX) - return -EINVAL; - - data[0] = vlan4k->vid & RTL8366RB_VLAN_VID_MASK; - data[1] = (vlan4k->member & RTL8366RB_VLAN_MEMBER_MASK) | - ((vlan4k->untag & RTL8366RB_VLAN_UNTAG_MASK) << - RTL8366RB_VLAN_UNTAG_SHIFT); - data[2] = vlan4k->fid & RTL8366RB_VLAN_FID_MASK; - - for (i = 0; i < 3; i++) { - err = rtl8366_smi_write_reg(smi, - RTL8366RB_VLAN_TABLE_WRITE_BASE + i, - data[i]); - if (err) - return err; - } - - /* write table access control word */ - err = rtl8366_smi_write_reg(smi, RTL8366RB_TABLE_ACCESS_CTRL_REG, - RTL8366RB_TABLE_VLAN_WRITE_CTRL); - - return err; -} - -static int rtl8366rb_get_vlan_mc(struct rtl8366_smi *smi, u32 index, - struct rtl8366_vlan_mc *vlanmc) -{ - u32 data[3]; - int err; - int i; - - memset(vlanmc, '\0', sizeof(struct rtl8366_vlan_mc)); - - if (index >= RTL8366RB_NUM_VLANS) - return -EINVAL; - - for (i = 0; i < 3; i++) { - err = rtl8366_smi_read_reg(smi, - RTL8366RB_VLAN_MC_BASE(index) + i, - &data[i]); - if (err) - return err; - } - - vlanmc->vid = data[0] & RTL8366RB_VLAN_VID_MASK; - vlanmc->priority = (data[0] >> RTL8366RB_VLAN_PRIORITY_SHIFT) & - RTL8366RB_VLAN_PRIORITY_MASK; - vlanmc->untag = (data[1] >> RTL8366RB_VLAN_UNTAG_SHIFT) & - RTL8366RB_VLAN_UNTAG_MASK; - vlanmc->member = data[1] & RTL8366RB_VLAN_MEMBER_MASK; - vlanmc->fid = data[2] & RTL8366RB_VLAN_FID_MASK; - - return 0; -} - -static int rtl8366rb_set_vlan_mc(struct rtl8366_smi *smi, u32 index, - const struct rtl8366_vlan_mc *vlanmc) -{ - u32 data[3]; - int err; - int i; - - if (index >= RTL8366RB_NUM_VLANS || - vlanmc->vid >= RTL8366RB_NUM_VIDS || - vlanmc->priority > RTL8366RB_PRIORITYMAX || - vlanmc->member > RTL8366RB_VLAN_MEMBER_MASK || - vlanmc->untag > RTL8366RB_VLAN_UNTAG_MASK || - vlanmc->fid > RTL8366RB_FIDMAX) - return -EINVAL; - - data[0] = (vlanmc->vid & RTL8366RB_VLAN_VID_MASK) | - ((vlanmc->priority & RTL8366RB_VLAN_PRIORITY_MASK) << - RTL8366RB_VLAN_PRIORITY_SHIFT); - data[1] = (vlanmc->member & RTL8366RB_VLAN_MEMBER_MASK) | - ((vlanmc->untag & RTL8366RB_VLAN_UNTAG_MASK) << - RTL8366RB_VLAN_UNTAG_SHIFT); - data[2] = vlanmc->fid & RTL8366RB_VLAN_FID_MASK; - - for (i = 0; i < 3; i++) { - err = rtl8366_smi_write_reg(smi, - RTL8366RB_VLAN_MC_BASE(index) + i, - data[i]); - if (err) - return err; - } - - return 0; -} - -static int rtl8366rb_get_mc_index(struct rtl8366_smi *smi, int port, int *val) -{ - u32 data; - int err; - - if (port >= RTL8366RB_NUM_PORTS) - return -EINVAL; - - err = rtl8366_smi_read_reg(smi, RTL8366RB_PORT_VLAN_CTRL_REG(port), - &data); - if (err) - return err; - - *val = (data >> RTL8366RB_PORT_VLAN_CTRL_SHIFT(port)) & - RTL8366RB_PORT_VLAN_CTRL_MASK; - - return 0; - -} - -static int rtl8366rb_set_mc_index(struct rtl8366_smi *smi, int port, int index) -{ - if (port >= RTL8366RB_NUM_PORTS || index >= RTL8366RB_NUM_VLANS) - return -EINVAL; - - return rtl8366_smi_rmwr(smi, RTL8366RB_PORT_VLAN_CTRL_REG(port), - RTL8366RB_PORT_VLAN_CTRL_MASK << - RTL8366RB_PORT_VLAN_CTRL_SHIFT(port), - (index & RTL8366RB_PORT_VLAN_CTRL_MASK) << - RTL8366RB_PORT_VLAN_CTRL_SHIFT(port)); -} - -static int rtl8366rb_is_vlan_valid(struct rtl8366_smi *smi, unsigned vlan) -{ - unsigned max = RTL8366RB_NUM_VLANS; - - if (smi->vlan4k_enabled) - max = RTL8366RB_NUM_VIDS - 1; - - if (vlan == 0 || vlan >= max) - return 0; - - return 1; -} - -static int rtl8366rb_enable_vlan(struct rtl8366_smi *smi, int enable) -{ - return rtl8366_smi_rmwr(smi, RTL8366RB_SGCR, RTL8366RB_SGCR_EN_VLAN, - (enable) ? RTL8366RB_SGCR_EN_VLAN : 0); -} - -static int rtl8366rb_enable_vlan4k(struct rtl8366_smi *smi, int enable) -{ - return rtl8366_smi_rmwr(smi, RTL8366RB_SGCR, - RTL8366RB_SGCR_EN_VLAN_4KTB, - (enable) ? RTL8366RB_SGCR_EN_VLAN_4KTB : 0); -} - -static int rtl8366rb_enable_port(struct rtl8366_smi *smi, int port, int enable) -{ - return rtl8366_smi_rmwr(smi, RTL8366RB_PECR, (1 << port), - (enable) ? 0 : (1 << port)); -} - -static int rtl8366rb_sw_reset_mibs(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val) -{ - struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev); - - return rtl8366_smi_rmwr(smi, RTL8366RB_MIB_CTRL_REG, 0, - RTL8366RB_MIB_CTRL_GLOBAL_RESET); -} - -static int rtl8366rb_sw_get_blinkrate(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val) -{ - struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev); - u32 data; - - rtl8366_smi_read_reg(smi, RTL8366RB_LED_BLINKRATE_REG, &data); - - val->value.i = (data & (RTL8366RB_LED_BLINKRATE_MASK)); - - return 0; -} - -static int rtl8366rb_sw_set_blinkrate(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val) -{ - struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev); - - if (val->value.i >= 6) - return -EINVAL; - - return rtl8366_smi_rmwr(smi, RTL8366RB_LED_BLINKRATE_REG, - RTL8366RB_LED_BLINKRATE_MASK, - val->value.i); -} - -static int rtl8366rb_sw_get_learning_enable(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val) -{ - struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev); - u32 data; - - rtl8366_smi_read_reg(smi, RTL8366RB_SSCR0, &data); - val->value.i = !data; - - return 0; -} - - -static int rtl8366rb_sw_set_learning_enable(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val) -{ - struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev); - u32 portmask = 0; - int err = 0; - - if (!val->value.i) - portmask = RTL8366RB_PORT_ALL; - - /* set learning for all ports */ - REG_WR(smi, RTL8366RB_SSCR0, portmask); - - /* set auto ageing for all ports */ - REG_WR(smi, RTL8366RB_SSCR1, portmask); - - return 0; -} - -static int rtl8366rb_sw_get_port_link(struct switch_dev *dev, - int port, - struct switch_port_link *link) -{ - struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev); - u32 data = 0; - u32 speed; - - if (port >= RTL8366RB_NUM_PORTS) - return -EINVAL; - - rtl8366_smi_read_reg(smi, RTL8366RB_PORT_LINK_STATUS_BASE + (port / 2), - &data); - - if (port % 2) - data = data >> 8; - - link->link = !!(data & RTL8366RB_PORT_STATUS_LINK_MASK); - if (!link->link) - return 0; - - link->duplex = !!(data & RTL8366RB_PORT_STATUS_DUPLEX_MASK); - link->rx_flow = !!(data & RTL8366RB_PORT_STATUS_RXPAUSE_MASK); - link->tx_flow = !!(data & RTL8366RB_PORT_STATUS_TXPAUSE_MASK); - link->aneg = !!(data & RTL8366RB_PORT_STATUS_AN_MASK); - - speed = (data & RTL8366RB_PORT_STATUS_SPEED_MASK); - switch (speed) { - case 0: - link->speed = SWITCH_PORT_SPEED_10; - break; - case 1: - link->speed = SWITCH_PORT_SPEED_100; - break; - case 2: - link->speed = SWITCH_PORT_SPEED_1000; - break; - default: - link->speed = SWITCH_PORT_SPEED_UNKNOWN; - break; - } - - return 0; -} - -static int rtl8366rb_sw_set_port_led(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val) -{ - struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev); - u32 data; - u32 mask; - u32 reg; - - if (val->port_vlan >= RTL8366RB_NUM_PORTS) - return -EINVAL; - - if (val->port_vlan == RTL8366RB_PORT_NUM_CPU) { - reg = RTL8366RB_LED_BLINKRATE_REG; - mask = 0xF << 4; - data = val->value.i << 4; - } else { - reg = RTL8366RB_LED_CTRL_REG; - mask = 0xF << (val->port_vlan * 4), - data = val->value.i << (val->port_vlan * 4); - } - - return rtl8366_smi_rmwr(smi, reg, mask, data); -} - -static int rtl8366rb_sw_get_port_led(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val) -{ - struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev); - u32 data = 0; - - if (val->port_vlan >= RTL8366RB_NUM_LEDGROUPS) - return -EINVAL; - - rtl8366_smi_read_reg(smi, RTL8366RB_LED_CTRL_REG, &data); - val->value.i = (data >> (val->port_vlan * 4)) & 0x000F; - - return 0; -} - -static int rtl8366rb_sw_set_port_disable(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val) -{ - struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev); - u32 mask, data; - - if (val->port_vlan >= RTL8366RB_NUM_PORTS) - return -EINVAL; - - mask = 1 << val->port_vlan ; - if (val->value.i) - data = mask; - else - data = 0; - - return rtl8366_smi_rmwr(smi, RTL8366RB_PECR, mask, data); -} - -static int rtl8366rb_sw_get_port_disable(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val) -{ - struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev); - u32 data; - - if (val->port_vlan >= RTL8366RB_NUM_PORTS) - return -EINVAL; - - rtl8366_smi_read_reg(smi, RTL8366RB_PECR, &data); - if (data & (1 << val->port_vlan)) - val->value.i = 1; - else - val->value.i = 0; - - return 0; -} - -static int rtl8366rb_sw_set_port_rate_in(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val) -{ - struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev); - - if (val->port_vlan >= RTL8366RB_NUM_PORTS) - return -EINVAL; - - if (val->value.i > 0 && val->value.i < RTL8366RB_BDTH_SW_MAX) - val->value.i = (val->value.i - 1) / RTL8366RB_BDTH_UNIT; - else - val->value.i = RTL8366RB_BDTH_REG_DEFAULT; - - return rtl8366_smi_rmwr(smi, RTL8366RB_IB_REG(val->port_vlan), - RTL8366RB_IB_BDTH_MASK | RTL8366RB_IB_PREIFG_MASK, - val->value.i | - (RTL8366RB_QOS_DEFAULT_PREIFG << RTL8366RB_IB_PREIFG_OFFSET)); - -} - -static int rtl8366rb_sw_get_port_rate_in(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val) -{ - struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev); - u32 data; - - if (val->port_vlan >= RTL8366RB_NUM_PORTS) - return -EINVAL; - - rtl8366_smi_read_reg(smi, RTL8366RB_IB_REG(val->port_vlan), &data); - data &= RTL8366RB_IB_BDTH_MASK; - if (data < RTL8366RB_IB_BDTH_MASK) - data += 1; - - val->value.i = (int)data * RTL8366RB_BDTH_UNIT; - - return 0; -} - -static int rtl8366rb_sw_set_port_rate_out(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val) -{ - struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev); - - if (val->port_vlan >= RTL8366RB_NUM_PORTS) - return -EINVAL; - - rtl8366_smi_rmwr(smi, RTL8366RB_EB_PREIFG_REG, - RTL8366RB_EB_PREIFG_MASK, - (RTL8366RB_QOS_DEFAULT_PREIFG << RTL8366RB_EB_PREIFG_OFFSET)); - - if (val->value.i > 0 && val->value.i < RTL8366RB_BDTH_SW_MAX) - val->value.i = (val->value.i - 1) / RTL8366RB_BDTH_UNIT; - else - val->value.i = RTL8366RB_BDTH_REG_DEFAULT; - - return rtl8366_smi_rmwr(smi, RTL8366RB_EB_REG(val->port_vlan), - RTL8366RB_EB_BDTH_MASK, val->value.i ); - -} - -static int rtl8366rb_sw_get_port_rate_out(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val) -{ - struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev); - u32 data; - - if (val->port_vlan >= RTL8366RB_NUM_PORTS) - return -EINVAL; - - rtl8366_smi_read_reg(smi, RTL8366RB_EB_REG(val->port_vlan), &data); - data &= RTL8366RB_EB_BDTH_MASK; - if (data < RTL8366RB_EB_BDTH_MASK) - data += 1; - - val->value.i = (int)data * RTL8366RB_BDTH_UNIT; - - return 0; -} - -static int rtl8366rb_sw_set_qos_enable(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val) -{ - struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev); - u32 data; - - if (val->value.i) - data = RTL8366RB_QOS_MASK; - else - data = 0; - - return rtl8366_smi_rmwr(smi, RTL8366RB_SGCR, RTL8366RB_QOS_MASK, data); -} - -static int rtl8366rb_sw_get_qos_enable(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val) -{ - struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev); - u32 data; - - rtl8366_smi_read_reg(smi, RTL8366RB_SGCR, &data); - if (data & RTL8366RB_QOS_MASK) - val->value.i = 1; - else - val->value.i = 0; - - return 0; -} - -static int rtl8366rb_sw_set_mirror_rx_enable(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val) -{ - struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev); - u32 data; - - if (val->value.i) - data = RTL8366RB_PMCR_MIRROR_RX; - else - data = 0; - - return rtl8366_smi_rmwr(smi, RTL8366RB_PMCR, RTL8366RB_PMCR_MIRROR_RX, data); -} - -static int rtl8366rb_sw_get_mirror_rx_enable(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val) -{ - struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev); - u32 data; - - rtl8366_smi_read_reg(smi, RTL8366RB_PMCR, &data); - if (data & RTL8366RB_PMCR_MIRROR_RX) - val->value.i = 1; - else - val->value.i = 0; - - return 0; -} - -static int rtl8366rb_sw_set_mirror_tx_enable(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val) -{ - struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev); - u32 data; - - if (val->value.i) - data = RTL8366RB_PMCR_MIRROR_TX; - else - data = 0; - - return rtl8366_smi_rmwr(smi, RTL8366RB_PMCR, RTL8366RB_PMCR_MIRROR_TX, data); -} - -static int rtl8366rb_sw_get_mirror_tx_enable(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val) -{ - struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev); - u32 data; - - rtl8366_smi_read_reg(smi, RTL8366RB_PMCR, &data); - if (data & RTL8366RB_PMCR_MIRROR_TX) - val->value.i = 1; - else - val->value.i = 0; - - return 0; -} - -static int rtl8366rb_sw_set_monitor_isolation_enable(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val) -{ - struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev); - u32 data; - - if (val->value.i) - data = RTL8366RB_PMCR_MIRROR_ISO; - else - data = 0; - - return rtl8366_smi_rmwr(smi, RTL8366RB_PMCR, RTL8366RB_PMCR_MIRROR_ISO, data); -} - -static int rtl8366rb_sw_get_monitor_isolation_enable(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val) -{ - struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev); - u32 data; - - rtl8366_smi_read_reg(smi, RTL8366RB_PMCR, &data); - if (data & RTL8366RB_PMCR_MIRROR_ISO) - val->value.i = 1; - else - val->value.i = 0; - - return 0; -} - -static int rtl8366rb_sw_set_mirror_pause_frames_enable(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val) -{ - struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev); - u32 data; - - if (val->value.i) - data = RTL8366RB_PMCR_MIRROR_SPC; - else - data = 0; - - return rtl8366_smi_rmwr(smi, RTL8366RB_PMCR, RTL8366RB_PMCR_MIRROR_SPC, data); -} - -static int rtl8366rb_sw_get_mirror_pause_frames_enable(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val) -{ - struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev); - u32 data; - - rtl8366_smi_read_reg(smi, RTL8366RB_PMCR, &data); - if (data & RTL8366RB_PMCR_MIRROR_SPC) - val->value.i = 1; - else - val->value.i = 0; - - return 0; -} - -static int rtl8366rb_sw_set_mirror_monitor_port(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val) -{ - struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev); - u32 data; - - data = RTL8366RB_PMCR_MONITOR_PORT(val->value.i); - - return rtl8366_smi_rmwr(smi, RTL8366RB_PMCR, RTL8366RB_PMCR_MONITOR_PORT_MASK, data); -} - -static int rtl8366rb_sw_get_mirror_monitor_port(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val) -{ - struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev); - u32 data; - - rtl8366_smi_read_reg(smi, RTL8366RB_PMCR, &data); - val->value.i = (data & RTL8366RB_PMCR_MONITOR_PORT_MASK) >> 4; - - return 0; -} - -static int rtl8366rb_sw_set_mirror_source_port(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val) -{ - struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev); - u32 data; - - data = RTL8366RB_PMCR_SOURCE_PORT(val->value.i); - - return rtl8366_smi_rmwr(smi, RTL8366RB_PMCR, RTL8366RB_PMCR_SOURCE_PORT_MASK, data); -} - -static int rtl8366rb_sw_get_mirror_source_port(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val) -{ - struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev); - u32 data; - - rtl8366_smi_read_reg(smi, RTL8366RB_PMCR, &data); - val->value.i = data & RTL8366RB_PMCR_SOURCE_PORT_MASK; - - return 0; -} - -static int rtl8366rb_sw_reset_port_mibs(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val) -{ - struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev); - - if (val->port_vlan >= RTL8366RB_NUM_PORTS) - return -EINVAL; - - return rtl8366_smi_rmwr(smi, RTL8366RB_MIB_CTRL_REG, 0, - RTL8366RB_MIB_CTRL_PORT_RESET(val->port_vlan)); -} - -static int rtl8366rb_sw_get_port_stats(struct switch_dev *dev, int port, - struct switch_port_stats *stats) -{ - return (rtl8366_sw_get_port_stats(dev, port, stats, - RTL8366RB_MIB_TXB_ID, RTL8366RB_MIB_RXB_ID)); -} - -static struct switch_attr rtl8366rb_globals[] = { - { - .type = SWITCH_TYPE_INT, - .name = "enable_learning", - .description = "Enable learning, enable aging", - .set = rtl8366rb_sw_set_learning_enable, - .get = rtl8366rb_sw_get_learning_enable, - .max = 1 - }, { - .type = SWITCH_TYPE_INT, - .name = "enable_vlan", - .description = "Enable VLAN mode", - .set = rtl8366_sw_set_vlan_enable, - .get = rtl8366_sw_get_vlan_enable, - .max = 1, - .ofs = 1 - }, { - .type = SWITCH_TYPE_INT, - .name = "enable_vlan4k", - .description = "Enable VLAN 4K mode", - .set = rtl8366_sw_set_vlan_enable, - .get = rtl8366_sw_get_vlan_enable, - .max = 1, - .ofs = 2 - }, { - .type = SWITCH_TYPE_NOVAL, - .name = "reset_mibs", - .description = "Reset all MIB counters", - .set = rtl8366rb_sw_reset_mibs, - }, { - .type = SWITCH_TYPE_INT, - .name = "blinkrate", - .description = "Get/Set LED blinking rate (0 = 43ms, 1 = 84ms," - " 2 = 120ms, 3 = 170ms, 4 = 340ms, 5 = 670ms)", - .set = rtl8366rb_sw_set_blinkrate, - .get = rtl8366rb_sw_get_blinkrate, - .max = 5 - }, { - .type = SWITCH_TYPE_INT, - .name = "enable_qos", - .description = "Enable QOS", - .set = rtl8366rb_sw_set_qos_enable, - .get = rtl8366rb_sw_get_qos_enable, - .max = 1 - }, { - .type = SWITCH_TYPE_INT, - .name = "enable_mirror_rx", - .description = "Enable mirroring of RX packets", - .set = rtl8366rb_sw_set_mirror_rx_enable, - .get = rtl8366rb_sw_get_mirror_rx_enable, - .max = 1 - }, { - .type = SWITCH_TYPE_INT, - .name = "enable_mirror_tx", - .description = "Enable mirroring of TX packets", - .set = rtl8366rb_sw_set_mirror_tx_enable, - .get = rtl8366rb_sw_get_mirror_tx_enable, - .max = 1 - }, { - .type = SWITCH_TYPE_INT, - .name = "enable_monitor_isolation", - .description = "Enable isolation of monitor port (TX packets will be dropped)", - .set = rtl8366rb_sw_set_monitor_isolation_enable, - .get = rtl8366rb_sw_get_monitor_isolation_enable, - .max = 1 - }, { - .type = SWITCH_TYPE_INT, - .name = "enable_mirror_pause_frames", - .description = "Enable mirroring of RX pause frames", - .set = rtl8366rb_sw_set_mirror_pause_frames_enable, - .get = rtl8366rb_sw_get_mirror_pause_frames_enable, - .max = 1 - }, { - .type = SWITCH_TYPE_INT, - .name = "mirror_monitor_port", - .description = "Mirror monitor port", - .set = rtl8366rb_sw_set_mirror_monitor_port, - .get = rtl8366rb_sw_get_mirror_monitor_port, - .max = 5 - }, { - .type = SWITCH_TYPE_INT, - .name = "mirror_source_port", - .description = "Mirror source port", - .set = rtl8366rb_sw_set_mirror_source_port, - .get = rtl8366rb_sw_get_mirror_source_port, - .max = 5 - }, -}; - -static struct switch_attr rtl8366rb_port[] = { - { - .type = SWITCH_TYPE_NOVAL, - .name = "reset_mib", - .description = "Reset single port MIB counters", - .set = rtl8366rb_sw_reset_port_mibs, - }, { - .type = SWITCH_TYPE_STRING, - .name = "mib", - .description = "Get MIB counters for port", - .max = 33, - .set = NULL, - .get = rtl8366_sw_get_port_mib, - }, { - .type = SWITCH_TYPE_INT, - .name = "led", - .description = "Get/Set port group (0 - 3) led mode (0 - 15)", - .max = 15, - .set = rtl8366rb_sw_set_port_led, - .get = rtl8366rb_sw_get_port_led, - }, { - .type = SWITCH_TYPE_INT, - .name = "disable", - .description = "Get/Set port state (enabled or disabled)", - .max = 1, - .set = rtl8366rb_sw_set_port_disable, - .get = rtl8366rb_sw_get_port_disable, - }, { - .type = SWITCH_TYPE_INT, - .name = "rate_in", - .description = "Get/Set port ingress (incoming) bandwidth limit in kbps", - .max = RTL8366RB_BDTH_SW_MAX, - .set = rtl8366rb_sw_set_port_rate_in, - .get = rtl8366rb_sw_get_port_rate_in, - }, { - .type = SWITCH_TYPE_INT, - .name = "rate_out", - .description = "Get/Set port egress (outgoing) bandwidth limit in kbps", - .max = RTL8366RB_BDTH_SW_MAX, - .set = rtl8366rb_sw_set_port_rate_out, - .get = rtl8366rb_sw_get_port_rate_out, - }, -}; - -static struct switch_attr rtl8366rb_vlan[] = { - { - .type = SWITCH_TYPE_STRING, - .name = "info", - .description = "Get vlan information", - .max = 1, - .set = NULL, - .get = rtl8366_sw_get_vlan_info, - }, { - .type = SWITCH_TYPE_INT, - .name = "fid", - .description = "Get/Set vlan FID", - .max = RTL8366RB_FIDMAX, - .set = rtl8366_sw_set_vlan_fid, - .get = rtl8366_sw_get_vlan_fid, - }, -}; - -static const struct switch_dev_ops rtl8366_ops = { - .attr_global = { - .attr = rtl8366rb_globals, - .n_attr = ARRAY_SIZE(rtl8366rb_globals), - }, - .attr_port = { - .attr = rtl8366rb_port, - .n_attr = ARRAY_SIZE(rtl8366rb_port), - }, - .attr_vlan = { - .attr = rtl8366rb_vlan, - .n_attr = ARRAY_SIZE(rtl8366rb_vlan), - }, - - .get_vlan_ports = rtl8366_sw_get_vlan_ports, - .set_vlan_ports = rtl8366_sw_set_vlan_ports, - .get_port_pvid = rtl8366_sw_get_port_pvid, - .set_port_pvid = rtl8366_sw_set_port_pvid, - .reset_switch = rtl8366_sw_reset_switch, - .get_port_link = rtl8366rb_sw_get_port_link, - .get_port_stats = rtl8366rb_sw_get_port_stats, -}; - -static int rtl8366rb_switch_init(struct rtl8366_smi *smi) -{ - struct switch_dev *dev = &smi->sw_dev; - int err; - - dev->name = "RTL8366RB"; - dev->cpu_port = RTL8366RB_PORT_NUM_CPU; - dev->ports = RTL8366RB_NUM_PORTS; - dev->vlans = RTL8366RB_NUM_VIDS; - dev->ops = &rtl8366_ops; - dev->alias = dev_name(smi->parent); - - err = register_switch(dev, NULL); - if (err) - dev_err(smi->parent, "switch registration failed\n"); - - return err; -} - -static void rtl8366rb_switch_cleanup(struct rtl8366_smi *smi) -{ - unregister_switch(&smi->sw_dev); -} - -static int rtl8366rb_mii_read(struct mii_bus *bus, int addr, int reg) -{ - struct rtl8366_smi *smi = bus->priv; - u32 val = 0; - int err; - - err = rtl8366rb_read_phy_reg(smi, addr, 0, reg, &val); - if (err) - return 0xffff; - - return val; -} - -static int rtl8366rb_mii_write(struct mii_bus *bus, int addr, int reg, u16 val) -{ - struct rtl8366_smi *smi = bus->priv; - u32 t; - int err; - - err = rtl8366rb_write_phy_reg(smi, addr, 0, reg, val); - /* flush write */ - (void) rtl8366rb_read_phy_reg(smi, addr, 0, reg, &t); - - return err; -} - -static int rtl8366rb_detect(struct rtl8366_smi *smi) -{ - u32 chip_id = 0; - u32 chip_ver = 0; - int ret; - - ret = rtl8366_smi_read_reg(smi, RTL8366RB_CHIP_ID_REG, &chip_id); - if (ret) { - dev_err(smi->parent, "unable to read chip id\n"); - return ret; - } - - switch (chip_id) { - case RTL8366RB_CHIP_ID_8366: - break; - default: - dev_err(smi->parent, "unknown chip id (%04x)\n", chip_id); - return -ENODEV; - } - - ret = rtl8366_smi_read_reg(smi, RTL8366RB_CHIP_VERSION_CTRL_REG, - &chip_ver); - if (ret) { - dev_err(smi->parent, "unable to read chip version\n"); - return ret; - } - - dev_info(smi->parent, "RTL%04x ver. %u chip found\n", - chip_id, chip_ver & RTL8366RB_CHIP_VERSION_MASK); - - return 0; -} - -static struct rtl8366_smi_ops rtl8366rb_smi_ops = { - .detect = rtl8366rb_detect, - .reset_chip = rtl8366rb_reset_chip, - .setup = rtl8366rb_setup, - - .mii_read = rtl8366rb_mii_read, - .mii_write = rtl8366rb_mii_write, - - .get_vlan_mc = rtl8366rb_get_vlan_mc, - .set_vlan_mc = rtl8366rb_set_vlan_mc, - .get_vlan_4k = rtl8366rb_get_vlan_4k, - .set_vlan_4k = rtl8366rb_set_vlan_4k, - .get_mc_index = rtl8366rb_get_mc_index, - .set_mc_index = rtl8366rb_set_mc_index, - .get_mib_counter = rtl8366rb_get_mib_counter, - .is_vlan_valid = rtl8366rb_is_vlan_valid, - .enable_vlan = rtl8366rb_enable_vlan, - .enable_vlan4k = rtl8366rb_enable_vlan4k, - .enable_port = rtl8366rb_enable_port, -}; - -static int rtl8366rb_probe(struct platform_device *pdev) -{ - static int rtl8366_smi_version_printed; - struct rtl8366_smi *smi; - int err; - - if (!rtl8366_smi_version_printed++) - printk(KERN_NOTICE RTL8366RB_DRIVER_DESC - " version " RTL8366RB_DRIVER_VER"\n"); - - smi = rtl8366_smi_probe(pdev); - if (IS_ERR(smi)) - return PTR_ERR(smi); - - smi->clk_delay = 10; - smi->cmd_read = 0xa9; - smi->cmd_write = 0xa8; - smi->ops = &rtl8366rb_smi_ops; - smi->cpu_port = RTL8366RB_PORT_NUM_CPU; - smi->num_ports = RTL8366RB_NUM_PORTS; - smi->num_vlan_mc = RTL8366RB_NUM_VLANS; - smi->mib_counters = rtl8366rb_mib_counters; - smi->num_mib_counters = ARRAY_SIZE(rtl8366rb_mib_counters); - - err = rtl8366_smi_init(smi); - if (err) - goto err_free_smi; - - platform_set_drvdata(pdev, smi); - - err = rtl8366rb_switch_init(smi); - if (err) - goto err_clear_drvdata; - - return 0; - - err_clear_drvdata: - platform_set_drvdata(pdev, NULL); - rtl8366_smi_cleanup(smi); - err_free_smi: - kfree(smi); - return err; -} - -static int rtl8366rb_remove(struct platform_device *pdev) -{ - struct rtl8366_smi *smi = platform_get_drvdata(pdev); - - if (smi) { - rtl8366rb_switch_cleanup(smi); - platform_set_drvdata(pdev, NULL); - rtl8366_smi_cleanup(smi); - kfree(smi); - } - - return 0; -} - -#ifdef CONFIG_OF -static const struct of_device_id rtl8366rb_match[] = { - { .compatible = "realtek,rtl8366rb" }, - {}, -}; -MODULE_DEVICE_TABLE(of, rtl8366rb_match); -#endif - -static struct platform_driver rtl8366rb_driver = { - .driver = { - .name = RTL8366RB_DRIVER_NAME, - .owner = THIS_MODULE, - .of_match_table = of_match_ptr(rtl8366rb_match), - }, - .probe = rtl8366rb_probe, - .remove = rtl8366rb_remove, -}; - -static int __init rtl8366rb_module_init(void) -{ - return platform_driver_register(&rtl8366rb_driver); -} -module_init(rtl8366rb_module_init); - -static void __exit rtl8366rb_module_exit(void) -{ - platform_driver_unregister(&rtl8366rb_driver); -} -module_exit(rtl8366rb_module_exit); - -MODULE_DESCRIPTION(RTL8366RB_DRIVER_DESC); -MODULE_VERSION(RTL8366RB_DRIVER_VER); -MODULE_AUTHOR("Gabor Juhos "); -MODULE_AUTHOR("Antti Seppälä "); -MODULE_AUTHOR("Roman Yeryomin "); -MODULE_AUTHOR("Colin Leitner "); -MODULE_LICENSE("GPL v2"); -MODULE_ALIAS("platform:" RTL8366RB_DRIVER_NAME); diff --git a/target/linux/generic/files-6.12/drivers/net/phy/rtl8366s.c b/target/linux/generic/files-6.12/drivers/net/phy/rtl8366s.c deleted file mode 100644 index 8c746778b8f820..00000000000000 --- a/target/linux/generic/files-6.12/drivers/net/phy/rtl8366s.c +++ /dev/null @@ -1,1320 +0,0 @@ -/* - * Platform driver for the Realtek RTL8366S ethernet switch - * - * Copyright (C) 2009-2010 Gabor Juhos - * Copyright (C) 2010 Antti Seppälä - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published - * by the Free Software Foundation. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "rtl8366_smi.h" - -#define RTL8366S_DRIVER_DESC "Realtek RTL8366S ethernet switch driver" -#define RTL8366S_DRIVER_VER "0.2.2" - -#define RTL8366S_PHY_NO_MAX 4 -#define RTL8366S_PHY_PAGE_MAX 7 -#define RTL8366S_PHY_ADDR_MAX 31 - -/* Switch Global Configuration register */ -#define RTL8366S_SGCR 0x0000 -#define RTL8366S_SGCR_EN_BC_STORM_CTRL BIT(0) -#define RTL8366S_SGCR_MAX_LENGTH(_x) (_x << 4) -#define RTL8366S_SGCR_MAX_LENGTH_MASK RTL8366S_SGCR_MAX_LENGTH(0x3) -#define RTL8366S_SGCR_MAX_LENGTH_1522 RTL8366S_SGCR_MAX_LENGTH(0x0) -#define RTL8366S_SGCR_MAX_LENGTH_1536 RTL8366S_SGCR_MAX_LENGTH(0x1) -#define RTL8366S_SGCR_MAX_LENGTH_1552 RTL8366S_SGCR_MAX_LENGTH(0x2) -#define RTL8366S_SGCR_MAX_LENGTH_16000 RTL8366S_SGCR_MAX_LENGTH(0x3) -#define RTL8366S_SGCR_EN_VLAN BIT(13) - -/* Port Enable Control register */ -#define RTL8366S_PECR 0x0001 - -/* Green Ethernet Feature (based on GPL_BELKIN_F5D8235-4_v1000 v1.01.24) */ -#define RTL8366S_GREEN_ETHERNET_CTRL_REG 0x000a -#define RTL8366S_GREEN_ETHERNET_CTRL_MASK 0x0018 -#define RTL8366S_GREEN_ETHERNET_TX_BIT (1 << 3) -#define RTL8366S_GREEN_ETHERNET_RX_BIT (1 << 4) - -/* Switch Security Control registers */ -#define RTL8366S_SSCR0 0x0002 -#define RTL8366S_SSCR1 0x0003 -#define RTL8366S_SSCR2 0x0004 -#define RTL8366S_SSCR2_DROP_UNKNOWN_DA BIT(0) - -#define RTL8366S_RESET_CTRL_REG 0x0100 -#define RTL8366S_CHIP_CTRL_RESET_HW 1 -#define RTL8366S_CHIP_CTRL_RESET_SW (1 << 1) - -#define RTL8366S_CHIP_VERSION_CTRL_REG 0x0104 -#define RTL8366S_CHIP_VERSION_MASK 0xf -#define RTL8366S_CHIP_ID_REG 0x0105 -#define RTL8366S_CHIP_ID_8366 0x8366 - -/* PHY registers control */ -#define RTL8366S_PHY_ACCESS_CTRL_REG 0x8028 -#define RTL8366S_PHY_ACCESS_DATA_REG 0x8029 - -#define RTL8366S_PHY_CTRL_READ 1 -#define RTL8366S_PHY_CTRL_WRITE 0 - -#define RTL8366S_PHY_REG_MASK 0x1f -#define RTL8366S_PHY_PAGE_OFFSET 5 -#define RTL8366S_PHY_PAGE_MASK (0x7 << 5) -#define RTL8366S_PHY_NO_OFFSET 9 -#define RTL8366S_PHY_NO_MASK (0x1f << 9) - -/* Green Ethernet Feature for PHY ports */ -#define RTL8366S_PHY_POWER_SAVING_CTRL_REG 12 -#define RTL8366S_PHY_POWER_SAVING_MASK 0x1000 - -/* LED control registers */ -#define RTL8366S_LED_BLINKRATE_REG 0x0420 -#define RTL8366S_LED_BLINKRATE_BIT 0 -#define RTL8366S_LED_BLINKRATE_MASK 0x0007 - -#define RTL8366S_LED_CTRL_REG 0x0421 -#define RTL8366S_LED_0_1_CTRL_REG 0x0422 -#define RTL8366S_LED_2_3_CTRL_REG 0x0423 - -#define RTL8366S_MIB_COUNT 33 -#define RTL8366S_GLOBAL_MIB_COUNT 1 -#define RTL8366S_MIB_COUNTER_PORT_OFFSET 0x0040 -#define RTL8366S_MIB_COUNTER_BASE 0x1000 -#define RTL8366S_MIB_COUNTER_PORT_OFFSET2 0x0008 -#define RTL8366S_MIB_COUNTER_BASE2 0x1180 -#define RTL8366S_MIB_CTRL_REG 0x11F0 -#define RTL8366S_MIB_CTRL_USER_MASK 0x01FF -#define RTL8366S_MIB_CTRL_BUSY_MASK 0x0001 -#define RTL8366S_MIB_CTRL_RESET_MASK 0x0002 - -#define RTL8366S_MIB_CTRL_GLOBAL_RESET_MASK 0x0004 -#define RTL8366S_MIB_CTRL_PORT_RESET_BIT 0x0003 -#define RTL8366S_MIB_CTRL_PORT_RESET_MASK 0x01FC - - -#define RTL8366S_PORT_VLAN_CTRL_BASE 0x0058 -#define RTL8366S_PORT_VLAN_CTRL_REG(_p) \ - (RTL8366S_PORT_VLAN_CTRL_BASE + (_p) / 4) -#define RTL8366S_PORT_VLAN_CTRL_MASK 0xf -#define RTL8366S_PORT_VLAN_CTRL_SHIFT(_p) (4 * ((_p) % 4)) - - -#define RTL8366S_VLAN_TABLE_READ_BASE 0x018B -#define RTL8366S_VLAN_TABLE_WRITE_BASE 0x0185 - -#define RTL8366S_VLAN_TB_CTRL_REG 0x010F - -#define RTL8366S_TABLE_ACCESS_CTRL_REG 0x0180 -#define RTL8366S_TABLE_VLAN_READ_CTRL 0x0E01 -#define RTL8366S_TABLE_VLAN_WRITE_CTRL 0x0F01 - -#define RTL8366S_VLAN_MC_BASE(_x) (0x0016 + (_x) * 2) - -#define RTL8366S_VLAN_MEMBERINGRESS_REG 0x0379 - -#define RTL8366S_PORT_LINK_STATUS_BASE 0x0060 -#define RTL8366S_PORT_STATUS_SPEED_MASK 0x0003 -#define RTL8366S_PORT_STATUS_DUPLEX_MASK 0x0004 -#define RTL8366S_PORT_STATUS_LINK_MASK 0x0010 -#define RTL8366S_PORT_STATUS_TXPAUSE_MASK 0x0020 -#define RTL8366S_PORT_STATUS_RXPAUSE_MASK 0x0040 -#define RTL8366S_PORT_STATUS_AN_MASK 0x0080 - - -#define RTL8366S_PORT_NUM_CPU 5 -#define RTL8366S_NUM_PORTS 6 -#define RTL8366S_NUM_VLANS 16 -#define RTL8366S_NUM_LEDGROUPS 4 -#define RTL8366S_NUM_VIDS 4096 -#define RTL8366S_PRIORITYMAX 7 -#define RTL8366S_FIDMAX 7 - - -#define RTL8366S_PORT_1 (1 << 0) /* In userspace port 0 */ -#define RTL8366S_PORT_2 (1 << 1) /* In userspace port 1 */ -#define RTL8366S_PORT_3 (1 << 2) /* In userspace port 2 */ -#define RTL8366S_PORT_4 (1 << 3) /* In userspace port 3 */ - -#define RTL8366S_PORT_UNKNOWN (1 << 4) /* No known connection */ -#define RTL8366S_PORT_CPU (1 << 5) /* CPU port */ - -#define RTL8366S_PORT_ALL (RTL8366S_PORT_1 | \ - RTL8366S_PORT_2 | \ - RTL8366S_PORT_3 | \ - RTL8366S_PORT_4 | \ - RTL8366S_PORT_UNKNOWN | \ - RTL8366S_PORT_CPU) - -#define RTL8366S_PORT_ALL_BUT_CPU (RTL8366S_PORT_1 | \ - RTL8366S_PORT_2 | \ - RTL8366S_PORT_3 | \ - RTL8366S_PORT_4 | \ - RTL8366S_PORT_UNKNOWN) - -#define RTL8366S_PORT_ALL_EXTERNAL (RTL8366S_PORT_1 | \ - RTL8366S_PORT_2 | \ - RTL8366S_PORT_3 | \ - RTL8366S_PORT_4) - -#define RTL8366S_PORT_ALL_INTERNAL (RTL8366S_PORT_UNKNOWN | \ - RTL8366S_PORT_CPU) - -#define RTL8366S_VLAN_VID_MASK 0xfff -#define RTL8366S_VLAN_PRIORITY_SHIFT 12 -#define RTL8366S_VLAN_PRIORITY_MASK 0x7 -#define RTL8366S_VLAN_MEMBER_MASK 0x3f -#define RTL8366S_VLAN_UNTAG_SHIFT 6 -#define RTL8366S_VLAN_UNTAG_MASK 0x3f -#define RTL8366S_VLAN_FID_SHIFT 12 -#define RTL8366S_VLAN_FID_MASK 0x7 - -#define RTL8366S_MIB_RXB_ID 0 /* IfInOctets */ -#define RTL8366S_MIB_TXB_ID 20 /* IfOutOctets */ - -static struct rtl8366_mib_counter rtl8366s_mib_counters[] = { - { 0, 0, 4, "IfInOctets" }, - { 0, 4, 4, "EtherStatsOctets" }, - { 0, 8, 2, "EtherStatsUnderSizePkts" }, - { 0, 10, 2, "EtherFragments" }, - { 0, 12, 2, "EtherStatsPkts64Octets" }, - { 0, 14, 2, "EtherStatsPkts65to127Octets" }, - { 0, 16, 2, "EtherStatsPkts128to255Octets" }, - { 0, 18, 2, "EtherStatsPkts256to511Octets" }, - { 0, 20, 2, "EtherStatsPkts512to1023Octets" }, - { 0, 22, 2, "EtherStatsPkts1024to1518Octets" }, - { 0, 24, 2, "EtherOversizeStats" }, - { 0, 26, 2, "EtherStatsJabbers" }, - { 0, 28, 2, "IfInUcastPkts" }, - { 0, 30, 2, "EtherStatsMulticastPkts" }, - { 0, 32, 2, "EtherStatsBroadcastPkts" }, - { 0, 34, 2, "EtherStatsDropEvents" }, - { 0, 36, 2, "Dot3StatsFCSErrors" }, - { 0, 38, 2, "Dot3StatsSymbolErrors" }, - { 0, 40, 2, "Dot3InPauseFrames" }, - { 0, 42, 2, "Dot3ControlInUnknownOpcodes" }, - { 0, 44, 4, "IfOutOctets" }, - { 0, 48, 2, "Dot3StatsSingleCollisionFrames" }, - { 0, 50, 2, "Dot3StatMultipleCollisionFrames" }, - { 0, 52, 2, "Dot3sDeferredTransmissions" }, - { 0, 54, 2, "Dot3StatsLateCollisions" }, - { 0, 56, 2, "EtherStatsCollisions" }, - { 0, 58, 2, "Dot3StatsExcessiveCollisions" }, - { 0, 60, 2, "Dot3OutPauseFrames" }, - { 0, 62, 2, "Dot1dBasePortDelayExceededDiscards" }, - - /* - * The following counters are accessible at a different - * base address. - */ - { 1, 0, 2, "Dot1dTpPortInDiscards" }, - { 1, 2, 2, "IfOutUcastPkts" }, - { 1, 4, 2, "IfOutMulticastPkts" }, - { 1, 6, 2, "IfOutBroadcastPkts" }, -}; - -#define REG_WR(_smi, _reg, _val) \ - do { \ - err = rtl8366_smi_write_reg(_smi, _reg, _val); \ - if (err) \ - return err; \ - } while (0) - -#define REG_RMW(_smi, _reg, _mask, _val) \ - do { \ - err = rtl8366_smi_rmwr(_smi, _reg, _mask, _val); \ - if (err) \ - return err; \ - } while (0) - -static int rtl8366s_reset_chip(struct rtl8366_smi *smi) -{ - int timeout = 10; - u32 data; - - rtl8366_smi_write_reg_noack(smi, RTL8366S_RESET_CTRL_REG, - RTL8366S_CHIP_CTRL_RESET_HW); - do { - msleep(1); - if (rtl8366_smi_read_reg(smi, RTL8366S_RESET_CTRL_REG, &data)) - return -EIO; - - if (!(data & RTL8366S_CHIP_CTRL_RESET_HW)) - break; - } while (--timeout); - - if (!timeout) { - printk("Timeout waiting for the switch to reset\n"); - return -EIO; - } - - return 0; -} - -static int rtl8366s_read_phy_reg(struct rtl8366_smi *smi, - u32 phy_no, u32 page, u32 addr, u32 *data) -{ - u32 reg; - int ret; - - if (phy_no > RTL8366S_PHY_NO_MAX) - return -EINVAL; - - if (page > RTL8366S_PHY_PAGE_MAX) - return -EINVAL; - - if (addr > RTL8366S_PHY_ADDR_MAX) - return -EINVAL; - - ret = rtl8366_smi_write_reg(smi, RTL8366S_PHY_ACCESS_CTRL_REG, - RTL8366S_PHY_CTRL_READ); - if (ret) - return ret; - - reg = 0x8000 | (1 << (phy_no + RTL8366S_PHY_NO_OFFSET)) | - ((page << RTL8366S_PHY_PAGE_OFFSET) & RTL8366S_PHY_PAGE_MASK) | - (addr & RTL8366S_PHY_REG_MASK); - - ret = rtl8366_smi_write_reg(smi, reg, 0); - if (ret) - return ret; - - ret = rtl8366_smi_read_reg(smi, RTL8366S_PHY_ACCESS_DATA_REG, data); - if (ret) - return ret; - - return 0; -} - -static int rtl8366s_write_phy_reg(struct rtl8366_smi *smi, - u32 phy_no, u32 page, u32 addr, u32 data) -{ - u32 reg; - int ret; - - if (phy_no > RTL8366S_PHY_NO_MAX) - return -EINVAL; - - if (page > RTL8366S_PHY_PAGE_MAX) - return -EINVAL; - - if (addr > RTL8366S_PHY_ADDR_MAX) - return -EINVAL; - - ret = rtl8366_smi_write_reg(smi, RTL8366S_PHY_ACCESS_CTRL_REG, - RTL8366S_PHY_CTRL_WRITE); - if (ret) - return ret; - - reg = 0x8000 | (1 << (phy_no + RTL8366S_PHY_NO_OFFSET)) | - ((page << RTL8366S_PHY_PAGE_OFFSET) & RTL8366S_PHY_PAGE_MASK) | - (addr & RTL8366S_PHY_REG_MASK); - - ret = rtl8366_smi_write_reg(smi, reg, data); - if (ret) - return ret; - - return 0; -} - -static int rtl8366s_set_green_port(struct rtl8366_smi *smi, int port, int enable) -{ - int err; - u32 phyData; - - if (port >= RTL8366S_NUM_PORTS) - return -EINVAL; - - err = rtl8366s_read_phy_reg(smi, port, 0, RTL8366S_PHY_POWER_SAVING_CTRL_REG, &phyData); - if (err) - return err; - - if (enable) - phyData |= RTL8366S_PHY_POWER_SAVING_MASK; - else - phyData &= ~RTL8366S_PHY_POWER_SAVING_MASK; - - err = rtl8366s_write_phy_reg(smi, port, 0, RTL8366S_PHY_POWER_SAVING_CTRL_REG, phyData); - if (err) - return err; - - return 0; -} - -static int rtl8366s_set_green(struct rtl8366_smi *smi, int enable) -{ - int err; - unsigned i; - u32 data = 0; - - if (!enable) { - for (i = 0; i <= RTL8366S_PHY_NO_MAX; i++) { - rtl8366s_set_green_port(smi, i, 0); - } - } - - if (enable) - data = (RTL8366S_GREEN_ETHERNET_TX_BIT | RTL8366S_GREEN_ETHERNET_RX_BIT); - - REG_RMW(smi, RTL8366S_GREEN_ETHERNET_CTRL_REG, RTL8366S_GREEN_ETHERNET_CTRL_MASK, data); - - return 0; -} - -static int rtl8366s_setup(struct rtl8366_smi *smi) -{ - struct rtl8366_platform_data *pdata; - int err; - unsigned i; -#ifdef CONFIG_OF - struct device_node *np; - unsigned num_initvals; - const __be32 *paddr; -#endif - - pdata = smi->parent->platform_data; - if (pdata && pdata->num_initvals && pdata->initvals) { - dev_info(smi->parent, "applying initvals\n"); - for (i = 0; i < pdata->num_initvals; i++) - REG_WR(smi, pdata->initvals[i].reg, - pdata->initvals[i].val); - } - -#ifdef CONFIG_OF - np = smi->parent->of_node; - - paddr = of_get_property(np, "realtek,initvals", &num_initvals); - if (paddr) { - dev_info(smi->parent, "applying initvals from DTS\n"); - - if (num_initvals < (2 * sizeof(*paddr))) - return -EINVAL; - - num_initvals /= sizeof(*paddr); - - for (i = 0; i < num_initvals - 1; i += 2) { - u32 reg = be32_to_cpup(paddr + i); - u32 val = be32_to_cpup(paddr + i + 1); - - REG_WR(smi, reg, val); - } - } - - if (of_property_read_bool(np, "realtek,green-ethernet-features")) { - dev_info(smi->parent, "activating Green Ethernet features\n"); - - err = rtl8366s_set_green(smi, 1); - if (err) - return err; - - for (i = 0; i <= RTL8366S_PHY_NO_MAX; i++) { - err = rtl8366s_set_green_port(smi, i, 1); - if (err) - return err; - } - } -#endif - - /* set maximum packet length to 1536 bytes */ - REG_RMW(smi, RTL8366S_SGCR, RTL8366S_SGCR_MAX_LENGTH_MASK, - RTL8366S_SGCR_MAX_LENGTH_1536); - - /* enable learning for all ports */ - REG_WR(smi, RTL8366S_SSCR0, 0); - - /* enable auto ageing for all ports */ - REG_WR(smi, RTL8366S_SSCR1, 0); - - /* - * discard VLAN tagged packets if the port is not a member of - * the VLAN with which the packets is associated. - */ - REG_WR(smi, RTL8366S_VLAN_MEMBERINGRESS_REG, RTL8366S_PORT_ALL); - - /* don't drop packets whose DA has not been learned */ - REG_RMW(smi, RTL8366S_SSCR2, RTL8366S_SSCR2_DROP_UNKNOWN_DA, 0); - - return 0; -} - -static int rtl8366_get_mib_counter(struct rtl8366_smi *smi, int counter, - int port, unsigned long long *val) -{ - int i; - int err; - u32 addr, data; - u64 mibvalue; - - if (port > RTL8366S_NUM_PORTS || counter >= RTL8366S_MIB_COUNT) - return -EINVAL; - - switch (rtl8366s_mib_counters[counter].base) { - case 0: - addr = RTL8366S_MIB_COUNTER_BASE + - RTL8366S_MIB_COUNTER_PORT_OFFSET * port; - break; - - case 1: - addr = RTL8366S_MIB_COUNTER_BASE2 + - RTL8366S_MIB_COUNTER_PORT_OFFSET2 * port; - break; - - default: - return -EINVAL; - } - - addr += rtl8366s_mib_counters[counter].offset; - - /* - * Writing access counter address first - * then ASIC will prepare 64bits counter wait for being retrived - */ - data = 0; /* writing data will be discard by ASIC */ - err = rtl8366_smi_write_reg(smi, addr, data); - if (err) - return err; - - /* read MIB control register */ - err = rtl8366_smi_read_reg(smi, RTL8366S_MIB_CTRL_REG, &data); - if (err) - return err; - - if (data & RTL8366S_MIB_CTRL_BUSY_MASK) - return -EBUSY; - - if (data & RTL8366S_MIB_CTRL_RESET_MASK) - return -EIO; - - mibvalue = 0; - for (i = rtl8366s_mib_counters[counter].length; i > 0; i--) { - err = rtl8366_smi_read_reg(smi, addr + (i - 1), &data); - if (err) - return err; - - mibvalue = (mibvalue << 16) | (data & 0xFFFF); - } - - *val = mibvalue; - return 0; -} - -static int rtl8366s_get_vlan_4k(struct rtl8366_smi *smi, u32 vid, - struct rtl8366_vlan_4k *vlan4k) -{ - u32 data[2]; - int err; - int i; - - memset(vlan4k, '\0', sizeof(struct rtl8366_vlan_4k)); - - if (vid >= RTL8366S_NUM_VIDS) - return -EINVAL; - - /* write VID */ - err = rtl8366_smi_write_reg(smi, RTL8366S_VLAN_TABLE_WRITE_BASE, - vid & RTL8366S_VLAN_VID_MASK); - if (err) - return err; - - /* write table access control word */ - err = rtl8366_smi_write_reg(smi, RTL8366S_TABLE_ACCESS_CTRL_REG, - RTL8366S_TABLE_VLAN_READ_CTRL); - if (err) - return err; - - for (i = 0; i < 2; i++) { - err = rtl8366_smi_read_reg(smi, - RTL8366S_VLAN_TABLE_READ_BASE + i, - &data[i]); - if (err) - return err; - } - - vlan4k->vid = vid; - vlan4k->untag = (data[1] >> RTL8366S_VLAN_UNTAG_SHIFT) & - RTL8366S_VLAN_UNTAG_MASK; - vlan4k->member = data[1] & RTL8366S_VLAN_MEMBER_MASK; - vlan4k->fid = (data[1] >> RTL8366S_VLAN_FID_SHIFT) & - RTL8366S_VLAN_FID_MASK; - - return 0; -} - -static int rtl8366s_set_vlan_4k(struct rtl8366_smi *smi, - const struct rtl8366_vlan_4k *vlan4k) -{ - u32 data[2]; - int err; - int i; - - if (vlan4k->vid >= RTL8366S_NUM_VIDS || - vlan4k->member > RTL8366S_VLAN_MEMBER_MASK || - vlan4k->untag > RTL8366S_VLAN_UNTAG_MASK || - vlan4k->fid > RTL8366S_FIDMAX) - return -EINVAL; - - data[0] = vlan4k->vid & RTL8366S_VLAN_VID_MASK; - data[1] = (vlan4k->member & RTL8366S_VLAN_MEMBER_MASK) | - ((vlan4k->untag & RTL8366S_VLAN_UNTAG_MASK) << - RTL8366S_VLAN_UNTAG_SHIFT) | - ((vlan4k->fid & RTL8366S_VLAN_FID_MASK) << - RTL8366S_VLAN_FID_SHIFT); - - for (i = 0; i < 2; i++) { - err = rtl8366_smi_write_reg(smi, - RTL8366S_VLAN_TABLE_WRITE_BASE + i, - data[i]); - if (err) - return err; - } - - /* write table access control word */ - err = rtl8366_smi_write_reg(smi, RTL8366S_TABLE_ACCESS_CTRL_REG, - RTL8366S_TABLE_VLAN_WRITE_CTRL); - - return err; -} - -static int rtl8366s_get_vlan_mc(struct rtl8366_smi *smi, u32 index, - struct rtl8366_vlan_mc *vlanmc) -{ - u32 data[2]; - int err; - int i; - - memset(vlanmc, '\0', sizeof(struct rtl8366_vlan_mc)); - - if (index >= RTL8366S_NUM_VLANS) - return -EINVAL; - - for (i = 0; i < 2; i++) { - err = rtl8366_smi_read_reg(smi, - RTL8366S_VLAN_MC_BASE(index) + i, - &data[i]); - if (err) - return err; - } - - vlanmc->vid = data[0] & RTL8366S_VLAN_VID_MASK; - vlanmc->priority = (data[0] >> RTL8366S_VLAN_PRIORITY_SHIFT) & - RTL8366S_VLAN_PRIORITY_MASK; - vlanmc->untag = (data[1] >> RTL8366S_VLAN_UNTAG_SHIFT) & - RTL8366S_VLAN_UNTAG_MASK; - vlanmc->member = data[1] & RTL8366S_VLAN_MEMBER_MASK; - vlanmc->fid = (data[1] >> RTL8366S_VLAN_FID_SHIFT) & - RTL8366S_VLAN_FID_MASK; - - return 0; -} - -static int rtl8366s_set_vlan_mc(struct rtl8366_smi *smi, u32 index, - const struct rtl8366_vlan_mc *vlanmc) -{ - u32 data[2]; - int err; - int i; - - if (index >= RTL8366S_NUM_VLANS || - vlanmc->vid >= RTL8366S_NUM_VIDS || - vlanmc->priority > RTL8366S_PRIORITYMAX || - vlanmc->member > RTL8366S_VLAN_MEMBER_MASK || - vlanmc->untag > RTL8366S_VLAN_UNTAG_MASK || - vlanmc->fid > RTL8366S_FIDMAX) - return -EINVAL; - - data[0] = (vlanmc->vid & RTL8366S_VLAN_VID_MASK) | - ((vlanmc->priority & RTL8366S_VLAN_PRIORITY_MASK) << - RTL8366S_VLAN_PRIORITY_SHIFT); - data[1] = (vlanmc->member & RTL8366S_VLAN_MEMBER_MASK) | - ((vlanmc->untag & RTL8366S_VLAN_UNTAG_MASK) << - RTL8366S_VLAN_UNTAG_SHIFT) | - ((vlanmc->fid & RTL8366S_VLAN_FID_MASK) << - RTL8366S_VLAN_FID_SHIFT); - - for (i = 0; i < 2; i++) { - err = rtl8366_smi_write_reg(smi, - RTL8366S_VLAN_MC_BASE(index) + i, - data[i]); - if (err) - return err; - } - - return 0; -} - -static int rtl8366s_get_mc_index(struct rtl8366_smi *smi, int port, int *val) -{ - u32 data; - int err; - - if (port >= RTL8366S_NUM_PORTS) - return -EINVAL; - - err = rtl8366_smi_read_reg(smi, RTL8366S_PORT_VLAN_CTRL_REG(port), - &data); - if (err) - return err; - - *val = (data >> RTL8366S_PORT_VLAN_CTRL_SHIFT(port)) & - RTL8366S_PORT_VLAN_CTRL_MASK; - - return 0; -} - -static int rtl8366s_set_mc_index(struct rtl8366_smi *smi, int port, int index) -{ - if (port >= RTL8366S_NUM_PORTS || index >= RTL8366S_NUM_VLANS) - return -EINVAL; - - return rtl8366_smi_rmwr(smi, RTL8366S_PORT_VLAN_CTRL_REG(port), - RTL8366S_PORT_VLAN_CTRL_MASK << - RTL8366S_PORT_VLAN_CTRL_SHIFT(port), - (index & RTL8366S_PORT_VLAN_CTRL_MASK) << - RTL8366S_PORT_VLAN_CTRL_SHIFT(port)); -} - -static int rtl8366s_enable_vlan(struct rtl8366_smi *smi, int enable) -{ - return rtl8366_smi_rmwr(smi, RTL8366S_SGCR, RTL8366S_SGCR_EN_VLAN, - (enable) ? RTL8366S_SGCR_EN_VLAN : 0); -} - -static int rtl8366s_enable_vlan4k(struct rtl8366_smi *smi, int enable) -{ - return rtl8366_smi_rmwr(smi, RTL8366S_VLAN_TB_CTRL_REG, - 1, (enable) ? 1 : 0); -} - -static int rtl8366s_is_vlan_valid(struct rtl8366_smi *smi, unsigned vlan) -{ - unsigned max = RTL8366S_NUM_VLANS; - - if (smi->vlan4k_enabled) - max = RTL8366S_NUM_VIDS - 1; - - if (vlan == 0 || vlan >= max) - return 0; - - return 1; -} - -static int rtl8366s_enable_port(struct rtl8366_smi *smi, int port, int enable) -{ - return rtl8366_smi_rmwr(smi, RTL8366S_PECR, (1 << port), - (enable) ? 0 : (1 << port)); -} - -static int rtl8366s_sw_reset_mibs(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val) -{ - struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev); - - return rtl8366_smi_rmwr(smi, RTL8366S_MIB_CTRL_REG, 0, (1 << 2)); -} - -static int rtl8366s_sw_get_blinkrate(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val) -{ - struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev); - u32 data; - - rtl8366_smi_read_reg(smi, RTL8366S_LED_BLINKRATE_REG, &data); - - val->value.i = (data & (RTL8366S_LED_BLINKRATE_MASK)); - - return 0; -} - -static int rtl8366s_sw_set_blinkrate(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val) -{ - struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev); - - if (val->value.i >= 6) - return -EINVAL; - - return rtl8366_smi_rmwr(smi, RTL8366S_LED_BLINKRATE_REG, - RTL8366S_LED_BLINKRATE_MASK, - val->value.i); -} - -static int rtl8366s_sw_get_max_length(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val) -{ - struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev); - u32 data; - - rtl8366_smi_read_reg(smi, RTL8366S_SGCR, &data); - - val->value.i = ((data & (RTL8366S_SGCR_MAX_LENGTH_MASK)) >> 4); - - return 0; -} - -static int rtl8366s_sw_set_max_length(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val) -{ - struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev); - char length_code; - - switch (val->value.i) { - case 0: - length_code = RTL8366S_SGCR_MAX_LENGTH_1522; - break; - case 1: - length_code = RTL8366S_SGCR_MAX_LENGTH_1536; - break; - case 2: - length_code = RTL8366S_SGCR_MAX_LENGTH_1552; - break; - case 3: - length_code = RTL8366S_SGCR_MAX_LENGTH_16000; - break; - default: - return -EINVAL; - } - - return rtl8366_smi_rmwr(smi, RTL8366S_SGCR, - RTL8366S_SGCR_MAX_LENGTH_MASK, - length_code); -} - -static int rtl8366s_sw_get_learning_enable(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val) -{ - struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev); - u32 data; - - rtl8366_smi_read_reg(smi,RTL8366S_SSCR0, &data); - val->value.i = !data; - - return 0; -} - - -static int rtl8366s_sw_set_learning_enable(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val) -{ - struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev); - u32 portmask = 0; - int err = 0; - - if (!val->value.i) - portmask = RTL8366S_PORT_ALL; - - /* set learning for all ports */ - REG_WR(smi, RTL8366S_SSCR0, portmask); - - /* set auto ageing for all ports */ - REG_WR(smi, RTL8366S_SSCR1, portmask); - - return 0; -} - -static int rtl8366s_sw_get_green(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val) -{ - struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev); - u32 data; - int err; - - err = rtl8366_smi_read_reg(smi, RTL8366S_GREEN_ETHERNET_CTRL_REG, &data); - if (err) - return err; - - val->value.i = ((data & (RTL8366S_GREEN_ETHERNET_TX_BIT | RTL8366S_GREEN_ETHERNET_RX_BIT)) != 0) ? 1 : 0; - - return 0; -} - -static int rtl8366s_sw_set_green(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val) -{ - struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev); - - return rtl8366s_set_green(smi, val->value.i); -} - -static int rtl8366s_sw_get_port_link(struct switch_dev *dev, - int port, - struct switch_port_link *link) -{ - struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev); - u32 data = 0; - u32 speed; - - if (port >= RTL8366S_NUM_PORTS) - return -EINVAL; - - rtl8366_smi_read_reg(smi, RTL8366S_PORT_LINK_STATUS_BASE + (port / 2), - &data); - - if (port % 2) - data = data >> 8; - - link->link = !!(data & RTL8366S_PORT_STATUS_LINK_MASK); - if (!link->link) - return 0; - - link->duplex = !!(data & RTL8366S_PORT_STATUS_DUPLEX_MASK); - link->rx_flow = !!(data & RTL8366S_PORT_STATUS_RXPAUSE_MASK); - link->tx_flow = !!(data & RTL8366S_PORT_STATUS_TXPAUSE_MASK); - link->aneg = !!(data & RTL8366S_PORT_STATUS_AN_MASK); - - speed = (data & RTL8366S_PORT_STATUS_SPEED_MASK); - switch (speed) { - case 0: - link->speed = SWITCH_PORT_SPEED_10; - break; - case 1: - link->speed = SWITCH_PORT_SPEED_100; - break; - case 2: - link->speed = SWITCH_PORT_SPEED_1000; - break; - default: - link->speed = SWITCH_PORT_SPEED_UNKNOWN; - break; - } - - return 0; -} - -static int rtl8366s_sw_set_port_led(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val) -{ - struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev); - u32 data; - u32 mask; - u32 reg; - - if (val->port_vlan >= RTL8366S_NUM_PORTS || - (1 << val->port_vlan) == RTL8366S_PORT_UNKNOWN) - return -EINVAL; - - if (val->port_vlan == RTL8366S_PORT_NUM_CPU) { - reg = RTL8366S_LED_BLINKRATE_REG; - mask = 0xF << 4; - data = val->value.i << 4; - } else { - reg = RTL8366S_LED_CTRL_REG; - mask = 0xF << (val->port_vlan * 4), - data = val->value.i << (val->port_vlan * 4); - } - - return rtl8366_smi_rmwr(smi, reg, mask, data); -} - -static int rtl8366s_sw_get_port_led(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val) -{ - struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev); - u32 data = 0; - - if (val->port_vlan >= RTL8366S_NUM_LEDGROUPS) - return -EINVAL; - - rtl8366_smi_read_reg(smi, RTL8366S_LED_CTRL_REG, &data); - val->value.i = (data >> (val->port_vlan * 4)) & 0x000F; - - return 0; -} - -static int rtl8366s_sw_get_green_port(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val) -{ - struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev); - int err; - u32 phyData; - - if (val->port_vlan >= RTL8366S_NUM_PORTS) - return -EINVAL; - - err = rtl8366s_read_phy_reg(smi, val->port_vlan, 0, RTL8366S_PHY_POWER_SAVING_CTRL_REG, &phyData); - if (err) - return err; - - val->value.i = ((phyData & RTL8366S_PHY_POWER_SAVING_MASK) != 0) ? 1 : 0; - - return 0; -} - -static int rtl8366s_sw_set_green_port(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val) -{ - struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev); - return rtl8366s_set_green_port(smi, val->port_vlan, val->value.i); -} - -static int rtl8366s_sw_reset_port_mibs(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val) -{ - struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev); - - if (val->port_vlan >= RTL8366S_NUM_PORTS) - return -EINVAL; - - - return rtl8366_smi_rmwr(smi, RTL8366S_MIB_CTRL_REG, - 0, (1 << (val->port_vlan + 3))); -} - -static int rtl8366s_sw_get_port_stats(struct switch_dev *dev, int port, - struct switch_port_stats *stats) -{ - return (rtl8366_sw_get_port_stats(dev, port, stats, - RTL8366S_MIB_TXB_ID, RTL8366S_MIB_RXB_ID)); -} - -static struct switch_attr rtl8366s_globals[] = { - { - .type = SWITCH_TYPE_INT, - .name = "enable_learning", - .description = "Enable learning, enable aging", - .set = rtl8366s_sw_set_learning_enable, - .get = rtl8366s_sw_get_learning_enable, - .max = 1, - }, { - .type = SWITCH_TYPE_INT, - .name = "enable_vlan", - .description = "Enable VLAN mode", - .set = rtl8366_sw_set_vlan_enable, - .get = rtl8366_sw_get_vlan_enable, - .max = 1, - .ofs = 1 - }, { - .type = SWITCH_TYPE_INT, - .name = "enable_vlan4k", - .description = "Enable VLAN 4K mode", - .set = rtl8366_sw_set_vlan_enable, - .get = rtl8366_sw_get_vlan_enable, - .max = 1, - .ofs = 2 - }, { - .type = SWITCH_TYPE_NOVAL, - .name = "reset_mibs", - .description = "Reset all MIB counters", - .set = rtl8366s_sw_reset_mibs, - }, { - .type = SWITCH_TYPE_INT, - .name = "blinkrate", - .description = "Get/Set LED blinking rate (0 = 43ms, 1 = 84ms," - " 2 = 120ms, 3 = 170ms, 4 = 340ms, 5 = 670ms)", - .set = rtl8366s_sw_set_blinkrate, - .get = rtl8366s_sw_get_blinkrate, - .max = 5 - }, { - .type = SWITCH_TYPE_INT, - .name = "max_length", - .description = "Get/Set the maximum length of valid packets" - " (0 = 1522, 1 = 1536, 2 = 1552, 3 = 16000 (9216?))", - .set = rtl8366s_sw_set_max_length, - .get = rtl8366s_sw_get_max_length, - .max = 3, - }, { - .type = SWITCH_TYPE_INT, - .name = "green_mode", - .description = "Get/Set the router green feature", - .set = rtl8366s_sw_set_green, - .get = rtl8366s_sw_get_green, - .max = 1, - }, -}; - -static struct switch_attr rtl8366s_port[] = { - { - .type = SWITCH_TYPE_NOVAL, - .name = "reset_mib", - .description = "Reset single port MIB counters", - .set = rtl8366s_sw_reset_port_mibs, - }, { - .type = SWITCH_TYPE_STRING, - .name = "mib", - .description = "Get MIB counters for port", - .max = 33, - .set = NULL, - .get = rtl8366_sw_get_port_mib, - }, { - .type = SWITCH_TYPE_INT, - .name = "led", - .description = "Get/Set port group (0 - 3) led mode (0 - 15)", - .max = 15, - .set = rtl8366s_sw_set_port_led, - .get = rtl8366s_sw_get_port_led, - }, { - .type = SWITCH_TYPE_INT, - .name = "green_port", - .description = "Get/Set port green feature (0 - 1)", - .max = 1, - .set = rtl8366s_sw_set_green_port, - .get = rtl8366s_sw_get_green_port, - }, -}; - -static struct switch_attr rtl8366s_vlan[] = { - { - .type = SWITCH_TYPE_STRING, - .name = "info", - .description = "Get vlan information", - .max = 1, - .set = NULL, - .get = rtl8366_sw_get_vlan_info, - }, { - .type = SWITCH_TYPE_INT, - .name = "fid", - .description = "Get/Set vlan FID", - .max = RTL8366S_FIDMAX, - .set = rtl8366_sw_set_vlan_fid, - .get = rtl8366_sw_get_vlan_fid, - }, -}; - -static const struct switch_dev_ops rtl8366_ops = { - .attr_global = { - .attr = rtl8366s_globals, - .n_attr = ARRAY_SIZE(rtl8366s_globals), - }, - .attr_port = { - .attr = rtl8366s_port, - .n_attr = ARRAY_SIZE(rtl8366s_port), - }, - .attr_vlan = { - .attr = rtl8366s_vlan, - .n_attr = ARRAY_SIZE(rtl8366s_vlan), - }, - - .get_vlan_ports = rtl8366_sw_get_vlan_ports, - .set_vlan_ports = rtl8366_sw_set_vlan_ports, - .get_port_pvid = rtl8366_sw_get_port_pvid, - .set_port_pvid = rtl8366_sw_set_port_pvid, - .reset_switch = rtl8366_sw_reset_switch, - .get_port_link = rtl8366s_sw_get_port_link, - .get_port_stats = rtl8366s_sw_get_port_stats, -}; - -static int rtl8366s_switch_init(struct rtl8366_smi *smi) -{ - struct switch_dev *dev = &smi->sw_dev; - int err; - - dev->name = "RTL8366S"; - dev->cpu_port = RTL8366S_PORT_NUM_CPU; - dev->ports = RTL8366S_NUM_PORTS; - dev->vlans = RTL8366S_NUM_VIDS; - dev->ops = &rtl8366_ops; - dev->alias = dev_name(smi->parent); - - err = register_switch(dev, NULL); - if (err) - dev_err(smi->parent, "switch registration failed\n"); - - return err; -} - -static void rtl8366s_switch_cleanup(struct rtl8366_smi *smi) -{ - unregister_switch(&smi->sw_dev); -} - -static int rtl8366s_mii_read(struct mii_bus *bus, int addr, int reg) -{ - struct rtl8366_smi *smi = bus->priv; - u32 val = 0; - int err; - - err = rtl8366s_read_phy_reg(smi, addr, 0, reg, &val); - if (err) - return 0xffff; - - return val; -} - -static int rtl8366s_mii_write(struct mii_bus *bus, int addr, int reg, u16 val) -{ - struct rtl8366_smi *smi = bus->priv; - u32 t; - int err; - - err = rtl8366s_write_phy_reg(smi, addr, 0, reg, val); - /* flush write */ - (void) rtl8366s_read_phy_reg(smi, addr, 0, reg, &t); - - return err; -} - -static int rtl8366s_detect(struct rtl8366_smi *smi) -{ - u32 chip_id = 0; - u32 chip_ver = 0; - int ret; - - ret = rtl8366_smi_read_reg(smi, RTL8366S_CHIP_ID_REG, &chip_id); - if (ret) { - dev_err(smi->parent, "unable to read chip id\n"); - return ret; - } - - switch (chip_id) { - case RTL8366S_CHIP_ID_8366: - break; - default: - dev_err(smi->parent, "unknown chip id (%04x)\n", chip_id); - return -ENODEV; - } - - ret = rtl8366_smi_read_reg(smi, RTL8366S_CHIP_VERSION_CTRL_REG, - &chip_ver); - if (ret) { - dev_err(smi->parent, "unable to read chip version\n"); - return ret; - } - - dev_info(smi->parent, "RTL%04x ver. %u chip found\n", - chip_id, chip_ver & RTL8366S_CHIP_VERSION_MASK); - - return 0; -} - -static struct rtl8366_smi_ops rtl8366s_smi_ops = { - .detect = rtl8366s_detect, - .reset_chip = rtl8366s_reset_chip, - .setup = rtl8366s_setup, - - .mii_read = rtl8366s_mii_read, - .mii_write = rtl8366s_mii_write, - - .get_vlan_mc = rtl8366s_get_vlan_mc, - .set_vlan_mc = rtl8366s_set_vlan_mc, - .get_vlan_4k = rtl8366s_get_vlan_4k, - .set_vlan_4k = rtl8366s_set_vlan_4k, - .get_mc_index = rtl8366s_get_mc_index, - .set_mc_index = rtl8366s_set_mc_index, - .get_mib_counter = rtl8366_get_mib_counter, - .is_vlan_valid = rtl8366s_is_vlan_valid, - .enable_vlan = rtl8366s_enable_vlan, - .enable_vlan4k = rtl8366s_enable_vlan4k, - .enable_port = rtl8366s_enable_port, -}; - -static int rtl8366s_probe(struct platform_device *pdev) -{ - static int rtl8366_smi_version_printed; - struct rtl8366_smi *smi; - int err; - - if (!rtl8366_smi_version_printed++) - printk(KERN_NOTICE RTL8366S_DRIVER_DESC - " version " RTL8366S_DRIVER_VER"\n"); - - smi = rtl8366_smi_probe(pdev); - if (IS_ERR(smi)) - return PTR_ERR(smi); - - smi->clk_delay = 10; - smi->cmd_read = 0xa9; - smi->cmd_write = 0xa8; - smi->ops = &rtl8366s_smi_ops; - smi->cpu_port = RTL8366S_PORT_NUM_CPU; - smi->num_ports = RTL8366S_NUM_PORTS; - smi->num_vlan_mc = RTL8366S_NUM_VLANS; - smi->mib_counters = rtl8366s_mib_counters; - smi->num_mib_counters = ARRAY_SIZE(rtl8366s_mib_counters); - - err = rtl8366_smi_init(smi); - if (err) - goto err_free_smi; - - platform_set_drvdata(pdev, smi); - - err = rtl8366s_switch_init(smi); - if (err) - goto err_clear_drvdata; - - return 0; - - err_clear_drvdata: - platform_set_drvdata(pdev, NULL); - rtl8366_smi_cleanup(smi); - err_free_smi: - kfree(smi); - return err; -} - -static int rtl8366s_remove(struct platform_device *pdev) -{ - struct rtl8366_smi *smi = platform_get_drvdata(pdev); - - if (smi) { - rtl8366s_switch_cleanup(smi); - platform_set_drvdata(pdev, NULL); - rtl8366_smi_cleanup(smi); - kfree(smi); - } - - return 0; -} - -#ifdef CONFIG_OF -static const struct of_device_id rtl8366s_match[] = { - { .compatible = "realtek,rtl8366s" }, - {}, -}; -MODULE_DEVICE_TABLE(of, rtl8366s_match); -#endif - -static struct platform_driver rtl8366s_driver = { - .driver = { - .name = RTL8366S_DRIVER_NAME, - .owner = THIS_MODULE, -#ifdef CONFIG_OF - .of_match_table = of_match_ptr(rtl8366s_match), -#endif - }, - .probe = rtl8366s_probe, - .remove = rtl8366s_remove, -}; - -static int __init rtl8366s_module_init(void) -{ - return platform_driver_register(&rtl8366s_driver); -} -module_init(rtl8366s_module_init); - -static void __exit rtl8366s_module_exit(void) -{ - platform_driver_unregister(&rtl8366s_driver); -} -module_exit(rtl8366s_module_exit); - -MODULE_DESCRIPTION(RTL8366S_DRIVER_DESC); -MODULE_VERSION(RTL8366S_DRIVER_VER); -MODULE_AUTHOR("Gabor Juhos "); -MODULE_AUTHOR("Antti Seppälä "); -MODULE_LICENSE("GPL v2"); -MODULE_ALIAS("platform:" RTL8366S_DRIVER_NAME); diff --git a/target/linux/generic/files-6.12/drivers/net/phy/rtl8367.c b/target/linux/generic/files-6.12/drivers/net/phy/rtl8367.c deleted file mode 100644 index 0acfeb54bba587..00000000000000 --- a/target/linux/generic/files-6.12/drivers/net/phy/rtl8367.c +++ /dev/null @@ -1,1862 +0,0 @@ -/* - * Platform driver for the Realtek RTL8367R/M ethernet switches - * - * Copyright (C) 2011 Gabor Juhos - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published - * by the Free Software Foundation. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "rtl8366_smi.h" - -#define RTL8367_RESET_DELAY 1000 /* msecs*/ - -#define RTL8367_PHY_ADDR_MAX 8 -#define RTL8367_PHY_REG_MAX 31 - -#define RTL8367_VID_MASK 0xffff -#define RTL8367_FID_MASK 0xfff -#define RTL8367_UNTAG_MASK 0xffff -#define RTL8367_MEMBER_MASK 0xffff - -#define RTL8367_PORT_CFG_REG(_p) (0x000e + 0x20 * (_p)) -#define RTL8367_PORT_CFG_EGRESS_MODE_SHIFT 4 -#define RTL8367_PORT_CFG_EGRESS_MODE_MASK 0x3 -#define RTL8367_PORT_CFG_EGRESS_MODE_ORIGINAL 0 -#define RTL8367_PORT_CFG_EGRESS_MODE_KEEP 1 -#define RTL8367_PORT_CFG_EGRESS_MODE_PRI 2 -#define RTL8367_PORT_CFG_EGRESS_MODE_REAL 3 - -#define RTL8367_BYPASS_LINE_RATE_REG 0x03f7 - -#define RTL8367_TA_CTRL_REG 0x0500 -#define RTL8367_TA_CTRL_STATUS BIT(12) -#define RTL8367_TA_CTRL_METHOD BIT(5) -#define RTL8367_TA_CTRL_CMD_SHIFT 4 -#define RTL8367_TA_CTRL_CMD_READ 0 -#define RTL8367_TA_CTRL_CMD_WRITE 1 -#define RTL8367_TA_CTRL_TABLE_SHIFT 0 -#define RTL8367_TA_CTRL_TABLE_ACLRULE 1 -#define RTL8367_TA_CTRL_TABLE_ACLACT 2 -#define RTL8367_TA_CTRL_TABLE_CVLAN 3 -#define RTL8367_TA_CTRL_TABLE_L2 4 -#define RTL8367_TA_CTRL_CVLAN_READ \ - ((RTL8367_TA_CTRL_CMD_READ << RTL8367_TA_CTRL_CMD_SHIFT) | \ - RTL8367_TA_CTRL_TABLE_CVLAN) -#define RTL8367_TA_CTRL_CVLAN_WRITE \ - ((RTL8367_TA_CTRL_CMD_WRITE << RTL8367_TA_CTRL_CMD_SHIFT) | \ - RTL8367_TA_CTRL_TABLE_CVLAN) - -#define RTL8367_TA_ADDR_REG 0x0501 -#define RTL8367_TA_ADDR_MASK 0x3fff - -#define RTL8367_TA_DATA_REG(_x) (0x0503 + (_x)) -#define RTL8367_TA_VLAN_DATA_SIZE 4 -#define RTL8367_TA_VLAN_VID_MASK RTL8367_VID_MASK -#define RTL8367_TA_VLAN_MEMBER_SHIFT 0 -#define RTL8367_TA_VLAN_MEMBER_MASK RTL8367_MEMBER_MASK -#define RTL8367_TA_VLAN_FID_SHIFT 0 -#define RTL8367_TA_VLAN_FID_MASK RTL8367_FID_MASK -#define RTL8367_TA_VLAN_UNTAG1_SHIFT 14 -#define RTL8367_TA_VLAN_UNTAG1_MASK 0x3 -#define RTL8367_TA_VLAN_UNTAG2_SHIFT 0 -#define RTL8367_TA_VLAN_UNTAG2_MASK 0x3fff - -#define RTL8367_VLAN_PVID_CTRL_REG(_p) (0x0700 + (_p) / 2) -#define RTL8367_VLAN_PVID_CTRL_MASK 0x1f -#define RTL8367_VLAN_PVID_CTRL_SHIFT(_p) (8 * ((_p) % 2)) - -#define RTL8367_VLAN_MC_BASE(_x) (0x0728 + (_x) * 4) -#define RTL8367_VLAN_MC_DATA_SIZE 4 -#define RTL8367_VLAN_MC_MEMBER_SHIFT 0 -#define RTL8367_VLAN_MC_MEMBER_MASK RTL8367_MEMBER_MASK -#define RTL8367_VLAN_MC_FID_SHIFT 0 -#define RTL8367_VLAN_MC_FID_MASK RTL8367_FID_MASK -#define RTL8367_VLAN_MC_EVID_SHIFT 0 -#define RTL8367_VLAN_MC_EVID_MASK RTL8367_VID_MASK - -#define RTL8367_VLAN_CTRL_REG 0x07a8 -#define RTL8367_VLAN_CTRL_ENABLE BIT(0) - -#define RTL8367_VLAN_INGRESS_REG 0x07a9 - -#define RTL8367_PORT_ISOLATION_REG(_p) (0x08a2 + (_p)) - -#define RTL8367_MIB_COUNTER_REG(_x) (0x1000 + (_x)) - -#define RTL8367_MIB_ADDRESS_REG 0x1004 - -#define RTL8367_MIB_CTRL_REG(_x) (0x1005 + (_x)) -#define RTL8367_MIB_CTRL_GLOBAL_RESET_MASK BIT(11) -#define RTL8367_MIB_CTRL_QM_RESET_MASK BIT(10) -#define RTL8367_MIB_CTRL_PORT_RESET_MASK(_p) BIT(2 + (_p)) -#define RTL8367_MIB_CTRL_RESET_MASK BIT(1) -#define RTL8367_MIB_CTRL_BUSY_MASK BIT(0) - -#define RTL8367_MIB_COUNT 36 -#define RTL8367_MIB_COUNTER_PORT_OFFSET 0x0050 - -#define RTL8367_SWC0_REG 0x1200 -#define RTL8367_SWC0_MAX_LENGTH_SHIFT 13 -#define RTL8367_SWC0_MAX_LENGTH(_x) ((_x) << 13) -#define RTL8367_SWC0_MAX_LENGTH_MASK RTL8367_SWC0_MAX_LENGTH(0x3) -#define RTL8367_SWC0_MAX_LENGTH_1522 RTL8367_SWC0_MAX_LENGTH(0) -#define RTL8367_SWC0_MAX_LENGTH_1536 RTL8367_SWC0_MAX_LENGTH(1) -#define RTL8367_SWC0_MAX_LENGTH_1552 RTL8367_SWC0_MAX_LENGTH(2) -#define RTL8367_SWC0_MAX_LENGTH_16000 RTL8367_SWC0_MAX_LENGTH(3) - -#define RTL8367_CHIP_NUMBER_REG 0x1300 - -#define RTL8367_CHIP_VER_REG 0x1301 -#define RTL8367_CHIP_VER_RLVID_SHIFT 12 -#define RTL8367_CHIP_VER_RLVID_MASK 0xf -#define RTL8367_CHIP_VER_MCID_SHIFT 8 -#define RTL8367_CHIP_VER_MCID_MASK 0xf -#define RTL8367_CHIP_VER_BOID_SHIFT 4 -#define RTL8367_CHIP_VER_BOID_MASK 0xf - -#define RTL8367_CHIP_MODE_REG 0x1302 -#define RTL8367_CHIP_MODE_MASK 0x7 - -#define RTL8367_CHIP_DEBUG0_REG 0x1303 -#define RTL8367_CHIP_DEBUG0_DUMMY0(_x) BIT(8 + (_x)) - -#define RTL8367_CHIP_DEBUG1_REG 0x1304 - -#define RTL8367_DIS_REG 0x1305 -#define RTL8367_DIS_SKIP_MII_RXER(_x) BIT(12 + (_x)) -#define RTL8367_DIS_RGMII_SHIFT(_x) (4 * (_x)) -#define RTL8367_DIS_RGMII_MASK 0x7 - -#define RTL8367_EXT_RGMXF_REG(_x) (0x1306 + (_x)) -#define RTL8367_EXT_RGMXF_DUMMY0_SHIFT 5 -#define RTL8367_EXT_RGMXF_DUMMY0_MASK 0x7ff -#define RTL8367_EXT_RGMXF_TXDELAY_SHIFT 3 -#define RTL8367_EXT_RGMXF_TXDELAY_MASK 1 -#define RTL8367_EXT_RGMXF_RXDELAY_MASK 0x7 - -#define RTL8367_DI_FORCE_REG(_x) (0x1310 + (_x)) -#define RTL8367_DI_FORCE_MODE BIT(12) -#define RTL8367_DI_FORCE_NWAY BIT(7) -#define RTL8367_DI_FORCE_TXPAUSE BIT(6) -#define RTL8367_DI_FORCE_RXPAUSE BIT(5) -#define RTL8367_DI_FORCE_LINK BIT(4) -#define RTL8367_DI_FORCE_DUPLEX BIT(2) -#define RTL8367_DI_FORCE_SPEED_MASK 3 -#define RTL8367_DI_FORCE_SPEED_10 0 -#define RTL8367_DI_FORCE_SPEED_100 1 -#define RTL8367_DI_FORCE_SPEED_1000 2 - -#define RTL8367_MAC_FORCE_REG(_x) (0x1312 + (_x)) - -#define RTL8367_CHIP_RESET_REG 0x1322 -#define RTL8367_CHIP_RESET_SW BIT(1) -#define RTL8367_CHIP_RESET_HW BIT(0) - -#define RTL8367_PORT_STATUS_REG(_p) (0x1352 + (_p)) -#define RTL8367_PORT_STATUS_NWAY BIT(7) -#define RTL8367_PORT_STATUS_TXPAUSE BIT(6) -#define RTL8367_PORT_STATUS_RXPAUSE BIT(5) -#define RTL8367_PORT_STATUS_LINK BIT(4) -#define RTL8367_PORT_STATUS_DUPLEX BIT(2) -#define RTL8367_PORT_STATUS_SPEED_MASK 0x0003 -#define RTL8367_PORT_STATUS_SPEED_10 0 -#define RTL8367_PORT_STATUS_SPEED_100 1 -#define RTL8367_PORT_STATUS_SPEED_1000 2 - -#define RTL8367_RTL_NO_REG 0x13c0 -#define RTL8367_RTL_NO_8367R 0x3670 -#define RTL8367_RTL_NO_8367M 0x3671 - -#define RTL8367_RTL_VER_REG 0x13c1 -#define RTL8367_RTL_VER_MASK 0xf - -#define RTL8367_RTL_MAGIC_ID_REG 0x13c2 -#define RTL8367_RTL_MAGIC_ID_VAL 0x0249 - -#define RTL8367_LED_SYS_CONFIG_REG 0x1b00 -#define RTL8367_LED_MODE_REG 0x1b02 -#define RTL8367_LED_MODE_RATE_M 0x7 -#define RTL8367_LED_MODE_RATE_S 1 - -#define RTL8367_LED_CONFIG_REG 0x1b03 -#define RTL8367_LED_CONFIG_DATA_S 12 -#define RTL8367_LED_CONFIG_DATA_M 0x3 -#define RTL8367_LED_CONFIG_SEL BIT(14) -#define RTL8367_LED_CONFIG_LED_CFG_M 0xf - -#define RTL8367_PARA_LED_IO_EN1_REG 0x1b24 -#define RTL8367_PARA_LED_IO_EN2_REG 0x1b25 -#define RTL8367_PARA_LED_IO_EN_PMASK 0xff - -#define RTL8367_IA_CTRL_REG 0x1f00 -#define RTL8367_IA_CTRL_RW(_x) ((_x) << 1) -#define RTL8367_IA_CTRL_RW_READ RTL8367_IA_CTRL_RW(0) -#define RTL8367_IA_CTRL_RW_WRITE RTL8367_IA_CTRL_RW(1) -#define RTL8367_IA_CTRL_CMD_MASK BIT(0) - -#define RTL8367_IA_STATUS_REG 0x1f01 -#define RTL8367_IA_STATUS_PHY_BUSY BIT(2) -#define RTL8367_IA_STATUS_SDS_BUSY BIT(1) -#define RTL8367_IA_STATUS_MDX_BUSY BIT(0) - -#define RTL8367_IA_ADDRESS_REG 0x1f02 - -#define RTL8367_IA_WRITE_DATA_REG 0x1f03 -#define RTL8367_IA_READ_DATA_REG 0x1f04 - -#define RTL8367_INTERNAL_PHY_REG(_a, _r) (0x2000 + 32 * (_a) + (_r)) - -#define RTL8367_CPU_PORT_NUM 9 -#define RTL8367_NUM_PORTS 10 -#define RTL8367_NUM_VLANS 32 -#define RTL8367_NUM_LEDGROUPS 4 -#define RTL8367_NUM_VIDS 4096 -#define RTL8367_PRIORITYMAX 7 -#define RTL8367_FIDMAX 7 - -#define RTL8367_PORT_0 BIT(0) -#define RTL8367_PORT_1 BIT(1) -#define RTL8367_PORT_2 BIT(2) -#define RTL8367_PORT_3 BIT(3) -#define RTL8367_PORT_4 BIT(4) -#define RTL8367_PORT_5 BIT(5) -#define RTL8367_PORT_6 BIT(6) -#define RTL8367_PORT_7 BIT(7) -#define RTL8367_PORT_E1 BIT(8) /* external port 1 */ -#define RTL8367_PORT_E0 BIT(9) /* external port 0 */ - -#define RTL8367_PORTS_ALL \ - (RTL8367_PORT_0 | RTL8367_PORT_1 | RTL8367_PORT_2 | \ - RTL8367_PORT_3 | RTL8367_PORT_4 | RTL8367_PORT_5 | \ - RTL8367_PORT_6 | RTL8367_PORT_7 | RTL8367_PORT_E1 | \ - RTL8367_PORT_E0) - -#define RTL8367_PORTS_ALL_BUT_CPU \ - (RTL8367_PORT_0 | RTL8367_PORT_1 | RTL8367_PORT_2 | \ - RTL8367_PORT_3 | RTL8367_PORT_4 | RTL8367_PORT_5 | \ - RTL8367_PORT_6 | RTL8367_PORT_7 | RTL8367_PORT_E1) - -struct rtl8367_initval { - u16 reg; - u16 val; -}; - -#define RTL8367_MIB_RXB_ID 0 /* IfInOctets */ -#define RTL8367_MIB_TXB_ID 20 /* IfOutOctets */ - -static struct rtl8366_mib_counter rtl8367_mib_counters[] = { - { 0, 0, 4, "IfInOctets" }, - { 0, 4, 2, "Dot3StatsFCSErrors" }, - { 0, 6, 2, "Dot3StatsSymbolErrors" }, - { 0, 8, 2, "Dot3InPauseFrames" }, - { 0, 10, 2, "Dot3ControlInUnknownOpcodes" }, - { 0, 12, 2, "EtherStatsFragments" }, - { 0, 14, 2, "EtherStatsJabbers" }, - { 0, 16, 2, "IfInUcastPkts" }, - { 0, 18, 2, "EtherStatsDropEvents" }, - { 0, 20, 4, "EtherStatsOctets" }, - - { 0, 24, 2, "EtherStatsUnderSizePkts" }, - { 0, 26, 2, "EtherOversizeStats" }, - { 0, 28, 2, "EtherStatsPkts64Octets" }, - { 0, 30, 2, "EtherStatsPkts65to127Octets" }, - { 0, 32, 2, "EtherStatsPkts128to255Octets" }, - { 0, 34, 2, "EtherStatsPkts256to511Octets" }, - { 0, 36, 2, "EtherStatsPkts512to1023Octets" }, - { 0, 38, 2, "EtherStatsPkts1024to1518Octets" }, - { 0, 40, 2, "EtherStatsMulticastPkts" }, - { 0, 42, 2, "EtherStatsBroadcastPkts" }, - - { 0, 44, 4, "IfOutOctets" }, - - { 0, 48, 2, "Dot3StatsSingleCollisionFrames" }, - { 0, 50, 2, "Dot3StatMultipleCollisionFrames" }, - { 0, 52, 2, "Dot3sDeferredTransmissions" }, - { 0, 54, 2, "Dot3StatsLateCollisions" }, - { 0, 56, 2, "EtherStatsCollisions" }, - { 0, 58, 2, "Dot3StatsExcessiveCollisions" }, - { 0, 60, 2, "Dot3OutPauseFrames" }, - { 0, 62, 2, "Dot1dBasePortDelayExceededDiscards" }, - { 0, 64, 2, "Dot1dTpPortInDiscards" }, - { 0, 66, 2, "IfOutUcastPkts" }, - { 0, 68, 2, "IfOutMulticastPkts" }, - { 0, 70, 2, "IfOutBroadcastPkts" }, - { 0, 72, 2, "OutOampduPkts" }, - { 0, 74, 2, "InOampduPkts" }, - { 0, 76, 2, "PktgenPkts" }, -}; - -#define REG_RD(_smi, _reg, _val) \ - do { \ - err = rtl8366_smi_read_reg(_smi, _reg, _val); \ - if (err) \ - return err; \ - } while (0) - -#define REG_WR(_smi, _reg, _val) \ - do { \ - err = rtl8366_smi_write_reg(_smi, _reg, _val); \ - if (err) \ - return err; \ - } while (0) - -#define REG_RMW(_smi, _reg, _mask, _val) \ - do { \ - err = rtl8366_smi_rmwr(_smi, _reg, _mask, _val); \ - if (err) \ - return err; \ - } while (0) - -static const struct rtl8367_initval rtl8367_initvals_0_0[] = { - {0x133f, 0x0030}, {0x133e, 0x000e}, {0x221f, 0x0000}, {0x2215, 0x1006}, - {0x221f, 0x0005}, {0x2200, 0x00c6}, {0x221f, 0x0007}, {0x221e, 0x0048}, - {0x2215, 0x6412}, {0x2216, 0x6412}, {0x2217, 0x6412}, {0x2218, 0x6412}, - {0x2219, 0x6412}, {0x221A, 0x6412}, {0x221f, 0x0001}, {0x220c, 0xdbf0}, - {0x2209, 0x2576}, {0x2207, 0x287E}, {0x220A, 0x68E5}, {0x221D, 0x3DA4}, - {0x221C, 0xE7F7}, {0x2214, 0x7F52}, {0x2218, 0x7FCE}, {0x2208, 0x04B7}, - {0x2206, 0x4072}, {0x2210, 0xF05E}, {0x221B, 0xB414}, {0x221F, 0x0003}, - {0x221A, 0x06A6}, {0x2210, 0xF05E}, {0x2213, 0x06EB}, {0x2212, 0xF4D2}, - {0x220E, 0xE120}, {0x2200, 0x7C00}, {0x2202, 0x5FD0}, {0x220D, 0x0207}, - {0x221f, 0x0002}, {0x2205, 0x0978}, {0x2202, 0x8C01}, {0x2207, 0x3620}, - {0x221C, 0x0001}, {0x2203, 0x0420}, {0x2204, 0x80C8}, {0x133e, 0x0ede}, - {0x221f, 0x0002}, {0x220c, 0x0073}, {0x220d, 0xEB65}, {0x220e, 0x51d1}, - {0x220f, 0x5dcb}, {0x2210, 0x3044}, {0x2211, 0x1800}, {0x2212, 0x7E00}, - {0x2213, 0x0000}, {0x133f, 0x0010}, {0x133e, 0x0ffe}, {0x207f, 0x0002}, - {0x2074, 0x3D22}, {0x2075, 0x2000}, {0x2076, 0x6040}, {0x2077, 0x0000}, - {0x2078, 0x0f0a}, {0x2079, 0x50AB}, {0x207a, 0x0000}, {0x207b, 0x0f0f}, - {0x205f, 0x0002}, {0x2054, 0xFF00}, {0x2055, 0x000A}, {0x2056, 0x000A}, - {0x2057, 0x0005}, {0x2058, 0x0005}, {0x2059, 0x0000}, {0x205A, 0x0005}, - {0x205B, 0x0005}, {0x205C, 0x0005}, {0x209f, 0x0002}, {0x2094, 0x00AA}, - {0x2095, 0x00AA}, {0x2096, 0x00AA}, {0x2097, 0x00AA}, {0x2098, 0x0055}, - {0x2099, 0x00AA}, {0x209A, 0x00AA}, {0x209B, 0x00AA}, {0x1363, 0x8354}, - {0x1270, 0x3333}, {0x1271, 0x3333}, {0x1272, 0x3333}, {0x1330, 0x00DB}, - {0x1203, 0xff00}, {0x1200, 0x7fc4}, {0x121d, 0x1006}, {0x121e, 0x03e8}, - {0x121f, 0x02b3}, {0x1220, 0x028f}, {0x1221, 0x029b}, {0x1222, 0x0277}, - {0x1223, 0x02b3}, {0x1224, 0x028f}, {0x1225, 0x029b}, {0x1226, 0x0277}, - {0x1227, 0x00c0}, {0x1228, 0x00b4}, {0x122f, 0x00c0}, {0x1230, 0x00b4}, - {0x1229, 0x0020}, {0x122a, 0x000c}, {0x1231, 0x0030}, {0x1232, 0x0024}, - {0x0219, 0x0032}, {0x0200, 0x03e8}, {0x0201, 0x03e8}, {0x0202, 0x03e8}, - {0x0203, 0x03e8}, {0x0204, 0x03e8}, {0x0205, 0x03e8}, {0x0206, 0x03e8}, - {0x0207, 0x03e8}, {0x0218, 0x0032}, {0x0208, 0x029b}, {0x0209, 0x029b}, - {0x020a, 0x029b}, {0x020b, 0x029b}, {0x020c, 0x029b}, {0x020d, 0x029b}, - {0x020e, 0x029b}, {0x020f, 0x029b}, {0x0210, 0x029b}, {0x0211, 0x029b}, - {0x0212, 0x029b}, {0x0213, 0x029b}, {0x0214, 0x029b}, {0x0215, 0x029b}, - {0x0216, 0x029b}, {0x0217, 0x029b}, {0x0900, 0x0000}, {0x0901, 0x0000}, - {0x0902, 0x0000}, {0x0903, 0x0000}, {0x0865, 0x3210}, {0x087b, 0x0000}, - {0x087c, 0xff00}, {0x087d, 0x0000}, {0x087e, 0x0000}, {0x0801, 0x0100}, - {0x0802, 0x0100}, {0x1700, 0x014C}, {0x0301, 0x00FF}, {0x12AA, 0x0096}, - {0x133f, 0x0030}, {0x133e, 0x000e}, {0x221f, 0x0005}, {0x2200, 0x00C4}, - {0x221f, 0x0000}, {0x2210, 0x05EF}, {0x2204, 0x05E1}, {0x2200, 0x1340}, - {0x133f, 0x0010}, {0x20A0, 0x1940}, {0x20C0, 0x1940}, {0x20E0, 0x1940}, -}; - -static const struct rtl8367_initval rtl8367_initvals_0_1[] = { - {0x133f, 0x0030}, {0x133e, 0x000e}, {0x221f, 0x0000}, {0x2215, 0x1006}, - {0x221f, 0x0005}, {0x2200, 0x00c6}, {0x221f, 0x0007}, {0x221e, 0x0048}, - {0x2215, 0x6412}, {0x2216, 0x6412}, {0x2217, 0x6412}, {0x2218, 0x6412}, - {0x2219, 0x6412}, {0x221A, 0x6412}, {0x221f, 0x0001}, {0x220c, 0xdbf0}, - {0x2209, 0x2576}, {0x2207, 0x287E}, {0x220A, 0x68E5}, {0x221D, 0x3DA4}, - {0x221C, 0xE7F7}, {0x2214, 0x7F52}, {0x2218, 0x7FCE}, {0x2208, 0x04B7}, - {0x2206, 0x4072}, {0x2210, 0xF05E}, {0x221B, 0xB414}, {0x221F, 0x0003}, - {0x221A, 0x06A6}, {0x2210, 0xF05E}, {0x2213, 0x06EB}, {0x2212, 0xF4D2}, - {0x220E, 0xE120}, {0x2200, 0x7C00}, {0x2202, 0x5FD0}, {0x220D, 0x0207}, - {0x221f, 0x0002}, {0x2205, 0x0978}, {0x2202, 0x8C01}, {0x2207, 0x3620}, - {0x221C, 0x0001}, {0x2203, 0x0420}, {0x2204, 0x80C8}, {0x133e, 0x0ede}, - {0x221f, 0x0002}, {0x220c, 0x0073}, {0x220d, 0xEB65}, {0x220e, 0x51d1}, - {0x220f, 0x5dcb}, {0x2210, 0x3044}, {0x2211, 0x1800}, {0x2212, 0x7E00}, - {0x2213, 0x0000}, {0x133f, 0x0010}, {0x133e, 0x0ffe}, {0x207f, 0x0002}, - {0x2074, 0x3D22}, {0x2075, 0x2000}, {0x2076, 0x6040}, {0x2077, 0x0000}, - {0x2078, 0x0f0a}, {0x2079, 0x50AB}, {0x207a, 0x0000}, {0x207b, 0x0f0f}, - {0x205f, 0x0002}, {0x2054, 0xFF00}, {0x2055, 0x000A}, {0x2056, 0x000A}, - {0x2057, 0x0005}, {0x2058, 0x0005}, {0x2059, 0x0000}, {0x205A, 0x0005}, - {0x205B, 0x0005}, {0x205C, 0x0005}, {0x209f, 0x0002}, {0x2094, 0x00AA}, - {0x2095, 0x00AA}, {0x2096, 0x00AA}, {0x2097, 0x00AA}, {0x2098, 0x0055}, - {0x2099, 0x00AA}, {0x209A, 0x00AA}, {0x209B, 0x00AA}, {0x1363, 0x8354}, - {0x1270, 0x3333}, {0x1271, 0x3333}, {0x1272, 0x3333}, {0x1330, 0x00DB}, - {0x1203, 0xff00}, {0x1200, 0x7fc4}, {0x121d, 0x1b06}, {0x121e, 0x07f0}, - {0x121f, 0x0438}, {0x1220, 0x040f}, {0x1221, 0x040f}, {0x1222, 0x03eb}, - {0x1223, 0x0438}, {0x1224, 0x040f}, {0x1225, 0x040f}, {0x1226, 0x03eb}, - {0x1227, 0x0144}, {0x1228, 0x0138}, {0x122f, 0x0144}, {0x1230, 0x0138}, - {0x1229, 0x0020}, {0x122a, 0x000c}, {0x1231, 0x0030}, {0x1232, 0x0024}, - {0x0219, 0x0032}, {0x0200, 0x07d0}, {0x0201, 0x07d0}, {0x0202, 0x07d0}, - {0x0203, 0x07d0}, {0x0204, 0x07d0}, {0x0205, 0x07d0}, {0x0206, 0x07d0}, - {0x0207, 0x07d0}, {0x0218, 0x0032}, {0x0208, 0x0190}, {0x0209, 0x0190}, - {0x020a, 0x0190}, {0x020b, 0x0190}, {0x020c, 0x0190}, {0x020d, 0x0190}, - {0x020e, 0x0190}, {0x020f, 0x0190}, {0x0210, 0x0190}, {0x0211, 0x0190}, - {0x0212, 0x0190}, {0x0213, 0x0190}, {0x0214, 0x0190}, {0x0215, 0x0190}, - {0x0216, 0x0190}, {0x0217, 0x0190}, {0x0900, 0x0000}, {0x0901, 0x0000}, - {0x0902, 0x0000}, {0x0903, 0x0000}, {0x0865, 0x3210}, {0x087b, 0x0000}, - {0x087c, 0xff00}, {0x087d, 0x0000}, {0x087e, 0x0000}, {0x0801, 0x0100}, - {0x0802, 0x0100}, {0x1700, 0x0125}, {0x0301, 0x00FF}, {0x12AA, 0x0096}, - {0x133f, 0x0030}, {0x133e, 0x000e}, {0x221f, 0x0005}, {0x2200, 0x00C4}, - {0x221f, 0x0000}, {0x2210, 0x05EF}, {0x2204, 0x05E1}, {0x2200, 0x1340}, - {0x133f, 0x0010}, -}; - -static const struct rtl8367_initval rtl8367_initvals_1_0[] = { - {0x1B24, 0x0000}, {0x1B25, 0x0000}, {0x1B26, 0x0000}, {0x1B27, 0x0000}, - {0x207F, 0x0002}, {0x2079, 0x0200}, {0x207F, 0x0000}, {0x133F, 0x0030}, - {0x133E, 0x000E}, {0x221F, 0x0005}, {0x2201, 0x0700}, {0x2205, 0x8B82}, - {0x2206, 0x05CB}, {0x221F, 0x0002}, {0x2204, 0x80C2}, {0x2205, 0x0938}, - {0x221F, 0x0003}, {0x2212, 0xC4D2}, {0x220D, 0x0207}, {0x221F, 0x0001}, - {0x2207, 0x267E}, {0x221C, 0xE5F7}, {0x221B, 0x0424}, {0x221F, 0x0007}, - {0x221E, 0x0040}, {0x2218, 0x0000}, {0x221F, 0x0007}, {0x221E, 0x002C}, - {0x2218, 0x008B}, {0x221F, 0x0005}, {0x2205, 0xFFF6}, {0x2206, 0x0080}, - {0x2205, 0x8000}, {0x2206, 0xF8E0}, {0x2206, 0xE000}, {0x2206, 0xE1E0}, - {0x2206, 0x01AC}, {0x2206, 0x2408}, {0x2206, 0xE08B}, {0x2206, 0x84F7}, - {0x2206, 0x20E4}, {0x2206, 0x8B84}, {0x2206, 0xFC05}, {0x2206, 0xF8FA}, - {0x2206, 0xEF69}, {0x2206, 0xE08B}, {0x2206, 0x86AC}, {0x2206, 0x201A}, - {0x2206, 0xBF80}, {0x2206, 0x59D0}, {0x2206, 0x2402}, {0x2206, 0x803D}, - {0x2206, 0xE0E0}, {0x2206, 0xE4E1}, {0x2206, 0xE0E5}, {0x2206, 0x5806}, - {0x2206, 0x68C0}, {0x2206, 0xD1D2}, {0x2206, 0xE4E0}, {0x2206, 0xE4E5}, - {0x2206, 0xE0E5}, {0x2206, 0xEF96}, {0x2206, 0xFEFC}, {0x2206, 0x05FB}, - {0x2206, 0x0BFB}, {0x2206, 0x58FF}, {0x2206, 0x9E11}, {0x2206, 0x06F0}, - {0x2206, 0x0C81}, {0x2206, 0x8AE0}, {0x2206, 0x0019}, {0x2206, 0x1B89}, - {0x2206, 0xCFEB}, {0x2206, 0x19EB}, {0x2206, 0x19B0}, {0x2206, 0xEFFF}, - {0x2206, 0x0BFF}, {0x2206, 0x0425}, {0x2206, 0x0807}, {0x2206, 0x2640}, - {0x2206, 0x7227}, {0x2206, 0x267E}, {0x2206, 0x2804}, {0x2206, 0xB729}, - {0x2206, 0x2576}, {0x2206, 0x2A68}, {0x2206, 0xE52B}, {0x2206, 0xAD00}, - {0x2206, 0x2CDB}, {0x2206, 0xF02D}, {0x2206, 0x67BB}, {0x2206, 0x2E7B}, - {0x2206, 0x0F2F}, {0x2206, 0x7365}, {0x2206, 0x31AC}, {0x2206, 0xCC32}, - {0x2206, 0x2300}, {0x2206, 0x332D}, {0x2206, 0x1734}, {0x2206, 0x7F52}, - {0x2206, 0x3510}, {0x2206, 0x0036}, {0x2206, 0x0600}, {0x2206, 0x370C}, - {0x2206, 0xC038}, {0x2206, 0x7FCE}, {0x2206, 0x3CE5}, {0x2206, 0xF73D}, - {0x2206, 0x3DA4}, {0x2206, 0x6530}, {0x2206, 0x3E67}, {0x2206, 0x0053}, - {0x2206, 0x69D2}, {0x2206, 0x0F6A}, {0x2206, 0x012C}, {0x2206, 0x6C2B}, - {0x2206, 0x136E}, {0x2206, 0xE100}, {0x2206, 0x6F12}, {0x2206, 0xF771}, - {0x2206, 0x006B}, {0x2206, 0x7306}, {0x2206, 0xEB74}, {0x2206, 0x94C7}, - {0x2206, 0x7698}, {0x2206, 0x0A77}, {0x2206, 0x5000}, {0x2206, 0x788A}, - {0x2206, 0x1579}, {0x2206, 0x7F6F}, {0x2206, 0x7A06}, {0x2206, 0xA600}, - {0x2205, 0x8B90}, {0x2206, 0x8000}, {0x2205, 0x8B92}, {0x2206, 0x8000}, - {0x2205, 0x8B94}, {0x2206, 0x8014}, {0x2208, 0xFFFA}, {0x2202, 0x3C65}, - {0x2205, 0xFFF6}, {0x2206, 0x00F7}, {0x221F, 0x0000}, {0x221F, 0x0007}, - {0x221E, 0x0042}, {0x2218, 0x0000}, {0x221E, 0x002D}, {0x2218, 0xF010}, - {0x221E, 0x0020}, {0x2215, 0x0000}, {0x221E, 0x0023}, {0x2216, 0x8000}, - {0x221F, 0x0000}, {0x133F, 0x0010}, {0x133E, 0x0FFE}, {0x1362, 0x0115}, - {0x1363, 0x0002}, {0x1363, 0x0000}, {0x1306, 0x000C}, {0x1307, 0x000C}, - {0x1303, 0x0067}, {0x1304, 0x4444}, {0x1203, 0xFF00}, {0x1200, 0x7FC4}, - {0x121D, 0x7D16}, {0x121E, 0x03E8}, {0x121F, 0x024E}, {0x1220, 0x0230}, - {0x1221, 0x0244}, {0x1222, 0x0226}, {0x1223, 0x024E}, {0x1224, 0x0230}, - {0x1225, 0x0244}, {0x1226, 0x0226}, {0x1227, 0x00C0}, {0x1228, 0x00B4}, - {0x122F, 0x00C0}, {0x1230, 0x00B4}, {0x0208, 0x03E8}, {0x0209, 0x03E8}, - {0x020A, 0x03E8}, {0x020B, 0x03E8}, {0x020C, 0x03E8}, {0x020D, 0x03E8}, - {0x020E, 0x03E8}, {0x020F, 0x03E8}, {0x0210, 0x03E8}, {0x0211, 0x03E8}, - {0x0212, 0x03E8}, {0x0213, 0x03E8}, {0x0214, 0x03E8}, {0x0215, 0x03E8}, - {0x0216, 0x03E8}, {0x0217, 0x03E8}, {0x0900, 0x0000}, {0x0901, 0x0000}, - {0x0902, 0x0000}, {0x0903, 0x0000}, {0x0865, 0x3210}, {0x087B, 0x0000}, - {0x087C, 0xFF00}, {0x087D, 0x0000}, {0x087E, 0x0000}, {0x0801, 0x0100}, - {0x0802, 0x0100}, {0x0A20, 0x2040}, {0x0A21, 0x2040}, {0x0A22, 0x2040}, - {0x0A23, 0x2040}, {0x0A24, 0x2040}, {0x0A28, 0x2040}, {0x0A29, 0x2040}, - {0x133F, 0x0030}, {0x133E, 0x000E}, {0x221F, 0x0000}, {0x2200, 0x1340}, - {0x221F, 0x0000}, {0x133F, 0x0010}, {0x133E, 0x0FFE}, {0x20A0, 0x1940}, - {0x20C0, 0x1940}, {0x20E0, 0x1940}, {0x130c, 0x0050}, -}; - -static const struct rtl8367_initval rtl8367_initvals_1_1[] = { - {0x1B24, 0x0000}, {0x1B25, 0x0000}, {0x1B26, 0x0000}, {0x1B27, 0x0000}, - {0x207F, 0x0002}, {0x2079, 0x0200}, {0x207F, 0x0000}, {0x133F, 0x0030}, - {0x133E, 0x000E}, {0x221F, 0x0005}, {0x2201, 0x0700}, {0x2205, 0x8B82}, - {0x2206, 0x05CB}, {0x221F, 0x0002}, {0x2204, 0x80C2}, {0x2205, 0x0938}, - {0x221F, 0x0003}, {0x2212, 0xC4D2}, {0x220D, 0x0207}, {0x221F, 0x0001}, - {0x2207, 0x267E}, {0x221C, 0xE5F7}, {0x221B, 0x0424}, {0x221F, 0x0007}, - {0x221E, 0x0040}, {0x2218, 0x0000}, {0x221F, 0x0007}, {0x221E, 0x002C}, - {0x2218, 0x008B}, {0x221F, 0x0005}, {0x2205, 0xFFF6}, {0x2206, 0x0080}, - {0x2205, 0x8000}, {0x2206, 0xF8E0}, {0x2206, 0xE000}, {0x2206, 0xE1E0}, - {0x2206, 0x01AC}, {0x2206, 0x2408}, {0x2206, 0xE08B}, {0x2206, 0x84F7}, - {0x2206, 0x20E4}, {0x2206, 0x8B84}, {0x2206, 0xFC05}, {0x2206, 0xF8FA}, - {0x2206, 0xEF69}, {0x2206, 0xE08B}, {0x2206, 0x86AC}, {0x2206, 0x201A}, - {0x2206, 0xBF80}, {0x2206, 0x59D0}, {0x2206, 0x2402}, {0x2206, 0x803D}, - {0x2206, 0xE0E0}, {0x2206, 0xE4E1}, {0x2206, 0xE0E5}, {0x2206, 0x5806}, - {0x2206, 0x68C0}, {0x2206, 0xD1D2}, {0x2206, 0xE4E0}, {0x2206, 0xE4E5}, - {0x2206, 0xE0E5}, {0x2206, 0xEF96}, {0x2206, 0xFEFC}, {0x2206, 0x05FB}, - {0x2206, 0x0BFB}, {0x2206, 0x58FF}, {0x2206, 0x9E11}, {0x2206, 0x06F0}, - {0x2206, 0x0C81}, {0x2206, 0x8AE0}, {0x2206, 0x0019}, {0x2206, 0x1B89}, - {0x2206, 0xCFEB}, {0x2206, 0x19EB}, {0x2206, 0x19B0}, {0x2206, 0xEFFF}, - {0x2206, 0x0BFF}, {0x2206, 0x0425}, {0x2206, 0x0807}, {0x2206, 0x2640}, - {0x2206, 0x7227}, {0x2206, 0x267E}, {0x2206, 0x2804}, {0x2206, 0xB729}, - {0x2206, 0x2576}, {0x2206, 0x2A68}, {0x2206, 0xE52B}, {0x2206, 0xAD00}, - {0x2206, 0x2CDB}, {0x2206, 0xF02D}, {0x2206, 0x67BB}, {0x2206, 0x2E7B}, - {0x2206, 0x0F2F}, {0x2206, 0x7365}, {0x2206, 0x31AC}, {0x2206, 0xCC32}, - {0x2206, 0x2300}, {0x2206, 0x332D}, {0x2206, 0x1734}, {0x2206, 0x7F52}, - {0x2206, 0x3510}, {0x2206, 0x0036}, {0x2206, 0x0600}, {0x2206, 0x370C}, - {0x2206, 0xC038}, {0x2206, 0x7FCE}, {0x2206, 0x3CE5}, {0x2206, 0xF73D}, - {0x2206, 0x3DA4}, {0x2206, 0x6530}, {0x2206, 0x3E67}, {0x2206, 0x0053}, - {0x2206, 0x69D2}, {0x2206, 0x0F6A}, {0x2206, 0x012C}, {0x2206, 0x6C2B}, - {0x2206, 0x136E}, {0x2206, 0xE100}, {0x2206, 0x6F12}, {0x2206, 0xF771}, - {0x2206, 0x006B}, {0x2206, 0x7306}, {0x2206, 0xEB74}, {0x2206, 0x94C7}, - {0x2206, 0x7698}, {0x2206, 0x0A77}, {0x2206, 0x5000}, {0x2206, 0x788A}, - {0x2206, 0x1579}, {0x2206, 0x7F6F}, {0x2206, 0x7A06}, {0x2206, 0xA600}, - {0x2205, 0x8B90}, {0x2206, 0x8000}, {0x2205, 0x8B92}, {0x2206, 0x8000}, - {0x2205, 0x8B94}, {0x2206, 0x8014}, {0x2208, 0xFFFA}, {0x2202, 0x3C65}, - {0x2205, 0xFFF6}, {0x2206, 0x00F7}, {0x221F, 0x0000}, {0x221F, 0x0007}, - {0x221E, 0x0042}, {0x2218, 0x0000}, {0x221E, 0x002D}, {0x2218, 0xF010}, - {0x221E, 0x0020}, {0x2215, 0x0000}, {0x221E, 0x0023}, {0x2216, 0x8000}, - {0x221F, 0x0000}, {0x133F, 0x0010}, {0x133E, 0x0FFE}, {0x1362, 0x0115}, - {0x1363, 0x0002}, {0x1363, 0x0000}, {0x1306, 0x000C}, {0x1307, 0x000C}, - {0x1303, 0x0067}, {0x1304, 0x4444}, {0x1203, 0xFF00}, {0x1200, 0x7FC4}, - {0x0900, 0x0000}, {0x0901, 0x0000}, {0x0902, 0x0000}, {0x0903, 0x0000}, - {0x0865, 0x3210}, {0x087B, 0x0000}, {0x087C, 0xFF00}, {0x087D, 0x0000}, - {0x087E, 0x0000}, {0x0801, 0x0100}, {0x0802, 0x0100}, {0x0A20, 0x2040}, - {0x0A21, 0x2040}, {0x0A22, 0x2040}, {0x0A23, 0x2040}, {0x0A24, 0x2040}, - {0x0A25, 0x2040}, {0x0A26, 0x2040}, {0x0A27, 0x2040}, {0x0A28, 0x2040}, - {0x0A29, 0x2040}, {0x133F, 0x0030}, {0x133E, 0x000E}, {0x221F, 0x0000}, - {0x2200, 0x1340}, {0x221F, 0x0000}, {0x133F, 0x0010}, {0x133E, 0x0FFE}, - {0x1B03, 0x0876}, -}; - -static const struct rtl8367_initval rtl8367_initvals_2_0[] = { - {0x1b24, 0x0000}, {0x1b25, 0x0000}, {0x1b26, 0x0000}, {0x1b27, 0x0000}, - {0x133f, 0x0030}, {0x133e, 0x000e}, {0x221f, 0x0007}, {0x221e, 0x0048}, - {0x2219, 0x4012}, {0x221f, 0x0003}, {0x2201, 0x3554}, {0x2202, 0x63e8}, - {0x2203, 0x99c2}, {0x2204, 0x0113}, {0x2205, 0x303e}, {0x220d, 0x0207}, - {0x220e, 0xe100}, {0x221f, 0x0007}, {0x221e, 0x0040}, {0x2218, 0x0000}, - {0x221f, 0x0007}, {0x221e, 0x002c}, {0x2218, 0x008b}, {0x221f, 0x0005}, - {0x2205, 0xfff6}, {0x2206, 0x0080}, {0x221f, 0x0005}, {0x2205, 0x8000}, - {0x2206, 0x0280}, {0x2206, 0x2bf7}, {0x2206, 0x00e0}, {0x2206, 0xfff7}, - {0x2206, 0xa080}, {0x2206, 0x02ae}, {0x2206, 0xf602}, {0x2206, 0x804e}, - {0x2206, 0x0201}, {0x2206, 0x5002}, {0x2206, 0x0163}, {0x2206, 0x0201}, - {0x2206, 0x79e0}, {0x2206, 0x8b8c}, {0x2206, 0xe18b}, {0x2206, 0x8d1e}, - {0x2206, 0x01e1}, {0x2206, 0x8b8e}, {0x2206, 0x1e01}, {0x2206, 0xa000}, - {0x2206, 0xe4ae}, {0x2206, 0xd8bf}, {0x2206, 0x8b88}, {0x2206, 0xec00}, - {0x2206, 0x19a9}, {0x2206, 0x8b90}, {0x2206, 0xf9ee}, {0x2206, 0xfff6}, - {0x2206, 0x00ee}, {0x2206, 0xfff7}, {0x2206, 0xfce0}, {0x2206, 0xe140}, - {0x2206, 0xe1e1}, {0x2206, 0x41f7}, {0x2206, 0x2ff6}, {0x2206, 0x28e4}, - {0x2206, 0xe140}, {0x2206, 0xe5e1}, {0x2206, 0x4104}, {0x2206, 0xf8fa}, - {0x2206, 0xef69}, {0x2206, 0xe08b}, {0x2206, 0x86ac}, {0x2206, 0x201a}, - {0x2206, 0xbf80}, {0x2206, 0x77d0}, {0x2206, 0x6c02}, {0x2206, 0x2978}, - {0x2206, 0xe0e0}, {0x2206, 0xe4e1}, {0x2206, 0xe0e5}, {0x2206, 0x5806}, - {0x2206, 0x68c0}, {0x2206, 0xd1d2}, {0x2206, 0xe4e0}, {0x2206, 0xe4e5}, - {0x2206, 0xe0e5}, {0x2206, 0xef96}, {0x2206, 0xfefc}, {0x2206, 0x0425}, - {0x2206, 0x0807}, {0x2206, 0x2640}, {0x2206, 0x7227}, {0x2206, 0x267e}, - {0x2206, 0x2804}, {0x2206, 0xb729}, {0x2206, 0x2576}, {0x2206, 0x2a68}, - {0x2206, 0xe52b}, {0x2206, 0xad00}, {0x2206, 0x2cdb}, {0x2206, 0xf02d}, - {0x2206, 0x67bb}, {0x2206, 0x2e7b}, {0x2206, 0x0f2f}, {0x2206, 0x7365}, - {0x2206, 0x31ac}, {0x2206, 0xcc32}, {0x2206, 0x2300}, {0x2206, 0x332d}, - {0x2206, 0x1734}, {0x2206, 0x7f52}, {0x2206, 0x3510}, {0x2206, 0x0036}, - {0x2206, 0x0600}, {0x2206, 0x370c}, {0x2206, 0xc038}, {0x2206, 0x7fce}, - {0x2206, 0x3ce5}, {0x2206, 0xf73d}, {0x2206, 0x3da4}, {0x2206, 0x6530}, - {0x2206, 0x3e67}, {0x2206, 0x0053}, {0x2206, 0x69d2}, {0x2206, 0x0f6a}, - {0x2206, 0x012c}, {0x2206, 0x6c2b}, {0x2206, 0x136e}, {0x2206, 0xe100}, - {0x2206, 0x6f12}, {0x2206, 0xf771}, {0x2206, 0x006b}, {0x2206, 0x7306}, - {0x2206, 0xeb74}, {0x2206, 0x94c7}, {0x2206, 0x7698}, {0x2206, 0x0a77}, - {0x2206, 0x5000}, {0x2206, 0x788a}, {0x2206, 0x1579}, {0x2206, 0x7f6f}, - {0x2206, 0x7a06}, {0x2206, 0xa600}, {0x2201, 0x0701}, {0x2200, 0x0405}, - {0x221f, 0x0000}, {0x2200, 0x1340}, {0x221f, 0x0000}, {0x133f, 0x0010}, - {0x133e, 0x0ffe}, {0x1203, 0xff00}, {0x1200, 0x7fc4}, {0x121d, 0x7D16}, - {0x121e, 0x03e8}, {0x121f, 0x024e}, {0x1220, 0x0230}, {0x1221, 0x0244}, - {0x1222, 0x0226}, {0x1223, 0x024e}, {0x1224, 0x0230}, {0x1225, 0x0244}, - {0x1226, 0x0226}, {0x1227, 0x00c0}, {0x1228, 0x00b4}, {0x122f, 0x00c0}, - {0x1230, 0x00b4}, {0x0208, 0x03e8}, {0x0209, 0x03e8}, {0x020a, 0x03e8}, - {0x020b, 0x03e8}, {0x020c, 0x03e8}, {0x020d, 0x03e8}, {0x020e, 0x03e8}, - {0x020f, 0x03e8}, {0x0210, 0x03e8}, {0x0211, 0x03e8}, {0x0212, 0x03e8}, - {0x0213, 0x03e8}, {0x0214, 0x03e8}, {0x0215, 0x03e8}, {0x0216, 0x03e8}, - {0x0217, 0x03e8}, {0x0900, 0x0000}, {0x0901, 0x0000}, {0x0902, 0x0000}, - {0x0903, 0x0000}, {0x0865, 0x3210}, {0x087b, 0x0000}, {0x087c, 0xff00}, - {0x087d, 0x0000}, {0x087e, 0x0000}, {0x0801, 0x0100}, {0x0802, 0x0100}, - {0x0A20, 0x2040}, {0x0A21, 0x2040}, {0x0A22, 0x2040}, {0x0A23, 0x2040}, - {0x0A24, 0x2040}, {0x0A28, 0x2040}, {0x0A29, 0x2040}, {0x20A0, 0x1940}, - {0x20C0, 0x1940}, {0x20E0, 0x1940}, {0x130c, 0x0050}, -}; - -static const struct rtl8367_initval rtl8367_initvals_2_1[] = { - {0x1b24, 0x0000}, {0x1b25, 0x0000}, {0x1b26, 0x0000}, {0x1b27, 0x0000}, - {0x133f, 0x0030}, {0x133e, 0x000e}, {0x221f, 0x0007}, {0x221e, 0x0048}, - {0x2219, 0x4012}, {0x221f, 0x0003}, {0x2201, 0x3554}, {0x2202, 0x63e8}, - {0x2203, 0x99c2}, {0x2204, 0x0113}, {0x2205, 0x303e}, {0x220d, 0x0207}, - {0x220e, 0xe100}, {0x221f, 0x0007}, {0x221e, 0x0040}, {0x2218, 0x0000}, - {0x221f, 0x0007}, {0x221e, 0x002c}, {0x2218, 0x008b}, {0x221f, 0x0005}, - {0x2205, 0xfff6}, {0x2206, 0x0080}, {0x221f, 0x0005}, {0x2205, 0x8000}, - {0x2206, 0x0280}, {0x2206, 0x2bf7}, {0x2206, 0x00e0}, {0x2206, 0xfff7}, - {0x2206, 0xa080}, {0x2206, 0x02ae}, {0x2206, 0xf602}, {0x2206, 0x804e}, - {0x2206, 0x0201}, {0x2206, 0x5002}, {0x2206, 0x0163}, {0x2206, 0x0201}, - {0x2206, 0x79e0}, {0x2206, 0x8b8c}, {0x2206, 0xe18b}, {0x2206, 0x8d1e}, - {0x2206, 0x01e1}, {0x2206, 0x8b8e}, {0x2206, 0x1e01}, {0x2206, 0xa000}, - {0x2206, 0xe4ae}, {0x2206, 0xd8bf}, {0x2206, 0x8b88}, {0x2206, 0xec00}, - {0x2206, 0x19a9}, {0x2206, 0x8b90}, {0x2206, 0xf9ee}, {0x2206, 0xfff6}, - {0x2206, 0x00ee}, {0x2206, 0xfff7}, {0x2206, 0xfce0}, {0x2206, 0xe140}, - {0x2206, 0xe1e1}, {0x2206, 0x41f7}, {0x2206, 0x2ff6}, {0x2206, 0x28e4}, - {0x2206, 0xe140}, {0x2206, 0xe5e1}, {0x2206, 0x4104}, {0x2206, 0xf8fa}, - {0x2206, 0xef69}, {0x2206, 0xe08b}, {0x2206, 0x86ac}, {0x2206, 0x201a}, - {0x2206, 0xbf80}, {0x2206, 0x77d0}, {0x2206, 0x6c02}, {0x2206, 0x2978}, - {0x2206, 0xe0e0}, {0x2206, 0xe4e1}, {0x2206, 0xe0e5}, {0x2206, 0x5806}, - {0x2206, 0x68c0}, {0x2206, 0xd1d2}, {0x2206, 0xe4e0}, {0x2206, 0xe4e5}, - {0x2206, 0xe0e5}, {0x2206, 0xef96}, {0x2206, 0xfefc}, {0x2206, 0x0425}, - {0x2206, 0x0807}, {0x2206, 0x2640}, {0x2206, 0x7227}, {0x2206, 0x267e}, - {0x2206, 0x2804}, {0x2206, 0xb729}, {0x2206, 0x2576}, {0x2206, 0x2a68}, - {0x2206, 0xe52b}, {0x2206, 0xad00}, {0x2206, 0x2cdb}, {0x2206, 0xf02d}, - {0x2206, 0x67bb}, {0x2206, 0x2e7b}, {0x2206, 0x0f2f}, {0x2206, 0x7365}, - {0x2206, 0x31ac}, {0x2206, 0xcc32}, {0x2206, 0x2300}, {0x2206, 0x332d}, - {0x2206, 0x1734}, {0x2206, 0x7f52}, {0x2206, 0x3510}, {0x2206, 0x0036}, - {0x2206, 0x0600}, {0x2206, 0x370c}, {0x2206, 0xc038}, {0x2206, 0x7fce}, - {0x2206, 0x3ce5}, {0x2206, 0xf73d}, {0x2206, 0x3da4}, {0x2206, 0x6530}, - {0x2206, 0x3e67}, {0x2206, 0x0053}, {0x2206, 0x69d2}, {0x2206, 0x0f6a}, - {0x2206, 0x012c}, {0x2206, 0x6c2b}, {0x2206, 0x136e}, {0x2206, 0xe100}, - {0x2206, 0x6f12}, {0x2206, 0xf771}, {0x2206, 0x006b}, {0x2206, 0x7306}, - {0x2206, 0xeb74}, {0x2206, 0x94c7}, {0x2206, 0x7698}, {0x2206, 0x0a77}, - {0x2206, 0x5000}, {0x2206, 0x788a}, {0x2206, 0x1579}, {0x2206, 0x7f6f}, - {0x2206, 0x7a06}, {0x2206, 0xa600}, {0x2201, 0x0701}, {0x2200, 0x0405}, - {0x221f, 0x0000}, {0x2200, 0x1340}, {0x221f, 0x0000}, {0x133f, 0x0010}, - {0x133e, 0x0ffe}, {0x1203, 0xff00}, {0x1200, 0x7fc4}, {0x0900, 0x0000}, - {0x0901, 0x0000}, {0x0902, 0x0000}, {0x0903, 0x0000}, {0x0865, 0x3210}, - {0x087b, 0x0000}, {0x087c, 0xff00}, {0x087d, 0x0000}, {0x087e, 0x0000}, - {0x0801, 0x0100}, {0x0802, 0x0100}, {0x0A20, 0x2040}, {0x0A21, 0x2040}, - {0x0A22, 0x2040}, {0x0A23, 0x2040}, {0x0A24, 0x2040}, {0x0A25, 0x2040}, - {0x0A26, 0x2040}, {0x0A27, 0x2040}, {0x0A28, 0x2040}, {0x0A29, 0x2040}, - {0x130c, 0x0050}, -}; - -static int rtl8367_write_initvals(struct rtl8366_smi *smi, - const struct rtl8367_initval *initvals, - int count) -{ - int err; - int i; - - for (i = 0; i < count; i++) - REG_WR(smi, initvals[i].reg, initvals[i].val); - - return 0; -} - -static int rtl8367_read_phy_reg(struct rtl8366_smi *smi, - u32 phy_addr, u32 phy_reg, u32 *val) -{ - int timeout; - u32 data; - int err; - - if (phy_addr > RTL8367_PHY_ADDR_MAX) - return -EINVAL; - - if (phy_reg > RTL8367_PHY_REG_MAX) - return -EINVAL; - - REG_RD(smi, RTL8367_IA_STATUS_REG, &data); - if (data & RTL8367_IA_STATUS_PHY_BUSY) - return -ETIMEDOUT; - - /* prepare address */ - REG_WR(smi, RTL8367_IA_ADDRESS_REG, - RTL8367_INTERNAL_PHY_REG(phy_addr, phy_reg)); - - /* send read command */ - REG_WR(smi, RTL8367_IA_CTRL_REG, - RTL8367_IA_CTRL_CMD_MASK | RTL8367_IA_CTRL_RW_READ); - - timeout = 5; - do { - REG_RD(smi, RTL8367_IA_STATUS_REG, &data); - if ((data & RTL8367_IA_STATUS_PHY_BUSY) == 0) - break; - - if (timeout--) { - dev_err(smi->parent, "phy read timed out\n"); - return -ETIMEDOUT; - } - - udelay(1); - } while (1); - - /* read data */ - REG_RD(smi, RTL8367_IA_READ_DATA_REG, val); - - dev_dbg(smi->parent, "phy_read: addr:%02x, reg:%02x, val:%04x\n", - phy_addr, phy_reg, *val); - return 0; -} - -static int rtl8367_write_phy_reg(struct rtl8366_smi *smi, - u32 phy_addr, u32 phy_reg, u32 val) -{ - int timeout; - u32 data; - int err; - - dev_dbg(smi->parent, "phy_write: addr:%02x, reg:%02x, val:%04x\n", - phy_addr, phy_reg, val); - - if (phy_addr > RTL8367_PHY_ADDR_MAX) - return -EINVAL; - - if (phy_reg > RTL8367_PHY_REG_MAX) - return -EINVAL; - - REG_RD(smi, RTL8367_IA_STATUS_REG, &data); - if (data & RTL8367_IA_STATUS_PHY_BUSY) - return -ETIMEDOUT; - - /* preapre data */ - REG_WR(smi, RTL8367_IA_WRITE_DATA_REG, val); - - /* prepare address */ - REG_WR(smi, RTL8367_IA_ADDRESS_REG, - RTL8367_INTERNAL_PHY_REG(phy_addr, phy_reg)); - - /* send write command */ - REG_WR(smi, RTL8367_IA_CTRL_REG, - RTL8367_IA_CTRL_CMD_MASK | RTL8367_IA_CTRL_RW_WRITE); - - timeout = 5; - do { - REG_RD(smi, RTL8367_IA_STATUS_REG, &data); - if ((data & RTL8367_IA_STATUS_PHY_BUSY) == 0) - break; - - if (timeout--) { - dev_err(smi->parent, "phy write timed out\n"); - return -ETIMEDOUT; - } - - udelay(1); - } while (1); - - return 0; -} - -static int rtl8367_init_regs0(struct rtl8366_smi *smi, unsigned mode) -{ - const struct rtl8367_initval *initvals; - int count; - int err; - - switch (mode) { - case 0: - initvals = rtl8367_initvals_0_0; - count = ARRAY_SIZE(rtl8367_initvals_0_0); - break; - - case 1: - case 2: - initvals = rtl8367_initvals_0_1; - count = ARRAY_SIZE(rtl8367_initvals_0_1); - break; - - default: - dev_err(smi->parent, "%s: unknow mode %u\n", __func__, mode); - return -ENODEV; - } - - err = rtl8367_write_initvals(smi, initvals, count); - if (err) - return err; - - /* TODO: complete this */ - - return 0; -} - -static int rtl8367_init_regs1(struct rtl8366_smi *smi, unsigned mode) -{ - const struct rtl8367_initval *initvals; - int count; - - switch (mode) { - case 0: - initvals = rtl8367_initvals_1_0; - count = ARRAY_SIZE(rtl8367_initvals_1_0); - break; - - case 1: - case 2: - initvals = rtl8367_initvals_1_1; - count = ARRAY_SIZE(rtl8367_initvals_1_1); - break; - - default: - dev_err(smi->parent, "%s: unknow mode %u\n", __func__, mode); - return -ENODEV; - } - - return rtl8367_write_initvals(smi, initvals, count); -} - -static int rtl8367_init_regs2(struct rtl8366_smi *smi, unsigned mode) -{ - const struct rtl8367_initval *initvals; - int count; - - switch (mode) { - case 0: - initvals = rtl8367_initvals_2_0; - count = ARRAY_SIZE(rtl8367_initvals_2_0); - break; - - case 1: - case 2: - initvals = rtl8367_initvals_2_1; - count = ARRAY_SIZE(rtl8367_initvals_2_1); - break; - - default: - dev_err(smi->parent, "%s: unknow mode %u\n", __func__, mode); - return -ENODEV; - } - - return rtl8367_write_initvals(smi, initvals, count); -} - -static int rtl8367_init_regs(struct rtl8366_smi *smi) -{ - u32 data; - u32 rlvid; - u32 mode; - int err; - - REG_WR(smi, RTL8367_RTL_MAGIC_ID_REG, RTL8367_RTL_MAGIC_ID_VAL); - - REG_RD(smi, RTL8367_CHIP_VER_REG, &data); - rlvid = (data >> RTL8367_CHIP_VER_RLVID_SHIFT) & - RTL8367_CHIP_VER_RLVID_MASK; - - REG_RD(smi, RTL8367_CHIP_MODE_REG, &data); - mode = data & RTL8367_CHIP_MODE_MASK; - - switch (rlvid) { - case 0: - err = rtl8367_init_regs0(smi, mode); - break; - - case 1: - err = rtl8367_write_phy_reg(smi, 0, 31, 5); - if (err) - break; - - err = rtl8367_write_phy_reg(smi, 0, 5, 0x3ffe); - if (err) - break; - - err = rtl8367_read_phy_reg(smi, 0, 6, &data); - if (err) - break; - - if (data == 0x94eb) { - err = rtl8367_init_regs1(smi, mode); - } else if (data == 0x2104) { - err = rtl8367_init_regs2(smi, mode); - } else { - dev_err(smi->parent, "unknow phy data %04x\n", data); - return -ENODEV; - } - - break; - - default: - dev_err(smi->parent, "unknow rlvid %u\n", rlvid); - err = -ENODEV; - break; - } - - return err; -} - -static int rtl8367_reset_chip(struct rtl8366_smi *smi) -{ - int timeout = 10; - int err; - u32 data; - - REG_WR(smi, RTL8367_CHIP_RESET_REG, RTL8367_CHIP_RESET_HW); - msleep(RTL8367_RESET_DELAY); - - do { - REG_RD(smi, RTL8367_CHIP_RESET_REG, &data); - if (!(data & RTL8367_CHIP_RESET_HW)) - break; - - msleep(1); - } while (--timeout); - - if (!timeout) { - dev_err(smi->parent, "chip reset timed out\n"); - return -ETIMEDOUT; - } - - return 0; -} - -static int rtl8367_extif_set_mode(struct rtl8366_smi *smi, int id, - enum rtl8367_extif_mode mode) -{ - int err; - - /* set port mode */ - switch (mode) { - case RTL8367_EXTIF_MODE_RGMII: - case RTL8367_EXTIF_MODE_RGMII_33V: - REG_WR(smi, RTL8367_CHIP_DEBUG0_REG, 0x0367); - REG_WR(smi, RTL8367_CHIP_DEBUG1_REG, 0x7777); - break; - - case RTL8367_EXTIF_MODE_TMII_MAC: - case RTL8367_EXTIF_MODE_TMII_PHY: - REG_RMW(smi, RTL8367_BYPASS_LINE_RATE_REG, - BIT((id + 1) % 2), BIT((id + 1) % 2)); - break; - - case RTL8367_EXTIF_MODE_GMII: - REG_RMW(smi, RTL8367_CHIP_DEBUG0_REG, - RTL8367_CHIP_DEBUG0_DUMMY0(id), - RTL8367_CHIP_DEBUG0_DUMMY0(id)); - REG_RMW(smi, RTL8367_EXT_RGMXF_REG(id), BIT(6), BIT(6)); - break; - - case RTL8367_EXTIF_MODE_MII_MAC: - case RTL8367_EXTIF_MODE_MII_PHY: - case RTL8367_EXTIF_MODE_DISABLED: - REG_RMW(smi, RTL8367_BYPASS_LINE_RATE_REG, - BIT((id + 1) % 2), 0); - REG_RMW(smi, RTL8367_EXT_RGMXF_REG(id), BIT(6), 0); - break; - - default: - dev_err(smi->parent, - "invalid mode for external interface %d\n", id); - return -EINVAL; - } - - REG_RMW(smi, RTL8367_DIS_REG, - RTL8367_DIS_RGMII_MASK << RTL8367_DIS_RGMII_SHIFT(id), - mode << RTL8367_DIS_RGMII_SHIFT(id)); - - return 0; -} - -static int rtl8367_extif_set_force(struct rtl8366_smi *smi, int id, - struct rtl8367_port_ability *pa) -{ - u32 mask; - u32 val; - int err; - - mask = (RTL8367_DI_FORCE_MODE | - RTL8367_DI_FORCE_NWAY | - RTL8367_DI_FORCE_TXPAUSE | - RTL8367_DI_FORCE_RXPAUSE | - RTL8367_DI_FORCE_LINK | - RTL8367_DI_FORCE_DUPLEX | - RTL8367_DI_FORCE_SPEED_MASK); - - val = pa->speed; - val |= pa->force_mode ? RTL8367_DI_FORCE_MODE : 0; - val |= pa->nway ? RTL8367_DI_FORCE_NWAY : 0; - val |= pa->txpause ? RTL8367_DI_FORCE_TXPAUSE : 0; - val |= pa->rxpause ? RTL8367_DI_FORCE_RXPAUSE : 0; - val |= pa->link ? RTL8367_DI_FORCE_LINK : 0; - val |= pa->duplex ? RTL8367_DI_FORCE_DUPLEX : 0; - - REG_RMW(smi, RTL8367_DI_FORCE_REG(id), mask, val); - - return 0; -} - -static int rtl8367_extif_set_rgmii_delay(struct rtl8366_smi *smi, int id, - unsigned txdelay, unsigned rxdelay) -{ - u32 mask; - u32 val; - int err; - - mask = (RTL8367_EXT_RGMXF_RXDELAY_MASK | - (RTL8367_EXT_RGMXF_TXDELAY_MASK << - RTL8367_EXT_RGMXF_TXDELAY_SHIFT)); - - val = rxdelay; - val |= txdelay << RTL8367_EXT_RGMXF_TXDELAY_SHIFT; - - REG_RMW(smi, RTL8367_EXT_RGMXF_REG(id), mask, val); - - return 0; -} - -static int rtl8367_extif_init(struct rtl8366_smi *smi, int id, - struct rtl8367_extif_config *cfg) -{ - enum rtl8367_extif_mode mode; - int err; - - mode = (cfg) ? cfg->mode : RTL8367_EXTIF_MODE_DISABLED; - - err = rtl8367_extif_set_mode(smi, id, mode); - if (err) - return err; - - if (mode != RTL8367_EXTIF_MODE_DISABLED) { - err = rtl8367_extif_set_force(smi, id, &cfg->ability); - if (err) - return err; - - err = rtl8367_extif_set_rgmii_delay(smi, id, cfg->txdelay, - cfg->rxdelay); - if (err) - return err; - } - - return 0; -} - -static int rtl8367_led_group_set_ports(struct rtl8366_smi *smi, - unsigned int group, u16 port_mask) -{ - u32 reg; - u32 s; - int err; - - port_mask &= RTL8367_PARA_LED_IO_EN_PMASK; - s = (group % 2) * 8; - reg = RTL8367_PARA_LED_IO_EN1_REG + (group / 2); - - REG_RMW(smi, reg, (RTL8367_PARA_LED_IO_EN_PMASK << s), port_mask << s); - - return 0; -} - -static int rtl8367_led_group_set_mode(struct rtl8366_smi *smi, - unsigned int mode) -{ - u16 mask; - u16 set; - int err; - - mode &= RTL8367_LED_CONFIG_DATA_M; - - mask = (RTL8367_LED_CONFIG_DATA_M << RTL8367_LED_CONFIG_DATA_S) | - RTL8367_LED_CONFIG_SEL; - set = (mode << RTL8367_LED_CONFIG_DATA_S) | RTL8367_LED_CONFIG_SEL; - - REG_RMW(smi, RTL8367_LED_CONFIG_REG, mask, set); - - return 0; -} - -static int rtl8367_led_group_set_config(struct rtl8366_smi *smi, - unsigned int led, unsigned int cfg) -{ - u16 mask; - u16 set; - int err; - - mask = (RTL8367_LED_CONFIG_LED_CFG_M << (led * 4)) | - RTL8367_LED_CONFIG_SEL; - set = (cfg & RTL8367_LED_CONFIG_LED_CFG_M) << (led * 4); - - REG_RMW(smi, RTL8367_LED_CONFIG_REG, mask, set); - return 0; -} - -static int rtl8367_led_op_select_parallel(struct rtl8366_smi *smi) -{ - int err; - - REG_WR(smi, RTL8367_LED_SYS_CONFIG_REG, 0x1472); - return 0; -} - -static int rtl8367_led_blinkrate_set(struct rtl8366_smi *smi, unsigned int rate) -{ - u16 mask; - u16 set; - int err; - - mask = RTL8367_LED_MODE_RATE_M << RTL8367_LED_MODE_RATE_S; - set = (rate & RTL8367_LED_MODE_RATE_M) << RTL8367_LED_MODE_RATE_S; - REG_RMW(smi, RTL8367_LED_MODE_REG, mask, set); - - return 0; -} - -#ifdef CONFIG_OF -static int rtl8367_extif_init_of(struct rtl8366_smi *smi, - const char *name) -{ - struct rtl8367_extif_config *cfg; - const __be32 *prop; - int size; - int err; - unsigned cpu_port; - unsigned id = UINT_MAX; - - prop = of_get_property(smi->parent->of_node, name, &size); - if (!prop || (size != (10 * sizeof(*prop)))) { - dev_err(smi->parent, "%s property is not defined or invalid\n", name); - err = -EINVAL; - goto err_init; - } - - cpu_port = be32_to_cpup(prop++); - switch (cpu_port) { - case RTL8367_CPU_PORT_NUM - 1: - case RTL8367_CPU_PORT_NUM: - id = RTL8367_CPU_PORT_NUM - cpu_port; - if (smi->cpu_port == UINT_MAX) { - dev_info(smi->parent, "cpu_port:%u, assigned to extif%u\n", cpu_port, id); - smi->cpu_port = cpu_port; - } - break; - default: - dev_err(smi->parent, "wrong cpu_port %u in %s property\n", cpu_port, name); - err = -EINVAL; - goto err_init; - } - - cfg = kzalloc(sizeof(struct rtl8367_extif_config), GFP_KERNEL); - if (!cfg) - return -ENOMEM; - - cfg->txdelay = be32_to_cpup(prop++); - cfg->rxdelay = be32_to_cpup(prop++); - cfg->mode = be32_to_cpup(prop++); - cfg->ability.force_mode = be32_to_cpup(prop++); - cfg->ability.txpause = be32_to_cpup(prop++); - cfg->ability.rxpause = be32_to_cpup(prop++); - cfg->ability.link = be32_to_cpup(prop++); - cfg->ability.duplex = be32_to_cpup(prop++); - cfg->ability.speed = be32_to_cpup(prop++); - - err = rtl8367_extif_init(smi, id, cfg); - kfree(cfg); - -err_init: - if (id != 0) rtl8367_extif_init(smi, 0, NULL); - if (id != 1) rtl8367_extif_init(smi, 1, NULL); - - return err; -} -#else -static int rtl8367_extif_init_of(struct rtl8366_smi *smi, - const char *name) -{ - return -EINVAL; -} -#endif - -static int rtl8367_setup(struct rtl8366_smi *smi) -{ - struct rtl8367_platform_data *pdata; - int err; - int i; - - pdata = smi->parent->platform_data; - - err = rtl8367_init_regs(smi); - if (err) - return err; - - /* initialize external interfaces */ - if (smi->parent->of_node) { - err = rtl8367_extif_init_of(smi, "realtek,extif"); - if (err) - return err; - } else { - err = rtl8367_extif_init(smi, 0, pdata->extif0_cfg); - if (err) - return err; - - err = rtl8367_extif_init(smi, 1, pdata->extif1_cfg); - if (err) - return err; - } - - /* set maximum packet length to 1536 bytes */ - REG_RMW(smi, RTL8367_SWC0_REG, RTL8367_SWC0_MAX_LENGTH_MASK, - RTL8367_SWC0_MAX_LENGTH_1536); - - /* - * discard VLAN tagged packets if the port is not a member of - * the VLAN with which the packets is associated. - */ - REG_WR(smi, RTL8367_VLAN_INGRESS_REG, RTL8367_PORTS_ALL); - - /* - * Setup egress tag mode for each port. - */ - for (i = 0; i < RTL8367_NUM_PORTS; i++) - REG_RMW(smi, - RTL8367_PORT_CFG_REG(i), - RTL8367_PORT_CFG_EGRESS_MODE_MASK << - RTL8367_PORT_CFG_EGRESS_MODE_SHIFT, - RTL8367_PORT_CFG_EGRESS_MODE_ORIGINAL << - RTL8367_PORT_CFG_EGRESS_MODE_SHIFT); - - /* setup LEDs */ - err = rtl8367_led_group_set_ports(smi, 0, RTL8367_PORTS_ALL); - if (err) - return err; - - err = rtl8367_led_group_set_mode(smi, 0); - if (err) - return err; - - err = rtl8367_led_op_select_parallel(smi); - if (err) - return err; - - err = rtl8367_led_blinkrate_set(smi, 1); - if (err) - return err; - - err = rtl8367_led_group_set_config(smi, 0, 2); - if (err) - return err; - - return 0; -} - -static int rtl8367_get_mib_counter(struct rtl8366_smi *smi, int counter, - int port, unsigned long long *val) -{ - struct rtl8366_mib_counter *mib; - int offset; - int i; - int err; - u32 addr, data; - u64 mibvalue; - - if (port > RTL8367_NUM_PORTS || counter >= RTL8367_MIB_COUNT) - return -EINVAL; - - mib = &rtl8367_mib_counters[counter]; - addr = RTL8367_MIB_COUNTER_PORT_OFFSET * port + mib->offset; - - /* - * Writing access counter address first - * then ASIC will prepare 64bits counter wait for being retrived - */ - REG_WR(smi, RTL8367_MIB_ADDRESS_REG, addr >> 2); - - /* read MIB control register */ - REG_RD(smi, RTL8367_MIB_CTRL_REG(0), &data); - - if (data & RTL8367_MIB_CTRL_BUSY_MASK) - return -EBUSY; - - if (data & RTL8367_MIB_CTRL_RESET_MASK) - return -EIO; - - if (mib->length == 4) - offset = 3; - else - offset = (mib->offset + 1) % 4; - - mibvalue = 0; - for (i = 0; i < mib->length; i++) { - REG_RD(smi, RTL8367_MIB_COUNTER_REG(offset - i), &data); - mibvalue = (mibvalue << 16) | (data & 0xFFFF); - } - - *val = mibvalue; - return 0; -} - -static int rtl8367_get_vlan_4k(struct rtl8366_smi *smi, u32 vid, - struct rtl8366_vlan_4k *vlan4k) -{ - u32 data[RTL8367_TA_VLAN_DATA_SIZE]; - int err; - int i; - - memset(vlan4k, '\0', sizeof(struct rtl8366_vlan_4k)); - - if (vid >= RTL8367_NUM_VIDS) - return -EINVAL; - - /* write VID */ - REG_WR(smi, RTL8367_TA_ADDR_REG, vid); - - /* write table access control word */ - REG_WR(smi, RTL8367_TA_CTRL_REG, RTL8367_TA_CTRL_CVLAN_READ); - - for (i = 0; i < ARRAY_SIZE(data); i++) - REG_RD(smi, RTL8367_TA_DATA_REG(i), &data[i]); - - vlan4k->vid = vid; - vlan4k->member = (data[0] >> RTL8367_TA_VLAN_MEMBER_SHIFT) & - RTL8367_TA_VLAN_MEMBER_MASK; - vlan4k->fid = (data[1] >> RTL8367_TA_VLAN_FID_SHIFT) & - RTL8367_TA_VLAN_FID_MASK; - vlan4k->untag = (data[2] >> RTL8367_TA_VLAN_UNTAG1_SHIFT) & - RTL8367_TA_VLAN_UNTAG1_MASK; - vlan4k->untag |= ((data[3] >> RTL8367_TA_VLAN_UNTAG2_SHIFT) & - RTL8367_TA_VLAN_UNTAG2_MASK) << 2; - - return 0; -} - -static int rtl8367_set_vlan_4k(struct rtl8366_smi *smi, - const struct rtl8366_vlan_4k *vlan4k) -{ - u32 data[RTL8367_TA_VLAN_DATA_SIZE]; - int err; - int i; - - if (vlan4k->vid >= RTL8367_NUM_VIDS || - vlan4k->member > RTL8367_TA_VLAN_MEMBER_MASK || - vlan4k->untag > RTL8367_UNTAG_MASK || - vlan4k->fid > RTL8367_FIDMAX) - return -EINVAL; - - data[0] = (vlan4k->member & RTL8367_TA_VLAN_MEMBER_MASK) << - RTL8367_TA_VLAN_MEMBER_SHIFT; - data[1] = (vlan4k->fid & RTL8367_TA_VLAN_FID_MASK) << - RTL8367_TA_VLAN_FID_SHIFT; - data[2] = (vlan4k->untag & RTL8367_TA_VLAN_UNTAG1_MASK) << - RTL8367_TA_VLAN_UNTAG1_SHIFT; - data[3] = ((vlan4k->untag >> 2) & RTL8367_TA_VLAN_UNTAG2_MASK) << - RTL8367_TA_VLAN_UNTAG2_SHIFT; - - for (i = 0; i < ARRAY_SIZE(data); i++) - REG_WR(smi, RTL8367_TA_DATA_REG(i), data[i]); - - /* write VID */ - REG_WR(smi, RTL8367_TA_ADDR_REG, - vlan4k->vid & RTL8367_TA_VLAN_VID_MASK); - - /* write table access control word */ - REG_WR(smi, RTL8367_TA_CTRL_REG, RTL8367_TA_CTRL_CVLAN_WRITE); - - return 0; -} - -static int rtl8367_get_vlan_mc(struct rtl8366_smi *smi, u32 index, - struct rtl8366_vlan_mc *vlanmc) -{ - u32 data[RTL8367_VLAN_MC_DATA_SIZE]; - int err; - int i; - - memset(vlanmc, '\0', sizeof(struct rtl8366_vlan_mc)); - - if (index >= RTL8367_NUM_VLANS) - return -EINVAL; - - for (i = 0; i < ARRAY_SIZE(data); i++) - REG_RD(smi, RTL8367_VLAN_MC_BASE(index) + i, &data[i]); - - vlanmc->member = (data[0] >> RTL8367_VLAN_MC_MEMBER_SHIFT) & - RTL8367_VLAN_MC_MEMBER_MASK; - vlanmc->fid = (data[1] >> RTL8367_VLAN_MC_FID_SHIFT) & - RTL8367_VLAN_MC_FID_MASK; - vlanmc->vid = (data[3] >> RTL8367_VLAN_MC_EVID_SHIFT) & - RTL8367_VLAN_MC_EVID_MASK; - - return 0; -} - -static int rtl8367_set_vlan_mc(struct rtl8366_smi *smi, u32 index, - const struct rtl8366_vlan_mc *vlanmc) -{ - u32 data[RTL8367_VLAN_MC_DATA_SIZE]; - int err; - int i; - - if (index >= RTL8367_NUM_VLANS || - vlanmc->vid >= RTL8367_NUM_VIDS || - vlanmc->priority > RTL8367_PRIORITYMAX || - vlanmc->member > RTL8367_VLAN_MC_MEMBER_MASK || - vlanmc->untag > RTL8367_UNTAG_MASK || - vlanmc->fid > RTL8367_FIDMAX) - return -EINVAL; - - data[0] = (vlanmc->member & RTL8367_VLAN_MC_MEMBER_MASK) << - RTL8367_VLAN_MC_MEMBER_SHIFT; - data[1] = (vlanmc->fid & RTL8367_VLAN_MC_FID_MASK) << - RTL8367_VLAN_MC_FID_SHIFT; - data[2] = 0; - data[3] = (vlanmc->vid & RTL8367_VLAN_MC_EVID_MASK) << - RTL8367_VLAN_MC_EVID_SHIFT; - - for (i = 0; i < ARRAY_SIZE(data); i++) - REG_WR(smi, RTL8367_VLAN_MC_BASE(index) + i, data[i]); - - return 0; -} - -static int rtl8367_get_mc_index(struct rtl8366_smi *smi, int port, int *val) -{ - u32 data; - int err; - - if (port >= RTL8367_NUM_PORTS) - return -EINVAL; - - REG_RD(smi, RTL8367_VLAN_PVID_CTRL_REG(port), &data); - - *val = (data >> RTL8367_VLAN_PVID_CTRL_SHIFT(port)) & - RTL8367_VLAN_PVID_CTRL_MASK; - - return 0; -} - -static int rtl8367_set_mc_index(struct rtl8366_smi *smi, int port, int index) -{ - if (port >= RTL8367_NUM_PORTS || index >= RTL8367_NUM_VLANS) - return -EINVAL; - - return rtl8366_smi_rmwr(smi, RTL8367_VLAN_PVID_CTRL_REG(port), - RTL8367_VLAN_PVID_CTRL_MASK << - RTL8367_VLAN_PVID_CTRL_SHIFT(port), - (index & RTL8367_VLAN_PVID_CTRL_MASK) << - RTL8367_VLAN_PVID_CTRL_SHIFT(port)); -} - -static int rtl8367_enable_vlan(struct rtl8366_smi *smi, int enable) -{ - return rtl8366_smi_rmwr(smi, RTL8367_VLAN_CTRL_REG, - RTL8367_VLAN_CTRL_ENABLE, - (enable) ? RTL8367_VLAN_CTRL_ENABLE : 0); -} - -static int rtl8367_enable_vlan4k(struct rtl8366_smi *smi, int enable) -{ - return 0; -} - -static int rtl8367_is_vlan_valid(struct rtl8366_smi *smi, unsigned vlan) -{ - unsigned max = RTL8367_NUM_VLANS; - - if (smi->vlan4k_enabled) - max = RTL8367_NUM_VIDS - 1; - - if (vlan == 0 || vlan >= max) - return 0; - - return 1; -} - -static int rtl8367_enable_port(struct rtl8366_smi *smi, int port, int enable) -{ - int err; - - REG_WR(smi, RTL8367_PORT_ISOLATION_REG(port), - (enable) ? RTL8367_PORTS_ALL : 0); - - return 0; -} - -static int rtl8367_sw_reset_mibs(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val) -{ - struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev); - - return rtl8366_smi_rmwr(smi, RTL8367_MIB_CTRL_REG(0), 0, - RTL8367_MIB_CTRL_GLOBAL_RESET_MASK); -} - -static int rtl8367_sw_get_port_link(struct switch_dev *dev, - int port, - struct switch_port_link *link) -{ - struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev); - u32 data = 0; - u32 speed; - - if (port >= RTL8367_NUM_PORTS) - return -EINVAL; - - rtl8366_smi_read_reg(smi, RTL8367_PORT_STATUS_REG(port), &data); - - link->link = !!(data & RTL8367_PORT_STATUS_LINK); - if (!link->link) - return 0; - - link->duplex = !!(data & RTL8367_PORT_STATUS_DUPLEX); - link->rx_flow = !!(data & RTL8367_PORT_STATUS_RXPAUSE); - link->tx_flow = !!(data & RTL8367_PORT_STATUS_TXPAUSE); - link->aneg = !!(data & RTL8367_PORT_STATUS_NWAY); - - speed = (data & RTL8367_PORT_STATUS_SPEED_MASK); - switch (speed) { - case 0: - link->speed = SWITCH_PORT_SPEED_10; - break; - case 1: - link->speed = SWITCH_PORT_SPEED_100; - break; - case 2: - link->speed = SWITCH_PORT_SPEED_1000; - break; - default: - link->speed = SWITCH_PORT_SPEED_UNKNOWN; - break; - } - - return 0; -} - -static int rtl8367_sw_get_max_length(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val) -{ - struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev); - u32 data; - - rtl8366_smi_read_reg(smi, RTL8367_SWC0_REG, &data); - val->value.i = (data & RTL8367_SWC0_MAX_LENGTH_MASK) >> - RTL8367_SWC0_MAX_LENGTH_SHIFT; - - return 0; -} - -static int rtl8367_sw_set_max_length(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val) -{ - struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev); - u32 max_len; - - switch (val->value.i) { - case 0: - max_len = RTL8367_SWC0_MAX_LENGTH_1522; - break; - case 1: - max_len = RTL8367_SWC0_MAX_LENGTH_1536; - break; - case 2: - max_len = RTL8367_SWC0_MAX_LENGTH_1552; - break; - case 3: - max_len = RTL8367_SWC0_MAX_LENGTH_16000; - break; - default: - return -EINVAL; - } - - return rtl8366_smi_rmwr(smi, RTL8367_SWC0_REG, - RTL8367_SWC0_MAX_LENGTH_MASK, max_len); -} - - -static int rtl8367_sw_reset_port_mibs(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val) -{ - struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev); - int port; - - port = val->port_vlan; - if (port >= RTL8367_NUM_PORTS) - return -EINVAL; - - return rtl8366_smi_rmwr(smi, RTL8367_MIB_CTRL_REG(port / 8), 0, - RTL8367_MIB_CTRL_PORT_RESET_MASK(port % 8)); -} - -static int rtl8367_sw_get_port_stats(struct switch_dev *dev, int port, - struct switch_port_stats *stats) -{ - return (rtl8366_sw_get_port_stats(dev, port, stats, - RTL8367_MIB_TXB_ID, RTL8367_MIB_RXB_ID)); -} - -static struct switch_attr rtl8367_globals[] = { - { - .type = SWITCH_TYPE_INT, - .name = "enable_vlan", - .description = "Enable VLAN mode", - .set = rtl8366_sw_set_vlan_enable, - .get = rtl8366_sw_get_vlan_enable, - .max = 1, - .ofs = 1 - }, { - .type = SWITCH_TYPE_INT, - .name = "enable_vlan4k", - .description = "Enable VLAN 4K mode", - .set = rtl8366_sw_set_vlan_enable, - .get = rtl8366_sw_get_vlan_enable, - .max = 1, - .ofs = 2 - }, { - .type = SWITCH_TYPE_NOVAL, - .name = "reset_mibs", - .description = "Reset all MIB counters", - .set = rtl8367_sw_reset_mibs, - }, { - .type = SWITCH_TYPE_INT, - .name = "max_length", - .description = "Get/Set the maximum length of valid packets" - "(0:1522, 1:1536, 2:1552, 3:16000)", - .set = rtl8367_sw_set_max_length, - .get = rtl8367_sw_get_max_length, - .max = 3, - } -}; - -static struct switch_attr rtl8367_port[] = { - { - .type = SWITCH_TYPE_NOVAL, - .name = "reset_mib", - .description = "Reset single port MIB counters", - .set = rtl8367_sw_reset_port_mibs, - }, { - .type = SWITCH_TYPE_STRING, - .name = "mib", - .description = "Get MIB counters for port", - .max = 33, - .set = NULL, - .get = rtl8366_sw_get_port_mib, - }, -}; - -static struct switch_attr rtl8367_vlan[] = { - { - .type = SWITCH_TYPE_STRING, - .name = "info", - .description = "Get vlan information", - .max = 1, - .set = NULL, - .get = rtl8366_sw_get_vlan_info, - }, { - .type = SWITCH_TYPE_INT, - .name = "fid", - .description = "Get/Set vlan FID", - .max = RTL8367_FIDMAX, - .set = rtl8366_sw_set_vlan_fid, - .get = rtl8366_sw_get_vlan_fid, - }, -}; - -static const struct switch_dev_ops rtl8367_sw_ops = { - .attr_global = { - .attr = rtl8367_globals, - .n_attr = ARRAY_SIZE(rtl8367_globals), - }, - .attr_port = { - .attr = rtl8367_port, - .n_attr = ARRAY_SIZE(rtl8367_port), - }, - .attr_vlan = { - .attr = rtl8367_vlan, - .n_attr = ARRAY_SIZE(rtl8367_vlan), - }, - - .get_vlan_ports = rtl8366_sw_get_vlan_ports, - .set_vlan_ports = rtl8366_sw_set_vlan_ports, - .get_port_pvid = rtl8366_sw_get_port_pvid, - .set_port_pvid = rtl8366_sw_set_port_pvid, - .reset_switch = rtl8366_sw_reset_switch, - .get_port_link = rtl8367_sw_get_port_link, - .get_port_stats = rtl8367_sw_get_port_stats, -}; - -static int rtl8367_switch_init(struct rtl8366_smi *smi) -{ - struct switch_dev *dev = &smi->sw_dev; - int err; - - dev->name = "RTL8367"; - dev->cpu_port = smi->cpu_port; - dev->ports = RTL8367_NUM_PORTS; - dev->vlans = RTL8367_NUM_VIDS; - dev->ops = &rtl8367_sw_ops; - dev->alias = dev_name(smi->parent); - - err = register_switch(dev, NULL); - if (err) - dev_err(smi->parent, "switch registration failed\n"); - - return err; -} - -static void rtl8367_switch_cleanup(struct rtl8366_smi *smi) -{ - unregister_switch(&smi->sw_dev); -} - -static int rtl8367_mii_read(struct mii_bus *bus, int addr, int reg) -{ - struct rtl8366_smi *smi = bus->priv; - u32 val = 0; - int err; - - err = rtl8367_read_phy_reg(smi, addr, reg, &val); - if (err) - return 0xffff; - - return val; -} - -static int rtl8367_mii_write(struct mii_bus *bus, int addr, int reg, u16 val) -{ - struct rtl8366_smi *smi = bus->priv; - u32 t; - int err; - - err = rtl8367_write_phy_reg(smi, addr, reg, val); - if (err) - return err; - - /* flush write */ - (void) rtl8367_read_phy_reg(smi, addr, reg, &t); - - return err; -} - -static int rtl8367_detect(struct rtl8366_smi *smi) -{ - u32 rtl_no = 0; - u32 rtl_ver = 0; - char *chip_name; - int ret; - - ret = rtl8366_smi_read_reg(smi, RTL8367_RTL_NO_REG, &rtl_no); - if (ret) { - dev_err(smi->parent, "unable to read chip number\n"); - return ret; - } - - switch (rtl_no) { - case RTL8367_RTL_NO_8367R: - chip_name = "8367R"; - break; - case RTL8367_RTL_NO_8367M: - chip_name = "8367M"; - break; - default: - dev_err(smi->parent, "unknown chip number (%04x)\n", rtl_no); - return -ENODEV; - } - - ret = rtl8366_smi_read_reg(smi, RTL8367_RTL_VER_REG, &rtl_ver); - if (ret) { - dev_err(smi->parent, "unable to read chip version\n"); - return ret; - } - - dev_info(smi->parent, "RTL%s ver. %u chip found\n", - chip_name, rtl_ver & RTL8367_RTL_VER_MASK); - - return 0; -} - -static struct rtl8366_smi_ops rtl8367_smi_ops = { - .detect = rtl8367_detect, - .reset_chip = rtl8367_reset_chip, - .setup = rtl8367_setup, - - .mii_read = rtl8367_mii_read, - .mii_write = rtl8367_mii_write, - - .get_vlan_mc = rtl8367_get_vlan_mc, - .set_vlan_mc = rtl8367_set_vlan_mc, - .get_vlan_4k = rtl8367_get_vlan_4k, - .set_vlan_4k = rtl8367_set_vlan_4k, - .get_mc_index = rtl8367_get_mc_index, - .set_mc_index = rtl8367_set_mc_index, - .get_mib_counter = rtl8367_get_mib_counter, - .is_vlan_valid = rtl8367_is_vlan_valid, - .enable_vlan = rtl8367_enable_vlan, - .enable_vlan4k = rtl8367_enable_vlan4k, - .enable_port = rtl8367_enable_port, -}; - -static int rtl8367_probe(struct platform_device *pdev) -{ - struct rtl8366_smi *smi; - int err; - - smi = rtl8366_smi_probe(pdev); - if (IS_ERR(smi)) - return PTR_ERR(smi); - - smi->clk_delay = 1500; - smi->cmd_read = 0xb9; - smi->cmd_write = 0xb8; - smi->ops = &rtl8367_smi_ops; - smi->cpu_port = UINT_MAX; /* not defined yet */ - smi->num_ports = RTL8367_NUM_PORTS; - smi->num_vlan_mc = RTL8367_NUM_VLANS; - smi->mib_counters = rtl8367_mib_counters; - smi->num_mib_counters = ARRAY_SIZE(rtl8367_mib_counters); - - err = rtl8366_smi_init(smi); - if (err) - goto err_free_smi; - - platform_set_drvdata(pdev, smi); - - err = rtl8367_switch_init(smi); - if (err) - goto err_clear_drvdata; - - return 0; - - err_clear_drvdata: - platform_set_drvdata(pdev, NULL); - rtl8366_smi_cleanup(smi); - err_free_smi: - kfree(smi); - return err; -} - -static int rtl8367_remove(struct platform_device *pdev) -{ - struct rtl8366_smi *smi = platform_get_drvdata(pdev); - - if (smi) { - rtl8367_switch_cleanup(smi); - platform_set_drvdata(pdev, NULL); - rtl8366_smi_cleanup(smi); - kfree(smi); - } - - return 0; -} - -static void rtl8367_shutdown(struct platform_device *pdev) -{ - struct rtl8366_smi *smi = platform_get_drvdata(pdev); - - if (smi) - rtl8367_reset_chip(smi); -} - -#ifdef CONFIG_OF -static const struct of_device_id rtl8367_match[] = { - { .compatible = "realtek,rtl8367" }, - {}, -}; -MODULE_DEVICE_TABLE(of, rtl8367_match); -#endif - -static struct platform_driver rtl8367_driver = { - .driver = { - .name = RTL8367_DRIVER_NAME, - .owner = THIS_MODULE, -#ifdef CONFIG_OF - .of_match_table = of_match_ptr(rtl8367_match), -#endif - }, - .probe = rtl8367_probe, - .remove = rtl8367_remove, - .shutdown = rtl8367_shutdown, -}; - -static int __init rtl8367_module_init(void) -{ - return platform_driver_register(&rtl8367_driver); -} -module_init(rtl8367_module_init); - -static void __exit rtl8367_module_exit(void) -{ - platform_driver_unregister(&rtl8367_driver); -} -module_exit(rtl8367_module_exit); - -MODULE_DESCRIPTION("Realtek RTL8367 ethernet switch driver"); -MODULE_AUTHOR("Gabor Juhos "); -MODULE_LICENSE("GPL v2"); -MODULE_ALIAS("platform:" RTL8367_DRIVER_NAME); diff --git a/target/linux/generic/files-6.12/drivers/net/phy/rtl8367b.c b/target/linux/generic/files-6.12/drivers/net/phy/rtl8367b.c deleted file mode 100644 index 4236912dd51e47..00000000000000 --- a/target/linux/generic/files-6.12/drivers/net/phy/rtl8367b.c +++ /dev/null @@ -1,1652 +0,0 @@ -/* - * Platform driver for Realtek RTL8367B family chips, i.e. RTL8367RB and RTL8367R-VB - * extended with support for RTL8367C family chips, i.e. RTL8367RB-VB and RTL8367S - * extended with support for RTL8367D family chips, i.e. RTL8367S-VB - * - * Copyright (C) 2012 Gabor Juhos - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published - * by the Free Software Foundation. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "rtl8366_smi.h" - -#define RTL8367B_RESET_DELAY 1000 /* msecs*/ - -#define RTL8367B_PHY_ADDR_MAX 8 -#define RTL8367B_PHY_REG_MAX 31 - -#define RTL8367B_VID_MASK 0x3fff -#define RTL8367B_FID_MASK 0xf -#define RTL8367B_UNTAG_MASK 0xff -#define RTL8367B_MEMBER_MASK 0xff - -#define RTL8367B_PORT_MISC_CFG_REG(_p) (0x000e + 0x20 * (_p)) -#define RTL8367B_PORT_MISC_CFG_EGRESS_MODE_SHIFT 4 -#define RTL8367B_PORT_MISC_CFG_EGRESS_MODE_MASK 0x3 -#define RTL8367B_PORT_MISC_CFG_EGRESS_MODE_ORIGINAL 0 -#define RTL8367B_PORT_MISC_CFG_EGRESS_MODE_KEEP 1 -#define RTL8367B_PORT_MISC_CFG_EGRESS_MODE_PRI 2 -#define RTL8367B_PORT_MISC_CFG_EGRESS_MODE_REAL 3 - -#define RTL8367B_BYPASS_LINE_RATE_REG 0x03f7 - -#define RTL8367B_TA_CTRL_REG 0x0500 /*GOOD*/ -#define RTL8367B_TA_CTRL_SPA_SHIFT 8 -#define RTL8367B_TA_CTRL_SPA_MASK 0x7 -#define RTL8367B_TA_CTRL_METHOD BIT(4)/*GOOD*/ -#define RTL8367B_TA_CTRL_CMD_SHIFT 3 -#define RTL8367B_TA_CTRL_CMD_READ 0 -#define RTL8367B_TA_CTRL_CMD_WRITE 1 -#define RTL8367B_TA_CTRL_TABLE_SHIFT 0 /*GOOD*/ -#define RTL8367B_TA_CTRL_TABLE_ACLRULE 1 -#define RTL8367B_TA_CTRL_TABLE_ACLACT 2 -#define RTL8367B_TA_CTRL_TABLE_CVLAN 3 -#define RTL8367B_TA_CTRL_TABLE_L2 4 -#define RTL8367B_TA_CTRL_CVLAN_READ \ - ((RTL8367B_TA_CTRL_CMD_READ << RTL8367B_TA_CTRL_CMD_SHIFT) | \ - RTL8367B_TA_CTRL_TABLE_CVLAN) -#define RTL8367B_TA_CTRL_CVLAN_WRITE \ - ((RTL8367B_TA_CTRL_CMD_WRITE << RTL8367B_TA_CTRL_CMD_SHIFT) | \ - RTL8367B_TA_CTRL_TABLE_CVLAN) - -#define RTL8367B_TA_ADDR_REG 0x0501/*GOOD*/ -#define RTL8367B_TA_ADDR_MASK 0x3fff/*GOOD*/ - -#define RTL8367B_TA_LUT_REG 0x0502/*GOOD*/ - -#define RTL8367B_TA_WRDATA_REG(_x) (0x0510 + (_x))/*GOOD*/ -#define RTL8367B_TA_VLAN_NUM_WORDS 2 -#define RTL8367B_TA_VLAN_VID_MASK RTL8367B_VID_MASK -#define RTL8367B_TA_VLAN0_MEMBER_SHIFT 0 -#define RTL8367B_TA_VLAN0_MEMBER_MASK RTL8367B_MEMBER_MASK -#define RTL8367B_TA_VLAN0_UNTAG_SHIFT 8 -#define RTL8367B_TA_VLAN0_UNTAG_MASK RTL8367B_MEMBER_MASK -#define RTL8367B_TA_VLAN1_FID_SHIFT 0 -#define RTL8367B_TA_VLAN1_FID_MASK RTL8367B_FID_MASK - -#define RTL8367B_TA_RDDATA_REG(_x) (0x0520 + (_x))/*GOOD*/ - -#define RTL8367B_VLAN_PVID_CTRL_REG(_p) (0x0700 + (_p) / 2) /*GOOD*/ -#define RTL8367B_VLAN_PVID_CTRL_MASK 0x1f /*GOOD*/ -#define RTL8367B_VLAN_PVID_CTRL_SHIFT(_p) (8 * ((_p) % 2)) /*GOOD*/ - -#define RTL8367B_VLAN_MC_BASE(_x) (0x0728 + (_x) * 4) /*GOOD*/ -#define RTL8367B_VLAN_MC_NUM_WORDS 4 /*GOOD*/ -#define RTL8367B_VLAN_MC0_MEMBER_SHIFT 0/*GOOD*/ -#define RTL8367B_VLAN_MC0_MEMBER_MASK RTL8367B_MEMBER_MASK/*GOOD*/ -#define RTL8367B_VLAN_MC1_FID_SHIFT 0/*GOOD*/ -#define RTL8367B_VLAN_MC1_FID_MASK RTL8367B_FID_MASK/*GOOD*/ -#define RTL8367B_VLAN_MC3_EVID_SHIFT 0/*GOOD*/ -#define RTL8367B_VLAN_MC3_EVID_MASK RTL8367B_VID_MASK/*GOOD*/ - -#define RTL8367B_VLAN_CTRL_REG 0x07a8 /*GOOD*/ -#define RTL8367B_VLAN_CTRL_ENABLE BIT(0) - -#define RTL8367B_VLAN_INGRESS_REG 0x07a9 /*GOOD*/ - -#define RTL8367B_PORT_ISOLATION_REG(_p) (0x08a2 + (_p)) /*GOOD*/ - -#define RTL8367B_MIB_COUNTER_REG(_x) (0x1000 + (_x)) /*GOOD*/ -#define RTL8367B_MIB_COUNTER_PORT_OFFSET 0x007c /*GOOD*/ - -#define RTL8367B_MIB_ADDRESS_REG 0x1004 /*GOOD*/ - -#define RTL8367B_MIB_CTRL0_REG(_x) (0x1005 + (_x)) /*GOOD*/ -#define RTL8367B_MIB_CTRL0_GLOBAL_RESET_MASK BIT(11) /*GOOD*/ -#define RTL8367B_MIB_CTRL0_QM_RESET_MASK BIT(10) /*GOOD*/ -#define RTL8367B_MIB_CTRL0_PORT_RESET_MASK(_p) BIT(2 + (_p)) /*GOOD*/ -#define RTL8367B_MIB_CTRL0_RESET_MASK BIT(1) /*GOOD*/ -#define RTL8367B_MIB_CTRL0_BUSY_MASK BIT(0) /*GOOD*/ - -#define RTL8367B_SWC0_REG 0x1200/*GOOD*/ -#define RTL8367B_SWC0_MAX_LENGTH_SHIFT 13/*GOOD*/ -#define RTL8367B_SWC0_MAX_LENGTH(_x) ((_x) << 13) /*GOOD*/ -#define RTL8367B_SWC0_MAX_LENGTH_MASK RTL8367B_SWC0_MAX_LENGTH(0x3) -#define RTL8367B_SWC0_MAX_LENGTH_1522 RTL8367B_SWC0_MAX_LENGTH(0) -#define RTL8367B_SWC0_MAX_LENGTH_1536 RTL8367B_SWC0_MAX_LENGTH(1) -#define RTL8367B_SWC0_MAX_LENGTH_1552 RTL8367B_SWC0_MAX_LENGTH(2) -#define RTL8367B_SWC0_MAX_LENGTH_16000 RTL8367B_SWC0_MAX_LENGTH(3) - -#define RTL8367B_CHIP_NUMBER_REG 0x1300/*GOOD*/ - -#define RTL8367B_CHIP_VER_REG 0x1301/*GOOD*/ -#define RTL8367B_CHIP_VER_RLVID_SHIFT 12/*GOOD*/ -#define RTL8367B_CHIP_VER_RLVID_MASK 0xf/*GOOD*/ -#define RTL8367B_CHIP_VER_MCID_SHIFT 8/*GOOD*/ -#define RTL8367B_CHIP_VER_MCID_MASK 0xf/*GOOD*/ -#define RTL8367B_CHIP_VER_BOID_SHIFT 4/*GOOD*/ -#define RTL8367B_CHIP_VER_BOID_MASK 0xf/*GOOD*/ -#define RTL8367B_CHIP_VER_AFE_SHIFT 0/*GOOD*/ -#define RTL8367B_CHIP_VER_AFE_MASK 0x1/*GOOD*/ - -#define RTL8367B_CHIP_MODE_REG 0x1302 -#define RTL8367B_CHIP_MODE_MASK 0x7 - -#define RTL8367B_CHIP_DEBUG0_REG 0x1303 -#define RTL8367B_DEBUG0_SEL33(_x) BIT(8 + (_x)) -#define RTL8367B_DEBUG0_DRI_OTHER BIT(7) -#define RTL8367B_DEBUG0_DRI_RG(_x) BIT(5 + (_x)) -#define RTL8367B_DEBUG0_DRI(_x) BIT(3 + (_x)) -#define RTL8367B_DEBUG0_SLR_OTHER BIT(2) -#define RTL8367B_DEBUG0_SLR(_x) BIT(_x) - -#define RTL8367B_CHIP_DEBUG1_REG 0x1304 -#define RTL8367B_DEBUG1_DN_MASK(_x) \ - GENMASK(6 + (_x)*8, 4 + (_x)*8) -#define RTL8367B_DEBUG1_DN_SHIFT(_x) (4 + (_x) * 8) -#define RTL8367B_DEBUG1_DP_MASK(_x) \ - GENMASK(2 + (_x) * 8, (_x) * 8) -#define RTL8367B_DEBUG1_DP_SHIFT(_x) ((_x) * 8) - -#define RTL8367B_CHIP_DEBUG2_REG 0x13e2 -#define RTL8367B_DEBUG2_RG2_DN_MASK GENMASK(8, 6) -#define RTL8367B_DEBUG2_RG2_DN_SHIFT 6 -#define RTL8367B_DEBUG2_RG2_DP_MASK GENMASK(5, 3) -#define RTL8367B_DEBUG2_RG2_DP_SHIFT 3 -#define RTL8367B_DEBUG2_DRI_EXT2_RG BIT(2) -#define RTL8367B_DEBUG2_DRI_EXT2 BIT(1) -#define RTL8367B_DEBUG2_SLR_EXT2 BIT(0) - -#define RTL8367B_DIS_REG 0x1305 -#define RTL8367B_DIS_SKIP_MII_RXER(_x) BIT(12 + (_x)) -#define RTL8367B_DIS_RGMII_SHIFT(_x) (4 * (_x)) -#define RTL8367B_DIS_RGMII_MASK 0x7 - -#define RTL8367B_DIS2_REG 0x13c3 -#define RTL8367B_DIS2_SKIP_MII_RXER_SHIFT 4 -#define RTL8367B_DIS2_SKIP_MII_RXER 0x10 -#define RTL8367B_DIS2_RGMII_SHIFT 0 -#define RTL8367B_DIS2_RGMII_MASK 0xf - -#define RTL8367B_EXT_RGMXF_REG(_x) \ - ((_x) == 2 ? 0x13c5 : 0x1306 + (_x)) -#define RTL8367B_EXT_RGMXF_DUMMY0_SHIFT 5 -#define RTL8367B_EXT_RGMXF_DUMMY0_MASK 0x7ff -#define RTL8367B_EXT_RGMXF_TXDELAY_SHIFT 3 -#define RTL8367B_EXT_RGMXF_TXDELAY_MASK 1 -#define RTL8367B_EXT_RGMXF_RXDELAY_MASK 0x7 - -#define RTL8367B_DI_FORCE_REG(_x) \ - ((_x) == 2 ? 0x13c4 : 0x1310 + (_x)) -#define RTL8367B_DI_FORCE_MODE BIT(12) -#define RTL8367B_DI_FORCE_NWAY BIT(7) -#define RTL8367B_DI_FORCE_TXPAUSE BIT(6) -#define RTL8367B_DI_FORCE_RXPAUSE BIT(5) -#define RTL8367B_DI_FORCE_LINK BIT(4) -#define RTL8367B_DI_FORCE_DUPLEX BIT(2) -#define RTL8367B_DI_FORCE_SPEED_MASK 3 -#define RTL8367B_DI_FORCE_SPEED_10 0 -#define RTL8367B_DI_FORCE_SPEED_100 1 -#define RTL8367B_DI_FORCE_SPEED_1000 2 - -#define RTL8367B_MAC_FORCE_REG(_x) (0x1312 + (_x)) - -#define RTL8367B_CHIP_RESET_REG 0x1322 /*GOOD*/ -#define RTL8367B_CHIP_RESET_SW BIT(1) /*GOOD*/ -#define RTL8367B_CHIP_RESET_HW BIT(0) /*GOOD*/ - -#define RTL8367B_PORT_STATUS_REG(_p) (0x1352 + (_p)) /*GOOD*/ -#define RTL8367B_PORT_STATUS_EN_1000_SPI BIT(11) /*GOOD*/ -#define RTL8367B_PORT_STATUS_EN_100_SPI BIT(10)/*GOOD*/ -#define RTL8367B_PORT_STATUS_NWAY_FAULT BIT(9)/*GOOD*/ -#define RTL8367B_PORT_STATUS_LINK_MASTER BIT(8)/*GOOD*/ -#define RTL8367B_PORT_STATUS_NWAY BIT(7)/*GOOD*/ -#define RTL8367B_PORT_STATUS_TXPAUSE BIT(6)/*GOOD*/ -#define RTL8367B_PORT_STATUS_RXPAUSE BIT(5)/*GOOD*/ -#define RTL8367B_PORT_STATUS_LINK BIT(4)/*GOOD*/ -#define RTL8367B_PORT_STATUS_DUPLEX BIT(2)/*GOOD*/ -#define RTL8367B_PORT_STATUS_SPEED_MASK 0x0003/*GOOD*/ -#define RTL8367B_PORT_STATUS_SPEED_10 0/*GOOD*/ -#define RTL8367B_PORT_STATUS_SPEED_100 1/*GOOD*/ -#define RTL8367B_PORT_STATUS_SPEED_1000 2/*GOOD*/ - -#define RTL8367B_RTL_MAGIC_ID_REG 0x13c2 -#define RTL8367B_RTL_MAGIC_ID_VAL 0x0249 - -#define RTL8367B_IA_CTRL_REG 0x1f00 -#define RTL8367B_IA_CTRL_RW(_x) ((_x) << 1) -#define RTL8367B_IA_CTRL_RW_READ RTL8367B_IA_CTRL_RW(0) -#define RTL8367B_IA_CTRL_RW_WRITE RTL8367B_IA_CTRL_RW(1) -#define RTL8367B_IA_CTRL_CMD_MASK BIT(0) - -#define RTL8367B_IA_STATUS_REG 0x1f01 -#define RTL8367B_IA_STATUS_PHY_BUSY BIT(2) -#define RTL8367B_IA_STATUS_SDS_BUSY BIT(1) -#define RTL8367B_IA_STATUS_MDX_BUSY BIT(0) - -#define RTL8367B_IA_ADDRESS_REG 0x1f02 -#define RTL8367B_IA_WRITE_DATA_REG 0x1f03 -#define RTL8367B_IA_READ_DATA_REG 0x1f04 - -#define RTL8367B_INTERNAL_PHY_REG(_a, _r) (0x2000 + 32 * (_a) + (_r)) - -#define RTL8367B_NUM_MIB_COUNTERS 58 - -#define RTL8367B_CPU_PORT_NUM 5 -#define RTL8367B_NUM_PORTS 8 -#define RTL8367B_NUM_VLANS 32 -#define RTL8367B_NUM_VIDS 4096 -#define RTL8367B_PRIORITYMAX 7 -#define RTL8367B_FIDMAX 7 - -#define RTL8367B_PORT_0 BIT(0) -#define RTL8367B_PORT_1 BIT(1) -#define RTL8367B_PORT_2 BIT(2) -#define RTL8367B_PORT_3 BIT(3) -#define RTL8367B_PORT_4 BIT(4) -#define RTL8367B_PORT_E0 BIT(5) /* External port 0 */ -#define RTL8367B_PORT_E1 BIT(6) /* External port 1 */ -#define RTL8367B_PORT_E2 BIT(7) /* External port 2 */ - -#define RTL8367B_PORTS_ALL \ - (RTL8367B_PORT_0 | RTL8367B_PORT_1 | RTL8367B_PORT_2 | \ - RTL8367B_PORT_3 | RTL8367B_PORT_4 | RTL8367B_PORT_E0 | \ - RTL8367B_PORT_E1 | RTL8367B_PORT_E2) - -#define RTL8367B_PORTS_ALL_BUT_CPU \ - (RTL8367B_PORT_0 | RTL8367B_PORT_1 | RTL8367B_PORT_2 | \ - RTL8367B_PORT_3 | RTL8367B_PORT_4 | RTL8367B_PORT_E1 | \ - RTL8367B_PORT_E2) - -struct rtl8367b_initval { - u16 reg; - u16 val; -}; - -#define RTL8367B_MIB_RXB_ID 0 /* IfInOctets */ -#define RTL8367B_MIB_TXB_ID 28 /* IfOutOctets */ - -#define RTL8367D_PORT_STATUS_REG(_p) (0x12d0 + (_p)) - -#define RTL8367D_PORT_STATUS_SPEED1_MASK 0x3000 -#define RTL8367D_PORT_STATUS_SPEED1_SHIFT 10 /*12-2*/ - -#define RTL8367D_REG_MAC0_FORCE_SELECT 0x12c0 -#define RTL8367D_REG_MAC0_FORCE_SELECT_EN 0x12c8 - -#define RTL8367D_VLAN_PVID_CTRL_REG(_p) (0x0700 + (_p)) -#define RTL8367D_VLAN_PVID_CTRL_MASK 0xfff -#define RTL8367D_VLAN_PVID_CTRL_SHIFT(_p) 0 - -#define RTL8367D_FIDMAX 3 -#define RTL8367D_FID_MASK 3 -#define RTL8367D_TA_VLAN1_FID_SHIFT 0 -#define RTL8367D_TA_VLAN1_FID_MASK RTL8367D_FID_MASK - -#define RTL8367D_VID_MASK 0xfff -#define RTL8367D_TA_VLAN_VID_MASK RTL8367D_VID_MASK - -#define RTL8367D_REG_EXT_TXC_DLY 0x13f9 -#define RTL8367D_EXT1_RGMII_TX_DLY_MASK 0x38 - -#define RTL8367D_REG_TOP_CON0 0x1d70 -#define RTL8367D_MAC7_SEL_EXT1_MASK 0x2000 -#define RTL8367D_MAC4_SEL_EXT1_MASK 0x1000 - -#define RTL8367D_REG_SDS1_MISC0 0x1d78 -#define RTL8367D_SDS1_MODE_MASK 0x1f -#define RTL8367D_PORT_SDS_MODE_DISABLE 0x1f - -static struct rtl8366_mib_counter -rtl8367b_mib_counters[RTL8367B_NUM_MIB_COUNTERS] = { - {0, 0, 4, "ifInOctets" }, - {0, 4, 2, "dot3StatsFCSErrors" }, - {0, 6, 2, "dot3StatsSymbolErrors" }, - {0, 8, 2, "dot3InPauseFrames" }, - {0, 10, 2, "dot3ControlInUnknownOpcodes" }, - {0, 12, 2, "etherStatsFragments" }, - {0, 14, 2, "etherStatsJabbers" }, - {0, 16, 2, "ifInUcastPkts" }, - {0, 18, 2, "etherStatsDropEvents" }, - {0, 20, 2, "ifInMulticastPkts" }, - {0, 22, 2, "ifInBroadcastPkts" }, - {0, 24, 2, "inMldChecksumError" }, - {0, 26, 2, "inIgmpChecksumError" }, - {0, 28, 2, "inMldSpecificQuery" }, - {0, 30, 2, "inMldGeneralQuery" }, - {0, 32, 2, "inIgmpSpecificQuery" }, - {0, 34, 2, "inIgmpGeneralQuery" }, - {0, 36, 2, "inMldLeaves" }, - {0, 38, 2, "inIgmpLeaves" }, - - {0, 40, 4, "etherStatsOctets" }, - {0, 44, 2, "etherStatsUnderSizePkts" }, - {0, 46, 2, "etherOversizeStats" }, - {0, 48, 2, "etherStatsPkts64Octets" }, - {0, 50, 2, "etherStatsPkts65to127Octets" }, - {0, 52, 2, "etherStatsPkts128to255Octets" }, - {0, 54, 2, "etherStatsPkts256to511Octets" }, - {0, 56, 2, "etherStatsPkts512to1023Octets" }, - {0, 58, 2, "etherStatsPkts1024to1518Octets" }, - - {0, 60, 4, "ifOutOctets" }, - {0, 64, 2, "dot3StatsSingleCollisionFrames" }, - {0, 66, 2, "dot3StatMultipleCollisionFrames" }, - {0, 68, 2, "dot3sDeferredTransmissions" }, - {0, 70, 2, "dot3StatsLateCollisions" }, - {0, 72, 2, "etherStatsCollisions" }, - {0, 74, 2, "dot3StatsExcessiveCollisions" }, - {0, 76, 2, "dot3OutPauseFrames" }, - {0, 78, 2, "ifOutDiscards" }, - {0, 80, 2, "dot1dTpPortInDiscards" }, - {0, 82, 2, "ifOutUcastPkts" }, - {0, 84, 2, "ifOutMulticastPkts" }, - {0, 86, 2, "ifOutBroadcastPkts" }, - {0, 88, 2, "outOampduPkts" }, - {0, 90, 2, "inOampduPkts" }, - {0, 92, 2, "inIgmpJoinsSuccess" }, - {0, 94, 2, "inIgmpJoinsFail" }, - {0, 96, 2, "inMldJoinsSuccess" }, - {0, 98, 2, "inMldJoinsFail" }, - {0, 100, 2, "inReportSuppressionDrop" }, - {0, 102, 2, "inLeaveSuppressionDrop" }, - {0, 104, 2, "outIgmpReports" }, - {0, 106, 2, "outIgmpLeaves" }, - {0, 108, 2, "outIgmpGeneralQuery" }, - {0, 110, 2, "outIgmpSpecificQuery" }, - {0, 112, 2, "outMldReports" }, - {0, 114, 2, "outMldLeaves" }, - {0, 116, 2, "outMldGeneralQuery" }, - {0, 118, 2, "outMldSpecificQuery" }, - {0, 120, 2, "inKnownMulticastPkts" }, -}; - -#define REG_RD(_smi, _reg, _val) \ - do { \ - err = rtl8366_smi_read_reg(_smi, _reg, _val); \ - if (err) \ - return err; \ - } while (0) - -#define REG_WR(_smi, _reg, _val) \ - do { \ - err = rtl8366_smi_write_reg(_smi, _reg, _val); \ - if (err) \ - return err; \ - } while (0) - -#define REG_RMW(_smi, _reg, _mask, _val) \ - do { \ - err = rtl8366_smi_rmwr(_smi, _reg, _mask, _val); \ - if (err) \ - return err; \ - } while (0) - -static const struct rtl8367b_initval rtl8367b_initvals[] = { - {0x1B03, 0x0876}, {0x1200, 0x7FC4}, {0x1305, 0xC000}, {0x121E, 0x03CA}, - {0x1233, 0x0352}, {0x1234, 0x0064}, {0x1237, 0x0096}, {0x1238, 0x0078}, - {0x1239, 0x0084}, {0x123A, 0x0030}, {0x205F, 0x0002}, {0x2059, 0x1A00}, - {0x205F, 0x0000}, {0x207F, 0x0002}, {0x2077, 0x0000}, {0x2078, 0x0000}, - {0x2079, 0x0000}, {0x207A, 0x0000}, {0x207B, 0x0000}, {0x207F, 0x0000}, - {0x205F, 0x0002}, {0x2053, 0x0000}, {0x2054, 0x0000}, {0x2055, 0x0000}, - {0x2056, 0x0000}, {0x2057, 0x0000}, {0x205F, 0x0000}, {0x133F, 0x0030}, - {0x133E, 0x000E}, {0x221F, 0x0005}, {0x2205, 0x8B86}, {0x2206, 0x800E}, - {0x221F, 0x0000}, {0x133F, 0x0010}, {0x12A3, 0x2200}, {0x6107, 0xE58B}, - {0x6103, 0xA970}, {0x0018, 0x0F00}, {0x0038, 0x0F00}, {0x0058, 0x0F00}, - {0x0078, 0x0F00}, {0x0098, 0x0F00}, {0x133F, 0x0030}, {0x133E, 0x000E}, - {0x221F, 0x0005}, {0x2205, 0x8B6E}, {0x2206, 0x0000}, {0x220F, 0x0100}, - {0x2205, 0xFFF6}, {0x2206, 0x0080}, {0x2205, 0x8000}, {0x2206, 0x0280}, - {0x2206, 0x2BF7}, {0x2206, 0x00E0}, {0x2206, 0xFFF7}, {0x2206, 0xA080}, - {0x2206, 0x02AE}, {0x2206, 0xF602}, {0x2206, 0x0153}, {0x2206, 0x0201}, - {0x2206, 0x6602}, {0x2206, 0x8044}, {0x2206, 0x0201}, {0x2206, 0x7CE0}, - {0x2206, 0x8B8C}, {0x2206, 0xE18B}, {0x2206, 0x8D1E}, {0x2206, 0x01E1}, - {0x2206, 0x8B8E}, {0x2206, 0x1E01}, {0x2206, 0xA000}, {0x2206, 0xE4AE}, - {0x2206, 0xD8EE}, {0x2206, 0x85C0}, {0x2206, 0x00EE}, {0x2206, 0x85C1}, - {0x2206, 0x00EE}, {0x2206, 0x8AFC}, {0x2206, 0x07EE}, {0x2206, 0x8AFD}, - {0x2206, 0x73EE}, {0x2206, 0xFFF6}, {0x2206, 0x00EE}, {0x2206, 0xFFF7}, - {0x2206, 0xFC04}, {0x2206, 0xF8E0}, {0x2206, 0x8B8E}, {0x2206, 0xAD20}, - {0x2206, 0x0302}, {0x2206, 0x8050}, {0x2206, 0xFC04}, {0x2206, 0xF8F9}, - {0x2206, 0xE08B}, {0x2206, 0x85AD}, {0x2206, 0x2548}, {0x2206, 0xE08A}, - {0x2206, 0xE4E1}, {0x2206, 0x8AE5}, {0x2206, 0x7C00}, {0x2206, 0x009E}, - {0x2206, 0x35EE}, {0x2206, 0x8AE4}, {0x2206, 0x00EE}, {0x2206, 0x8AE5}, - {0x2206, 0x00E0}, {0x2206, 0x8AFC}, {0x2206, 0xE18A}, {0x2206, 0xFDE2}, - {0x2206, 0x85C0}, {0x2206, 0xE385}, {0x2206, 0xC102}, {0x2206, 0x2DAC}, - {0x2206, 0xAD20}, {0x2206, 0x12EE}, {0x2206, 0x8AE4}, {0x2206, 0x03EE}, - {0x2206, 0x8AE5}, {0x2206, 0xB7EE}, {0x2206, 0x85C0}, {0x2206, 0x00EE}, - {0x2206, 0x85C1}, {0x2206, 0x00AE}, {0x2206, 0x1115}, {0x2206, 0xE685}, - {0x2206, 0xC0E7}, {0x2206, 0x85C1}, {0x2206, 0xAE08}, {0x2206, 0xEE85}, - {0x2206, 0xC000}, {0x2206, 0xEE85}, {0x2206, 0xC100}, {0x2206, 0xFDFC}, - {0x2206, 0x0400}, {0x2205, 0xE142}, {0x2206, 0x0701}, {0x2205, 0xE140}, - {0x2206, 0x0405}, {0x220F, 0x0000}, {0x221F, 0x0000}, {0x133E, 0x000E}, - {0x133F, 0x0010}, {0x13EB, 0x11BB}, {0x207F, 0x0002}, {0x2073, 0x1D22}, - {0x207F, 0x0000}, {0x133F, 0x0030}, {0x133E, 0x000E}, {0x2200, 0x1340}, - {0x133E, 0x000E}, {0x133F, 0x0010}, -}; - -static const struct rtl8367b_initval rtl8367c_initvals[] = { - {0x13c2, 0x0000}, {0x0018, 0x0f00}, {0x0038, 0x0f00}, {0x0058, 0x0f00}, - {0x0078, 0x0f00}, {0x0098, 0x0f00}, {0x1d15, 0x0a69}, {0x2000, 0x1340}, - {0x2020, 0x1340}, {0x2040, 0x1340}, {0x2060, 0x1340}, {0x2080, 0x1340}, - {0x13eb, 0x15bb}, {0x1303, 0x06d6}, {0x1304, 0x0700}, {0x13E2, 0x003F}, - {0x13F9, 0x0090}, {0x121e, 0x03CA}, {0x1233, 0x0352}, {0x1237, 0x00a0}, - {0x123a, 0x0030}, {0x1239, 0x0084}, {0x0301, 0x1000}, {0x1349, 0x001F}, - {0x18e0, 0x4004}, {0x122b, 0x641c}, {0x1305, 0xc000}, {0x1200, 0x7fcb}, - {0x0884, 0x0003}, {0x06eb, 0x0001}, {0x00cf, 0xffff}, {0x00d0, 0x0007}, - {0x00ce, 0x48b0}, {0x00ce, 0x48b0}, {0x0398, 0xffff}, {0x0399, 0x0007}, - {0x0300, 0x0001}, {0x03fa, 0x0007}, {0x08c8, 0x00c0}, {0x0a30, 0x020e}, - {0x0800, 0x0000}, {0x0802, 0x0000}, {0x09da, 0x0017}, {0x1d32, 0x0002}, -}; - -static int rtl8367b_write_initvals(struct rtl8366_smi *smi, - const struct rtl8367b_initval *initvals, - int count) -{ - int err; - int i; - - for (i = 0; i < count; i++) - REG_WR(smi, initvals[i].reg, initvals[i].val); - - return 0; -} - -static int rtl8367b_read_phy_reg(struct rtl8366_smi *smi, - u32 phy_addr, u32 phy_reg, u32 *val) -{ - int timeout; - u32 data; - int err; - - if (phy_addr > RTL8367B_PHY_ADDR_MAX) - return -EINVAL; - - if (phy_reg > RTL8367B_PHY_REG_MAX) - return -EINVAL; - - REG_RD(smi, RTL8367B_IA_STATUS_REG, &data); - if (data & RTL8367B_IA_STATUS_PHY_BUSY) - return -ETIMEDOUT; - - /* prepare address */ - REG_WR(smi, RTL8367B_IA_ADDRESS_REG, - RTL8367B_INTERNAL_PHY_REG(phy_addr, phy_reg)); - - /* send read command */ - REG_WR(smi, RTL8367B_IA_CTRL_REG, - RTL8367B_IA_CTRL_CMD_MASK | RTL8367B_IA_CTRL_RW_READ); - - timeout = 5; - do { - REG_RD(smi, RTL8367B_IA_STATUS_REG, &data); - if ((data & RTL8367B_IA_STATUS_PHY_BUSY) == 0) - break; - - if (timeout--) { - dev_err(smi->parent, "phy read timed out\n"); - return -ETIMEDOUT; - } - - udelay(1); - } while (1); - - /* read data */ - REG_RD(smi, RTL8367B_IA_READ_DATA_REG, val); - - dev_dbg(smi->parent, "phy_read: addr:%02x, reg:%02x, val:%04x\n", - phy_addr, phy_reg, *val); - return 0; -} - -static int rtl8367b_write_phy_reg(struct rtl8366_smi *smi, - u32 phy_addr, u32 phy_reg, u32 val) -{ - int timeout; - u32 data; - int err; - - dev_dbg(smi->parent, "phy_write: addr:%02x, reg:%02x, val:%04x\n", - phy_addr, phy_reg, val); - - if (phy_addr > RTL8367B_PHY_ADDR_MAX) - return -EINVAL; - - if (phy_reg > RTL8367B_PHY_REG_MAX) - return -EINVAL; - - REG_RD(smi, RTL8367B_IA_STATUS_REG, &data); - if (data & RTL8367B_IA_STATUS_PHY_BUSY) - return -ETIMEDOUT; - - /* preapre data */ - REG_WR(smi, RTL8367B_IA_WRITE_DATA_REG, val); - - /* prepare address */ - REG_WR(smi, RTL8367B_IA_ADDRESS_REG, - RTL8367B_INTERNAL_PHY_REG(phy_addr, phy_reg)); - - /* send write command */ - REG_WR(smi, RTL8367B_IA_CTRL_REG, - RTL8367B_IA_CTRL_CMD_MASK | RTL8367B_IA_CTRL_RW_WRITE); - - timeout = 5; - do { - REG_RD(smi, RTL8367B_IA_STATUS_REG, &data); - if ((data & RTL8367B_IA_STATUS_PHY_BUSY) == 0) - break; - - if (timeout--) { - dev_err(smi->parent, "phy write timed out\n"); - return -ETIMEDOUT; - } - - udelay(1); - } while (1); - - return 0; -} - -static int rtl8367b_init_regs(struct rtl8366_smi *smi) -{ - const struct rtl8367b_initval *initvals; - int count; - - switch (smi->rtl8367b_chip) { - case RTL8367B_CHIP_RTL8367RB: - case RTL8367B_CHIP_RTL8367R_VB: - initvals = rtl8367b_initvals; - count = ARRAY_SIZE(rtl8367b_initvals); - break; - case RTL8367B_CHIP_RTL8367RB_VB: - case RTL8367B_CHIP_RTL8367S: - case RTL8367B_CHIP_RTL8367S_VB: - initvals = rtl8367c_initvals; - count = ARRAY_SIZE(rtl8367c_initvals); - if ((smi->rtl8367b_chip == RTL8367B_CHIP_RTL8367S_VB) && (smi->emu_vlanmc == NULL)) { - smi->emu_vlanmc = kzalloc(sizeof(struct rtl8366_vlan_mc) * smi->num_vlan_mc, GFP_KERNEL); - dev_info(smi->parent, "alloc vlan mc emulator"); - } - break; - default: - return -ENODEV; - } - - return rtl8367b_write_initvals(smi, initvals, count); -} - -static int rtl8367b_reset_chip(struct rtl8366_smi *smi) -{ - int timeout = 10; - int err; - u32 data; - - REG_WR(smi, RTL8367B_CHIP_RESET_REG, RTL8367B_CHIP_RESET_HW); - msleep(RTL8367B_RESET_DELAY); - - do { - REG_RD(smi, RTL8367B_CHIP_RESET_REG, &data); - if (!(data & RTL8367B_CHIP_RESET_HW)) - break; - - msleep(1); - } while (--timeout); - - if (!timeout) { - dev_err(smi->parent, "chip reset timed out\n"); - return -ETIMEDOUT; - } - - return 0; -} - -static int rtl8367b_extif_set_mode(struct rtl8366_smi *smi, int id, - enum rtl8367_extif_mode mode) -{ - int err; - u32 data; - - /* set port mode */ - switch (mode) { - case RTL8367_EXTIF_MODE_RGMII: - REG_RMW(smi, RTL8367B_CHIP_DEBUG0_REG, - RTL8367B_DEBUG0_SEL33(id), - RTL8367B_DEBUG0_SEL33(id)); - if (id <= 1) { - REG_RMW(smi, RTL8367B_CHIP_DEBUG0_REG, - RTL8367B_DEBUG0_DRI(id) | - RTL8367B_DEBUG0_DRI_RG(id) | - RTL8367B_DEBUG0_SLR(id), - RTL8367B_DEBUG0_DRI_RG(id) | - RTL8367B_DEBUG0_SLR(id)); - REG_RMW(smi, RTL8367B_CHIP_DEBUG1_REG, - RTL8367B_DEBUG1_DN_MASK(id) | - RTL8367B_DEBUG1_DP_MASK(id), - (7 << RTL8367B_DEBUG1_DN_SHIFT(id)) | - (7 << RTL8367B_DEBUG1_DP_SHIFT(id))); - if ((smi->rtl8367b_chip == RTL8367B_CHIP_RTL8367S_VB) && (id == 1)) { - REG_RMW(smi, RTL8367D_REG_EXT_TXC_DLY, RTL8367D_EXT1_RGMII_TX_DLY_MASK, 0); - /* Configure RGMII/MII mux to port 7 if UTP_PORT4 is not RGMII mode */ - REG_RD(smi, RTL8367D_REG_TOP_CON0, &data); - data &= RTL8367D_MAC4_SEL_EXT1_MASK; - if (data == 0) - REG_RMW(smi, RTL8367D_REG_TOP_CON0, RTL8367D_MAC7_SEL_EXT1_MASK, RTL8367D_MAC7_SEL_EXT1_MASK); - REG_RMW(smi, RTL8367D_REG_SDS1_MISC0, RTL8367D_SDS1_MODE_MASK, RTL8367D_PORT_SDS_MODE_DISABLE); - } - } else { - REG_RMW(smi, RTL8367B_CHIP_DEBUG2_REG, - RTL8367B_DEBUG2_DRI_EXT2 | - RTL8367B_DEBUG2_DRI_EXT2_RG | - RTL8367B_DEBUG2_SLR_EXT2 | - RTL8367B_DEBUG2_RG2_DN_MASK | - RTL8367B_DEBUG2_RG2_DP_MASK, - RTL8367B_DEBUG2_DRI_EXT2_RG | - RTL8367B_DEBUG2_SLR_EXT2 | - (7 << RTL8367B_DEBUG2_RG2_DN_SHIFT) | - (7 << RTL8367B_DEBUG2_RG2_DP_SHIFT)); - } - break; - - case RTL8367_EXTIF_MODE_TMII_MAC: - case RTL8367_EXTIF_MODE_TMII_PHY: - REG_RMW(smi, RTL8367B_BYPASS_LINE_RATE_REG, BIT(id), BIT(id)); - break; - - case RTL8367_EXTIF_MODE_GMII: - REG_RMW(smi, RTL8367B_CHIP_DEBUG0_REG, - RTL8367B_DEBUG0_SEL33(id), - RTL8367B_DEBUG0_SEL33(id)); - REG_RMW(smi, RTL8367B_EXT_RGMXF_REG(id), BIT(6), BIT(6)); - break; - - case RTL8367_EXTIF_MODE_MII_MAC: - case RTL8367_EXTIF_MODE_MII_PHY: - case RTL8367_EXTIF_MODE_DISABLED: - REG_RMW(smi, RTL8367B_BYPASS_LINE_RATE_REG, BIT(id), 0); - REG_RMW(smi, RTL8367B_EXT_RGMXF_REG(id), BIT(6), 0); - break; - - default: - dev_err(smi->parent, - "invalid mode for external interface %d\n", id); - return -EINVAL; - } - - if (id <= 1) - REG_RMW(smi, RTL8367B_DIS_REG, - RTL8367B_DIS_RGMII_MASK << RTL8367B_DIS_RGMII_SHIFT(id), - mode << RTL8367B_DIS_RGMII_SHIFT(id)); - else - REG_RMW(smi, RTL8367B_DIS2_REG, - RTL8367B_DIS2_RGMII_MASK << RTL8367B_DIS2_RGMII_SHIFT, - mode << RTL8367B_DIS2_RGMII_SHIFT); - - return 0; -} - -static int rtl8367b_extif_set_force(struct rtl8366_smi *smi, int id, - struct rtl8367_port_ability *pa) -{ - u32 mask; - u32 val; - int err; - - val = pa->speed & RTL8367B_DI_FORCE_SPEED_MASK; - val |= pa->nway ? RTL8367B_DI_FORCE_NWAY : 0; - val |= pa->txpause ? RTL8367B_DI_FORCE_TXPAUSE : 0; - val |= pa->rxpause ? RTL8367B_DI_FORCE_RXPAUSE : 0; - val |= pa->link ? RTL8367B_DI_FORCE_LINK : 0; - val |= pa->duplex ? RTL8367B_DI_FORCE_DUPLEX : 0; - - if (smi->rtl8367b_chip >= RTL8367B_CHIP_RTL8367S_VB) { /* Family D */ - val |= (pa->speed << RTL8367D_PORT_STATUS_SPEED1_SHIFT) & RTL8367D_PORT_STATUS_SPEED1_MASK; - if (smi->cpu_port != UINT_MAX) { - REG_WR(smi, RTL8367D_REG_MAC0_FORCE_SELECT + smi->cpu_port, val); - REG_WR(smi, RTL8367D_REG_MAC0_FORCE_SELECT_EN + smi->cpu_port, pa->force_mode ? 0xffff : 0x0000); - } - } else { - val |= pa->force_mode ? RTL8367B_DI_FORCE_MODE : 0; - mask = (RTL8367B_DI_FORCE_MODE | - RTL8367B_DI_FORCE_NWAY | - RTL8367B_DI_FORCE_TXPAUSE | - RTL8367B_DI_FORCE_RXPAUSE | - RTL8367B_DI_FORCE_LINK | - RTL8367B_DI_FORCE_DUPLEX | - RTL8367B_DI_FORCE_SPEED_MASK); - - REG_RMW(smi, RTL8367B_DI_FORCE_REG(id), mask, val); - } - - return 0; -} - -static int rtl8367b_extif_set_rgmii_delay(struct rtl8366_smi *smi, int id, - unsigned txdelay, unsigned rxdelay) -{ - u32 mask; - u32 val; - int err; - - mask = (RTL8367B_EXT_RGMXF_RXDELAY_MASK | - (RTL8367B_EXT_RGMXF_TXDELAY_MASK << - RTL8367B_EXT_RGMXF_TXDELAY_SHIFT)); - - val = rxdelay; - val |= txdelay << RTL8367B_EXT_RGMXF_TXDELAY_SHIFT; - - REG_RMW(smi, RTL8367B_EXT_RGMXF_REG(id), mask, val); - - return 0; -} - -static int rtl8367b_extif_init(struct rtl8366_smi *smi, int id, - struct rtl8367_extif_config *cfg) -{ - enum rtl8367_extif_mode mode; - int err; - - mode = (cfg) ? cfg->mode : RTL8367_EXTIF_MODE_DISABLED; - - err = rtl8367b_extif_set_mode(smi, id, mode); - if (err) - return err; - - if (mode != RTL8367_EXTIF_MODE_DISABLED) { - err = rtl8367b_extif_set_force(smi, id, &cfg->ability); - if (err) - return err; - - err = rtl8367b_extif_set_rgmii_delay(smi, id, cfg->txdelay, - cfg->rxdelay); - if (err) - return err; - } - - return 0; -} - -#ifdef CONFIG_OF -static int rtl8367b_extif_init_of(struct rtl8366_smi *smi, - const char *name) -{ - struct rtl8367_extif_config *cfg; - const __be32 *prop; - int size; - int err; - unsigned cpu_port; - unsigned id = UINT_MAX; - - prop = of_get_property(smi->parent->of_node, name, &size); - if (!prop || (size != (10 * sizeof(*prop)))) { - dev_err(smi->parent, "%s property is not defined or invalid\n", name); - err = -EINVAL; - goto err_init; - } - - cpu_port = be32_to_cpup(prop++); - switch (cpu_port) { - case RTL8367B_CPU_PORT_NUM: - case RTL8367B_CPU_PORT_NUM + 1: - case RTL8367B_CPU_PORT_NUM + 2: - if (smi->rtl8367b_chip == RTL8367B_CHIP_RTL8367R_VB) { /* for the RTL8367R-VB chip, cpu_port 5 corresponds to extif1 */ - if (cpu_port == RTL8367B_CPU_PORT_NUM) - id = 1; - else { - dev_err(smi->parent, "wrong cpu_port %u in %s property\n", cpu_port, name); - err = -EINVAL; - goto err_init; - } - } else if (smi->rtl8367b_chip == RTL8367B_CHIP_RTL8367S_VB) { /* for the RTL8367S-VB chip, cpu_port 7 corresponds to extif1, cpu_port 6 corresponds to extif0 */ - if (cpu_port != RTL8367B_CPU_PORT_NUM) { - id = cpu_port - RTL8367B_CPU_PORT_NUM - 1; - } else { - dev_err(smi->parent, "wrong cpu_port %u in %s property\n", cpu_port, name); - err = -EINVAL; - goto err_init; - } - } else { - id = cpu_port - RTL8367B_CPU_PORT_NUM; - } - if (smi->cpu_port == UINT_MAX) { - dev_info(smi->parent, "cpu_port:%u, assigned to extif%u\n", cpu_port, id); - smi->cpu_port = cpu_port; - } - break; - default: - dev_err(smi->parent, "wrong cpu_port %u in %s property\n", cpu_port, name); - err = -EINVAL; - goto err_init; - } - - cfg = kzalloc(sizeof(struct rtl8367_extif_config), GFP_KERNEL); - if (!cfg) - return -ENOMEM; - - cfg->txdelay = be32_to_cpup(prop++); - cfg->rxdelay = be32_to_cpup(prop++); - cfg->mode = be32_to_cpup(prop++); - cfg->ability.force_mode = be32_to_cpup(prop++); - cfg->ability.txpause = be32_to_cpup(prop++); - cfg->ability.rxpause = be32_to_cpup(prop++); - cfg->ability.link = be32_to_cpup(prop++); - cfg->ability.duplex = be32_to_cpup(prop++); - cfg->ability.speed = be32_to_cpup(prop++); - - err = rtl8367b_extif_init(smi, id, cfg); - kfree(cfg); - -err_init: - if (id != 0) rtl8367b_extif_init(smi, 0, NULL); - if (id != 1) rtl8367b_extif_init(smi, 1, NULL); - if (id != 2) rtl8367b_extif_init(smi, 2, NULL); - - return err; -} -#else -static int rtl8367b_extif_init_of(struct rtl8366_smi *smi, - const char *name) -{ - return -EINVAL; -} -#endif - -static int rtl8367b_setup(struct rtl8366_smi *smi) -{ - struct rtl8367_platform_data *pdata; - int err; - int i; - - pdata = smi->parent->platform_data; - - err = rtl8367b_init_regs(smi); - if (err) - return err; - - /* initialize external interfaces */ - if (smi->parent->of_node) { - err = rtl8367b_extif_init_of(smi, "realtek,extif"); - if (err) - return err; - } else { - err = rtl8367b_extif_init(smi, 0, pdata->extif0_cfg); - if (err) - return err; - - err = rtl8367b_extif_init(smi, 1, pdata->extif1_cfg); - if (err) - return err; - } - - /* set maximum packet length to 1536 bytes */ - REG_RMW(smi, RTL8367B_SWC0_REG, RTL8367B_SWC0_MAX_LENGTH_MASK, - RTL8367B_SWC0_MAX_LENGTH_1536); - - /* - * discard VLAN tagged packets if the port is not a member of - * the VLAN with which the packets is associated. - */ - REG_WR(smi, RTL8367B_VLAN_INGRESS_REG, RTL8367B_PORTS_ALL); - - /* - * Setup egress tag mode for each port. - */ - for (i = 0; i < RTL8367B_NUM_PORTS; i++) - REG_RMW(smi, - RTL8367B_PORT_MISC_CFG_REG(i), - RTL8367B_PORT_MISC_CFG_EGRESS_MODE_MASK << - RTL8367B_PORT_MISC_CFG_EGRESS_MODE_SHIFT, - RTL8367B_PORT_MISC_CFG_EGRESS_MODE_ORIGINAL << - RTL8367B_PORT_MISC_CFG_EGRESS_MODE_SHIFT); - - return 0; -} - -static int rtl8367b_get_mib_counter(struct rtl8366_smi *smi, int counter, - int port, unsigned long long *val) -{ - struct rtl8366_mib_counter *mib; - int offset; - int i; - int err; - u32 addr, data; - u64 mibvalue; - - if (port > RTL8367B_NUM_PORTS || - counter >= RTL8367B_NUM_MIB_COUNTERS) - return -EINVAL; - - mib = &rtl8367b_mib_counters[counter]; - addr = RTL8367B_MIB_COUNTER_PORT_OFFSET * port + mib->offset; - - /* - * Writing access counter address first - * then ASIC will prepare 64bits counter wait for being retrived - */ - REG_WR(smi, RTL8367B_MIB_ADDRESS_REG, addr >> 2); - - /* read MIB control register */ - REG_RD(smi, RTL8367B_MIB_CTRL0_REG(0), &data); - - if (data & RTL8367B_MIB_CTRL0_BUSY_MASK) - return -EBUSY; - - if (data & RTL8367B_MIB_CTRL0_RESET_MASK) - return -EIO; - - if (mib->length == 4) - offset = 3; - else - offset = (mib->offset + 1) % 4; - - mibvalue = 0; - for (i = 0; i < mib->length; i++) { - REG_RD(smi, RTL8367B_MIB_COUNTER_REG(offset - i), &data); - mibvalue = (mibvalue << 16) | (data & 0xFFFF); - } - - *val = mibvalue; - return 0; -} - -static int rtl8367b_get_vlan_4k(struct rtl8366_smi *smi, u32 vid, - struct rtl8366_vlan_4k *vlan4k) -{ - u32 data[RTL8367B_TA_VLAN_NUM_WORDS]; - int err; - int i; - - memset(vlan4k, '\0', sizeof(struct rtl8366_vlan_4k)); - - if (vid >= RTL8367B_NUM_VIDS) - return -EINVAL; - - /* write VID */ - REG_WR(smi, RTL8367B_TA_ADDR_REG, vid); - - /* write table access control word */ - REG_WR(smi, RTL8367B_TA_CTRL_REG, RTL8367B_TA_CTRL_CVLAN_READ); - - for (i = 0; i < ARRAY_SIZE(data); i++) - REG_RD(smi, RTL8367B_TA_RDDATA_REG(i), &data[i]); - - vlan4k->vid = vid; - vlan4k->member = (data[0] >> RTL8367B_TA_VLAN0_MEMBER_SHIFT) & - RTL8367B_TA_VLAN0_MEMBER_MASK; - vlan4k->untag = (data[0] >> RTL8367B_TA_VLAN0_UNTAG_SHIFT) & - RTL8367B_TA_VLAN0_UNTAG_MASK; - if (smi->rtl8367b_chip >= RTL8367B_CHIP_RTL8367S_VB) /* Family D */ - vlan4k->fid = (data[1] >> RTL8367D_TA_VLAN1_FID_SHIFT) & - RTL8367D_TA_VLAN1_FID_MASK; - else - vlan4k->fid = (data[1] >> RTL8367B_TA_VLAN1_FID_SHIFT) & - RTL8367B_TA_VLAN1_FID_MASK; - - return 0; -} - -static int rtl8367b_set_vlan_4k(struct rtl8366_smi *smi, - const struct rtl8366_vlan_4k *vlan4k) -{ - u32 data[RTL8367B_TA_VLAN_NUM_WORDS]; - int err; - int i; - - if (vlan4k->vid >= RTL8367B_NUM_VIDS || - vlan4k->member > RTL8367B_TA_VLAN0_MEMBER_MASK || - vlan4k->untag > RTL8367B_UNTAG_MASK || - vlan4k->fid > ((smi->rtl8367b_chip >= RTL8367B_CHIP_RTL8367S_VB) ? RTL8367D_FIDMAX : RTL8367B_FIDMAX)) - return -EINVAL; - - memset(data, 0, sizeof(data)); - - data[0] = (vlan4k->member & RTL8367B_TA_VLAN0_MEMBER_MASK) << - RTL8367B_TA_VLAN0_MEMBER_SHIFT; - data[0] |= (vlan4k->untag & RTL8367B_TA_VLAN0_UNTAG_MASK) << - RTL8367B_TA_VLAN0_UNTAG_SHIFT; - - if (smi->rtl8367b_chip >= RTL8367B_CHIP_RTL8367S_VB) /* Family D */ - data[1] = ((vlan4k->fid & RTL8367D_TA_VLAN1_FID_MASK) << - RTL8367D_TA_VLAN1_FID_SHIFT) | 12; /* ivl_svl - BIT(3), svlan_chek_ivl_svl - BIT(2) */ - else - data[1] = (vlan4k->fid & RTL8367B_TA_VLAN1_FID_MASK) << - RTL8367B_TA_VLAN1_FID_SHIFT; - - for (i = 0; i < ARRAY_SIZE(data); i++) - REG_WR(smi, RTL8367B_TA_WRDATA_REG(i), data[i]); - - /* write VID */ - if (smi->rtl8367b_chip >= RTL8367B_CHIP_RTL8367S_VB) /* Family D */ - REG_WR(smi, RTL8367B_TA_ADDR_REG, - vlan4k->vid & RTL8367D_TA_VLAN_VID_MASK); - else - REG_WR(smi, RTL8367B_TA_ADDR_REG, - vlan4k->vid & RTL8367B_TA_VLAN_VID_MASK); - - /* write table access control word */ - REG_WR(smi, RTL8367B_TA_CTRL_REG, RTL8367B_TA_CTRL_CVLAN_WRITE); - - return 0; -} - -static int rtl8367b_get_vlan_mc(struct rtl8366_smi *smi, u32 index, - struct rtl8366_vlan_mc *vlanmc) -{ - u32 data[RTL8367B_VLAN_MC_NUM_WORDS]; - int err; - int i; - - memset(vlanmc, '\0', sizeof(struct rtl8366_vlan_mc)); - - if (index >= RTL8367B_NUM_VLANS) - return -EINVAL; - - if (smi->emu_vlanmc) { /* use vlan mc emulation */ - vlanmc->vid = smi->emu_vlanmc[index].vid; - vlanmc->member = smi->emu_vlanmc[index].member; - vlanmc->fid = smi->emu_vlanmc[index].fid; - vlanmc->untag = smi->emu_vlanmc[index].untag; - return 0; - } - - for (i = 0; i < ARRAY_SIZE(data); i++) - REG_RD(smi, RTL8367B_VLAN_MC_BASE(index) + i, &data[i]); - - vlanmc->member = (data[0] >> RTL8367B_VLAN_MC0_MEMBER_SHIFT) & - RTL8367B_VLAN_MC0_MEMBER_MASK; - vlanmc->fid = (data[1] >> RTL8367B_VLAN_MC1_FID_SHIFT) & - RTL8367B_VLAN_MC1_FID_MASK; - vlanmc->vid = (data[3] >> RTL8367B_VLAN_MC3_EVID_SHIFT) & - RTL8367B_VLAN_MC3_EVID_MASK; - - return 0; -} - -static int rtl8367b_set_vlan_mc(struct rtl8366_smi *smi, u32 index, - const struct rtl8366_vlan_mc *vlanmc) -{ - u32 data[RTL8367B_VLAN_MC_NUM_WORDS]; - int err; - int i; - - if (index >= RTL8367B_NUM_VLANS || - vlanmc->vid >= RTL8367B_NUM_VIDS || - vlanmc->priority > RTL8367B_PRIORITYMAX || - vlanmc->member > RTL8367B_VLAN_MC0_MEMBER_MASK || - vlanmc->untag > RTL8367B_UNTAG_MASK || - vlanmc->fid > ((smi->rtl8367b_chip >= RTL8367B_CHIP_RTL8367S_VB) ? RTL8367D_FIDMAX : RTL8367B_FIDMAX)) - return -EINVAL; - - if (smi->emu_vlanmc) { /* use vlanmc emulation */ - smi->emu_vlanmc[index].vid = vlanmc->vid; - smi->emu_vlanmc[index].member = vlanmc->member; - smi->emu_vlanmc[index].fid = vlanmc->fid; - smi->emu_vlanmc[index].untag = vlanmc->untag; - return 0; - } - - data[0] = (vlanmc->member & RTL8367B_VLAN_MC0_MEMBER_MASK) << - RTL8367B_VLAN_MC0_MEMBER_SHIFT; - data[1] = (vlanmc->fid & RTL8367B_VLAN_MC1_FID_MASK) << - RTL8367B_VLAN_MC1_FID_SHIFT; - data[2] = 0; - data[3] = (vlanmc->vid & RTL8367B_VLAN_MC3_EVID_MASK) << - RTL8367B_VLAN_MC3_EVID_SHIFT; - - for (i = 0; i < ARRAY_SIZE(data); i++) - REG_WR(smi, RTL8367B_VLAN_MC_BASE(index) + i, data[i]); - - return 0; -} - -static int rtl8367b_get_mc_index(struct rtl8366_smi *smi, int port, int *val) -{ - u32 data; - int err; - - if (port >= RTL8367B_NUM_PORTS) - return -EINVAL; - - if (smi->rtl8367b_chip >= RTL8367B_CHIP_RTL8367S_VB) { /* Family D */ - int i; - struct rtl8366_vlan_mc vlanmc; - - err = rtl8366_smi_read_reg(smi, RTL8367D_VLAN_PVID_CTRL_REG(port), &data); - - if (err) { - dev_err(smi->parent, "read pvid register 0x%04x fail", RTL8367D_VLAN_PVID_CTRL_REG(port)); - return err; - } - - data &= RTL8367D_VLAN_PVID_CTRL_MASK; - for (i = 0; i < smi->num_vlan_mc; i++) { - err = rtl8367b_get_vlan_mc(smi, i, &vlanmc); - - if (err) { - dev_err(smi->parent, "get vlan mc index %d fail", i); - return err; - } - - if (data == vlanmc.vid) break; - } - - if (i < smi->num_vlan_mc) { - *val = i; - } else { - dev_err(smi->parent, "vlan mc index for pvid %d not found", data); - return -EINVAL; - } - } else { - REG_RD(smi, RTL8367B_VLAN_PVID_CTRL_REG(port), &data); - - *val = (data >> RTL8367B_VLAN_PVID_CTRL_SHIFT(port)) & - RTL8367B_VLAN_PVID_CTRL_MASK; - } - - return 0; -} - -static int rtl8367b_set_mc_index(struct rtl8366_smi *smi, int port, int index) -{ - if (port >= RTL8367B_NUM_PORTS || index >= RTL8367B_NUM_VLANS) - return -EINVAL; - - if (smi->rtl8367b_chip >= RTL8367B_CHIP_RTL8367S_VB) { /* Family D */ - int pvid, err; - struct rtl8366_vlan_mc vlanmc; - - err = rtl8367b_get_vlan_mc(smi, index, &vlanmc); - - if (err) { - dev_err(smi->parent, "get vlan mc index %d fail", index); - return err; - } - - pvid = vlanmc.vid & RTL8367D_VLAN_PVID_CTRL_MASK; - err = rtl8366_smi_write_reg(smi, RTL8367D_VLAN_PVID_CTRL_REG(port), pvid); - - if (err) { - dev_err(smi->parent, "set port %d pvid %d fail", port, pvid); - return err; - } - - return 0; - } else - return rtl8366_smi_rmwr(smi, RTL8367B_VLAN_PVID_CTRL_REG(port), - RTL8367B_VLAN_PVID_CTRL_MASK << - RTL8367B_VLAN_PVID_CTRL_SHIFT(port), - (index & RTL8367B_VLAN_PVID_CTRL_MASK) << - RTL8367B_VLAN_PVID_CTRL_SHIFT(port)); -} - -static int rtl8367b_enable_vlan(struct rtl8366_smi *smi, int enable) -{ - return rtl8366_smi_rmwr(smi, RTL8367B_VLAN_CTRL_REG, - RTL8367B_VLAN_CTRL_ENABLE, - (enable) ? RTL8367B_VLAN_CTRL_ENABLE : 0); -} - -static int rtl8367b_enable_vlan4k(struct rtl8366_smi *smi, int enable) -{ - return 0; -} - -static int rtl8367b_is_vlan_valid(struct rtl8366_smi *smi, unsigned vlan) -{ - unsigned max = RTL8367B_NUM_VLANS; - - if (smi->vlan4k_enabled) - max = RTL8367B_NUM_VIDS - 1; - - if (vlan == 0 || vlan >= max) - return 0; - - return 1; -} - -static int rtl8367b_enable_port(struct rtl8366_smi *smi, int port, int enable) -{ - int err; - - REG_WR(smi, RTL8367B_PORT_ISOLATION_REG(port), - (enable) ? RTL8367B_PORTS_ALL : 0); - - return 0; -} - -static int rtl8367b_sw_reset_mibs(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val) -{ - struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev); - - return rtl8366_smi_rmwr(smi, RTL8367B_MIB_CTRL0_REG(0), 0, - RTL8367B_MIB_CTRL0_GLOBAL_RESET_MASK); -} - -static int rtl8367b_sw_get_port_link(struct switch_dev *dev, - int port, - struct switch_port_link *link) -{ - struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev); - u32 data = 0; - u32 speed; - - if (port >= RTL8367B_NUM_PORTS) - return -EINVAL; - - if (smi->rtl8367b_chip >= RTL8367B_CHIP_RTL8367S_VB) /* Family D */ - rtl8366_smi_read_reg(smi, RTL8367D_PORT_STATUS_REG(port), &data); - else - rtl8366_smi_read_reg(smi, RTL8367B_PORT_STATUS_REG(port), &data); - - link->link = !!(data & RTL8367B_PORT_STATUS_LINK); - if (!link->link) - return 0; - - link->duplex = !!(data & RTL8367B_PORT_STATUS_DUPLEX); - link->rx_flow = !!(data & RTL8367B_PORT_STATUS_RXPAUSE); - link->tx_flow = !!(data & RTL8367B_PORT_STATUS_TXPAUSE); - link->aneg = !!(data & RTL8367B_PORT_STATUS_NWAY); - - if (smi->rtl8367b_chip >= RTL8367B_CHIP_RTL8367S_VB) /* Family D */ - speed = (data & RTL8367B_PORT_STATUS_SPEED_MASK) | ((data & RTL8367D_PORT_STATUS_SPEED1_MASK) >> RTL8367D_PORT_STATUS_SPEED1_SHIFT); - else - speed = (data & RTL8367B_PORT_STATUS_SPEED_MASK); - switch (speed) { - case RTL8367B_PORT_STATUS_SPEED_10: - link->speed = SWITCH_PORT_SPEED_10; - break; - case RTL8367B_PORT_STATUS_SPEED_100: - link->speed = SWITCH_PORT_SPEED_100; - break; - case RTL8367B_PORT_STATUS_SPEED_1000: - link->speed = SWITCH_PORT_SPEED_1000; - break; - default: - link->speed = SWITCH_PORT_SPEED_UNKNOWN; - break; - } - - return 0; -} - -static int rtl8367b_sw_get_max_length(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val) -{ - struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev); - u32 data; - - rtl8366_smi_read_reg(smi, RTL8367B_SWC0_REG, &data); - val->value.i = (data & RTL8367B_SWC0_MAX_LENGTH_MASK) >> - RTL8367B_SWC0_MAX_LENGTH_SHIFT; - - return 0; -} - -static int rtl8367b_sw_set_max_length(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val) -{ - struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev); - u32 max_len; - - switch (val->value.i) { - case 0: - max_len = RTL8367B_SWC0_MAX_LENGTH_1522; - break; - case 1: - max_len = RTL8367B_SWC0_MAX_LENGTH_1536; - break; - case 2: - max_len = RTL8367B_SWC0_MAX_LENGTH_1552; - break; - case 3: - max_len = RTL8367B_SWC0_MAX_LENGTH_16000; - break; - default: - return -EINVAL; - } - - return rtl8366_smi_rmwr(smi, RTL8367B_SWC0_REG, - RTL8367B_SWC0_MAX_LENGTH_MASK, max_len); -} - - -static int rtl8367b_sw_reset_port_mibs(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val) -{ - struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev); - int port; - - port = val->port_vlan; - if (port >= RTL8367B_NUM_PORTS) - return -EINVAL; - - return rtl8366_smi_rmwr(smi, RTL8367B_MIB_CTRL0_REG(port / 8), 0, - RTL8367B_MIB_CTRL0_PORT_RESET_MASK(port % 8)); -} - -static int rtl8367b_sw_get_port_stats(struct switch_dev *dev, int port, - struct switch_port_stats *stats) -{ - return (rtl8366_sw_get_port_stats(dev, port, stats, - RTL8367B_MIB_TXB_ID, RTL8367B_MIB_RXB_ID)); -} - -static struct switch_attr rtl8367b_globals[] = { - { - .type = SWITCH_TYPE_INT, - .name = "enable_vlan", - .description = "Enable VLAN mode", - .set = rtl8366_sw_set_vlan_enable, - .get = rtl8366_sw_get_vlan_enable, - .max = 1, - .ofs = 1 - }, { - .type = SWITCH_TYPE_INT, - .name = "enable_vlan4k", - .description = "Enable VLAN 4K mode", - .set = rtl8366_sw_set_vlan_enable, - .get = rtl8366_sw_get_vlan_enable, - .max = 1, - .ofs = 2 - }, { - .type = SWITCH_TYPE_NOVAL, - .name = "reset_mibs", - .description = "Reset all MIB counters", - .set = rtl8367b_sw_reset_mibs, - }, { - .type = SWITCH_TYPE_INT, - .name = "max_length", - .description = "Get/Set the maximum length of valid packets" - "(0:1522, 1:1536, 2:1552, 3:16000)", - .set = rtl8367b_sw_set_max_length, - .get = rtl8367b_sw_get_max_length, - .max = 3, - } -}; - -static struct switch_attr rtl8367b_port[] = { - { - .type = SWITCH_TYPE_NOVAL, - .name = "reset_mib", - .description = "Reset single port MIB counters", - .set = rtl8367b_sw_reset_port_mibs, - }, { - .type = SWITCH_TYPE_STRING, - .name = "mib", - .description = "Get MIB counters for port", - .max = 33, - .set = NULL, - .get = rtl8366_sw_get_port_mib, - }, -}; - -static struct switch_attr rtl8367b_vlan[] = { - { - .type = SWITCH_TYPE_STRING, - .name = "info", - .description = "Get vlan information", - .max = 1, - .set = NULL, - .get = rtl8366_sw_get_vlan_info, - }, -}; - -static const struct switch_dev_ops rtl8367b_sw_ops = { - .attr_global = { - .attr = rtl8367b_globals, - .n_attr = ARRAY_SIZE(rtl8367b_globals), - }, - .attr_port = { - .attr = rtl8367b_port, - .n_attr = ARRAY_SIZE(rtl8367b_port), - }, - .attr_vlan = { - .attr = rtl8367b_vlan, - .n_attr = ARRAY_SIZE(rtl8367b_vlan), - }, - - .get_vlan_ports = rtl8366_sw_get_vlan_ports, - .set_vlan_ports = rtl8366_sw_set_vlan_ports, - .get_port_pvid = rtl8366_sw_get_port_pvid, - .set_port_pvid = rtl8366_sw_set_port_pvid, - .reset_switch = rtl8366_sw_reset_switch, - .get_port_link = rtl8367b_sw_get_port_link, - .get_port_stats = rtl8367b_sw_get_port_stats, -}; - -static int rtl8367b_switch_init(struct rtl8366_smi *smi) -{ - struct switch_dev *dev = &smi->sw_dev; - int err; - - dev->name = "RTL8367B"; - dev->cpu_port = smi->cpu_port; - dev->ports = RTL8367B_NUM_PORTS; - dev->vlans = RTL8367B_NUM_VIDS; - dev->ops = &rtl8367b_sw_ops; - dev->alias = dev_name(smi->parent); - - err = register_switch(dev, NULL); - if (err) - dev_err(smi->parent, "switch registration failed\n"); - - return err; -} - -static void rtl8367b_switch_cleanup(struct rtl8366_smi *smi) -{ - unregister_switch(&smi->sw_dev); -} - -static int rtl8367b_mii_read(struct mii_bus *bus, int addr, int reg) -{ - struct rtl8366_smi *smi = bus->priv; - u32 val = 0; - int err; - - err = rtl8367b_read_phy_reg(smi, addr, reg, &val); - if (err) - return 0xffff; - - return val; -} - -static int rtl8367b_mii_write(struct mii_bus *bus, int addr, int reg, u16 val) -{ - struct rtl8366_smi *smi = bus->priv; - u32 t; - int err; - - err = rtl8367b_write_phy_reg(smi, addr, reg, val); - if (err) - return err; - - /* flush write */ - (void) rtl8367b_read_phy_reg(smi, addr, reg, &t); - - return err; -} - -static int rtl8367b_detect(struct rtl8366_smi *smi) -{ - const char *chip_name = NULL; - u32 chip_num; - u32 chip_ver; - int ret; - - smi->emu_vlanmc = NULL; - smi->rtl8367b_chip = RTL8367B_CHIP_UNKNOWN; - - rtl8366_smi_write_reg(smi, RTL8367B_RTL_MAGIC_ID_REG, - RTL8367B_RTL_MAGIC_ID_VAL); - - ret = rtl8366_smi_read_reg(smi, RTL8367B_CHIP_NUMBER_REG, &chip_num); - if (ret) { - dev_err(smi->parent, "unable to read %s register\n", - "chip number"); - return ret; - } - - ret = rtl8366_smi_read_reg(smi, RTL8367B_CHIP_VER_REG, &chip_ver); - if (ret) { - dev_err(smi->parent, "unable to read %s register\n", - "chip version"); - return ret; - } - - switch (chip_ver) { - case 0x0010: - if (chip_num == 0x6642) { - chip_name = "8367S-VB"; - smi->rtl8367b_chip = RTL8367B_CHIP_RTL8367S_VB; - } - break; - case 0x0020: - if (chip_num == 0x6367) { - chip_name = "8367RB-VB"; - smi->rtl8367b_chip = RTL8367B_CHIP_RTL8367RB_VB; - } - break; - case 0x00A0: - if (chip_num == 0x6367) { - chip_name = "8367S"; - smi->rtl8367b_chip = RTL8367B_CHIP_RTL8367S; - } - break; - case 0x1000: - chip_name = "8367RB"; - smi->rtl8367b_chip = RTL8367B_CHIP_RTL8367RB; - break; - case 0x1010: - chip_name = "8367R-VB"; - smi->rtl8367b_chip = RTL8367B_CHIP_RTL8367R_VB; - } - - if (!chip_name) { - dev_err(smi->parent, - "unknown chip (num:%04x ver:%04x)\n", - chip_num, chip_ver); - return -ENODEV; - } - - dev_info(smi->parent, "RTL%s chip found (num:%04x ver:%04x)\n", chip_name, chip_num, chip_ver); - - return 0; -} - -static struct rtl8366_smi_ops rtl8367b_smi_ops = { - .detect = rtl8367b_detect, - .reset_chip = rtl8367b_reset_chip, - .setup = rtl8367b_setup, - - .mii_read = rtl8367b_mii_read, - .mii_write = rtl8367b_mii_write, - - .get_vlan_mc = rtl8367b_get_vlan_mc, - .set_vlan_mc = rtl8367b_set_vlan_mc, - .get_vlan_4k = rtl8367b_get_vlan_4k, - .set_vlan_4k = rtl8367b_set_vlan_4k, - .get_mc_index = rtl8367b_get_mc_index, - .set_mc_index = rtl8367b_set_mc_index, - .get_mib_counter = rtl8367b_get_mib_counter, - .is_vlan_valid = rtl8367b_is_vlan_valid, - .enable_vlan = rtl8367b_enable_vlan, - .enable_vlan4k = rtl8367b_enable_vlan4k, - .enable_port = rtl8367b_enable_port, -}; - -static int rtl8367b_probe(struct platform_device *pdev) -{ - struct rtl8366_smi *smi; - int err; - - smi = rtl8366_smi_probe(pdev); - if (IS_ERR(smi)) - return PTR_ERR(smi); - - smi->clk_delay = 1500; - smi->cmd_read = 0xb9; - smi->cmd_write = 0xb8; - smi->ops = &rtl8367b_smi_ops; - smi->num_ports = RTL8367B_NUM_PORTS; - smi->cpu_port = UINT_MAX; /* not defined yet */ - smi->num_vlan_mc = RTL8367B_NUM_VLANS; - smi->mib_counters = rtl8367b_mib_counters; - smi->num_mib_counters = ARRAY_SIZE(rtl8367b_mib_counters); - - err = rtl8366_smi_init(smi); - if (err) - goto err_free_smi; - - platform_set_drvdata(pdev, smi); - - err = rtl8367b_switch_init(smi); - if (err) - goto err_clear_drvdata; - - return 0; - - err_clear_drvdata: - platform_set_drvdata(pdev, NULL); - rtl8366_smi_cleanup(smi); - err_free_smi: - if (smi->emu_vlanmc) - kfree(smi->emu_vlanmc); - kfree(smi); - return err; -} - -static int rtl8367b_remove(struct platform_device *pdev) -{ - struct rtl8366_smi *smi = platform_get_drvdata(pdev); - - if (smi) { - rtl8367b_switch_cleanup(smi); - platform_set_drvdata(pdev, NULL); - rtl8366_smi_cleanup(smi); - kfree(smi); - } - - return 0; -} - -static void rtl8367b_shutdown(struct platform_device *pdev) -{ - struct rtl8366_smi *smi = platform_get_drvdata(pdev); - - if (smi) - rtl8367b_reset_chip(smi); -} - -#ifdef CONFIG_OF -static const struct of_device_id rtl8367b_match[] = { - { .compatible = "realtek,rtl8367b" }, - {}, -}; -MODULE_DEVICE_TABLE(of, rtl8367b_match); -#endif - -static struct platform_driver rtl8367b_driver = { - .driver = { - .name = RTL8367B_DRIVER_NAME, - .owner = THIS_MODULE, -#ifdef CONFIG_OF - .of_match_table = of_match_ptr(rtl8367b_match), -#endif - }, - .probe = rtl8367b_probe, - .remove = rtl8367b_remove, - .shutdown = rtl8367b_shutdown, -}; - -module_platform_driver(rtl8367b_driver); - -MODULE_DESCRIPTION("Realtek RTL8367B ethernet switch driver"); -MODULE_AUTHOR("Gabor Juhos "); -MODULE_LICENSE("GPL v2"); -MODULE_ALIAS("platform:" RTL8367B_DRIVER_NAME); - diff --git a/target/linux/generic/files-6.12/drivers/net/phy/swconfig.c b/target/linux/generic/files-6.12/drivers/net/phy/swconfig.c deleted file mode 100644 index 10dc8d0607aa93..00000000000000 --- a/target/linux/generic/files-6.12/drivers/net/phy/swconfig.c +++ /dev/null @@ -1,1242 +0,0 @@ -/* - * swconfig.c: Switch configuration API - * - * Copyright (C) 2008 Felix Fietkau - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define SWCONFIG_DEVNAME "switch%d" - -#include "swconfig_leds.c" - -MODULE_AUTHOR("Felix Fietkau "); -MODULE_LICENSE("GPL"); - -static int swdev_id; -static struct list_head swdevs; -static DEFINE_MUTEX(swdevs_lock); -struct swconfig_callback; - -struct swconfig_callback { - struct sk_buff *msg; - struct genlmsghdr *hdr; - struct genl_info *info; - int cmd; - - /* callback for filling in the message data */ - int (*fill)(struct swconfig_callback *cb, void *arg); - - /* callback for closing the message before sending it */ - int (*close)(struct swconfig_callback *cb, void *arg); - - struct nlattr *nest[4]; - int args[4]; -}; - -/* defaults */ - -static int -swconfig_get_vlan_ports(struct switch_dev *dev, const struct switch_attr *attr, - struct switch_val *val) -{ - int ret; - if (val->port_vlan >= dev->vlans) - return -EINVAL; - - if (!dev->ops->get_vlan_ports) - return -EOPNOTSUPP; - - ret = dev->ops->get_vlan_ports(dev, val); - return ret; -} - -static int -swconfig_set_vlan_ports(struct switch_dev *dev, const struct switch_attr *attr, - struct switch_val *val) -{ - struct switch_port *ports = val->value.ports; - const struct switch_dev_ops *ops = dev->ops; - int i; - - if (val->port_vlan >= dev->vlans) - return -EINVAL; - - /* validate ports */ - if (val->len > dev->ports) - return -EINVAL; - - if (!ops->set_vlan_ports) - return -EOPNOTSUPP; - - for (i = 0; i < val->len; i++) { - if (ports[i].id >= dev->ports) - return -EINVAL; - - if (ops->set_port_pvid && - !(ports[i].flags & (1 << SWITCH_PORT_FLAG_TAGGED))) - ops->set_port_pvid(dev, ports[i].id, val->port_vlan); - } - - return ops->set_vlan_ports(dev, val); -} - -static int -swconfig_set_pvid(struct switch_dev *dev, const struct switch_attr *attr, - struct switch_val *val) -{ - if (val->port_vlan >= dev->ports) - return -EINVAL; - - if (!dev->ops->set_port_pvid) - return -EOPNOTSUPP; - - return dev->ops->set_port_pvid(dev, val->port_vlan, val->value.i); -} - -static int -swconfig_get_pvid(struct switch_dev *dev, const struct switch_attr *attr, - struct switch_val *val) -{ - if (val->port_vlan >= dev->ports) - return -EINVAL; - - if (!dev->ops->get_port_pvid) - return -EOPNOTSUPP; - - return dev->ops->get_port_pvid(dev, val->port_vlan, &val->value.i); -} - -static int -swconfig_set_link(struct switch_dev *dev, const struct switch_attr *attr, - struct switch_val *val) -{ - if (!dev->ops->set_port_link) - return -EOPNOTSUPP; - - return dev->ops->set_port_link(dev, val->port_vlan, val->value.link); -} - -static int -swconfig_get_link(struct switch_dev *dev, const struct switch_attr *attr, - struct switch_val *val) -{ - struct switch_port_link *link = val->value.link; - - if (val->port_vlan >= dev->ports) - return -EINVAL; - - if (!dev->ops->get_port_link) - return -EOPNOTSUPP; - - memset(link, 0, sizeof(*link)); - return dev->ops->get_port_link(dev, val->port_vlan, link); -} - -static int -swconfig_apply_config(struct switch_dev *dev, const struct switch_attr *attr, - struct switch_val *val) -{ - /* don't complain if not supported by the switch driver */ - if (!dev->ops->apply_config) - return 0; - - return dev->ops->apply_config(dev); -} - -static int -swconfig_reset_switch(struct switch_dev *dev, const struct switch_attr *attr, - struct switch_val *val) -{ - /* don't complain if not supported by the switch driver */ - if (!dev->ops->reset_switch) - return 0; - - return dev->ops->reset_switch(dev); -} - -enum global_defaults { - GLOBAL_APPLY, - GLOBAL_RESET, -}; - -enum vlan_defaults { - VLAN_PORTS, -}; - -enum port_defaults { - PORT_PVID, - PORT_LINK, -}; - -static struct switch_attr default_global[] = { - [GLOBAL_APPLY] = { - .type = SWITCH_TYPE_NOVAL, - .name = "apply", - .description = "Activate changes in the hardware", - .set = swconfig_apply_config, - }, - [GLOBAL_RESET] = { - .type = SWITCH_TYPE_NOVAL, - .name = "reset", - .description = "Reset the switch", - .set = swconfig_reset_switch, - } -}; - -static struct switch_attr default_port[] = { - [PORT_PVID] = { - .type = SWITCH_TYPE_INT, - .name = "pvid", - .description = "Primary VLAN ID", - .set = swconfig_set_pvid, - .get = swconfig_get_pvid, - }, - [PORT_LINK] = { - .type = SWITCH_TYPE_LINK, - .name = "link", - .description = "Get port link information", - .set = swconfig_set_link, - .get = swconfig_get_link, - } -}; - -static struct switch_attr default_vlan[] = { - [VLAN_PORTS] = { - .type = SWITCH_TYPE_PORTS, - .name = "ports", - .description = "VLAN port mapping", - .set = swconfig_set_vlan_ports, - .get = swconfig_get_vlan_ports, - }, -}; - -static const struct switch_attr * -swconfig_find_attr_by_name(const struct switch_attrlist *alist, - const char *name) -{ - int i; - - for (i = 0; i < alist->n_attr; i++) - if (strcmp(name, alist->attr[i].name) == 0) - return &alist->attr[i]; - - return NULL; -} - -static void swconfig_defaults_init(struct switch_dev *dev) -{ - const struct switch_dev_ops *ops = dev->ops; - - dev->def_global = 0; - dev->def_vlan = 0; - dev->def_port = 0; - - if (ops->get_vlan_ports || ops->set_vlan_ports) - set_bit(VLAN_PORTS, &dev->def_vlan); - - if (ops->get_port_pvid || ops->set_port_pvid) - set_bit(PORT_PVID, &dev->def_port); - - if (ops->get_port_link && - !swconfig_find_attr_by_name(&ops->attr_port, "link")) - set_bit(PORT_LINK, &dev->def_port); - - /* always present, can be no-op */ - set_bit(GLOBAL_APPLY, &dev->def_global); - set_bit(GLOBAL_RESET, &dev->def_global); -} - - -static struct genl_family switch_fam; - -static const struct nla_policy switch_policy[SWITCH_ATTR_MAX+1] = { - [SWITCH_ATTR_ID] = { .type = NLA_U32 }, - [SWITCH_ATTR_OP_ID] = { .type = NLA_U32 }, - [SWITCH_ATTR_OP_PORT] = { .type = NLA_U32 }, - [SWITCH_ATTR_OP_VLAN] = { .type = NLA_U32 }, - [SWITCH_ATTR_OP_VALUE_INT] = { .type = NLA_U32 }, - [SWITCH_ATTR_OP_VALUE_STR] = { .type = NLA_NUL_STRING }, - [SWITCH_ATTR_OP_VALUE_PORTS] = { .type = NLA_NESTED }, - [SWITCH_ATTR_TYPE] = { .type = NLA_U32 }, -}; - -static const struct nla_policy port_policy[SWITCH_PORT_ATTR_MAX+1] = { - [SWITCH_PORT_ID] = { .type = NLA_U32 }, - [SWITCH_PORT_FLAG_TAGGED] = { .type = NLA_FLAG }, -}; - -static struct nla_policy link_policy[SWITCH_LINK_ATTR_MAX] = { - [SWITCH_LINK_FLAG_DUPLEX] = { .type = NLA_FLAG }, - [SWITCH_LINK_FLAG_ANEG] = { .type = NLA_FLAG }, - [SWITCH_LINK_SPEED] = { .type = NLA_U32 }, -}; - -static inline void -swconfig_lock(void) -{ - mutex_lock(&swdevs_lock); -} - -static inline void -swconfig_unlock(void) -{ - mutex_unlock(&swdevs_lock); -} - -static struct switch_dev * -swconfig_get_dev(struct genl_info *info) -{ - struct switch_dev *dev = NULL; - struct switch_dev *p; - int id; - - if (!info->attrs[SWITCH_ATTR_ID]) - goto done; - - id = nla_get_u32(info->attrs[SWITCH_ATTR_ID]); - swconfig_lock(); - list_for_each_entry(p, &swdevs, dev_list) { - if (id != p->id) - continue; - - dev = p; - break; - } - if (dev) - mutex_lock(&dev->sw_mutex); - else - pr_debug("device %d not found\n", id); - swconfig_unlock(); -done: - return dev; -} - -static inline void -swconfig_put_dev(struct switch_dev *dev) -{ - mutex_unlock(&dev->sw_mutex); -} - -static int -swconfig_dump_attr(struct swconfig_callback *cb, void *arg) -{ - struct switch_attr *op = arg; - struct genl_info *info = cb->info; - struct sk_buff *msg = cb->msg; - int id = cb->args[0]; - void *hdr; - - hdr = genlmsg_put(msg, info->snd_portid, info->snd_seq, &switch_fam, - NLM_F_MULTI, SWITCH_CMD_NEW_ATTR); - if (IS_ERR(hdr)) - return -1; - - if (nla_put_u32(msg, SWITCH_ATTR_OP_ID, id)) - goto nla_put_failure; - if (nla_put_u32(msg, SWITCH_ATTR_OP_TYPE, op->type)) - goto nla_put_failure; - if (nla_put_string(msg, SWITCH_ATTR_OP_NAME, op->name)) - goto nla_put_failure; - if (op->description) - if (nla_put_string(msg, SWITCH_ATTR_OP_DESCRIPTION, - op->description)) - goto nla_put_failure; - - genlmsg_end(msg, hdr); - return msg->len; -nla_put_failure: - genlmsg_cancel(msg, hdr); - return -EMSGSIZE; -} - -/* spread multipart messages across multiple message buffers */ -static int -swconfig_send_multipart(struct swconfig_callback *cb, void *arg) -{ - struct genl_info *info = cb->info; - int restart = 0; - int err; - - do { - if (!cb->msg) { - cb->msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); - if (cb->msg == NULL) - goto error; - } - - if (!(cb->fill(cb, arg) < 0)) - break; - - /* fill failed, check if this was already the second attempt */ - if (restart) - goto error; - - /* try again in a new message, send the current one */ - restart = 1; - if (cb->close) { - if (cb->close(cb, arg) < 0) - goto error; - } - err = genlmsg_reply(cb->msg, info); - cb->msg = NULL; - if (err < 0) - goto error; - - } while (restart); - - return 0; - -error: - if (cb->msg) - nlmsg_free(cb->msg); - return -1; -} - -static int -swconfig_list_attrs(struct sk_buff *skb, struct genl_info *info) -{ - struct genlmsghdr *hdr = nlmsg_data(info->nlhdr); - const struct switch_attrlist *alist; - struct switch_dev *dev; - struct swconfig_callback cb; - int err = -EINVAL; - int i; - - /* defaults */ - struct switch_attr *def_list; - unsigned long *def_active; - int n_def; - - dev = swconfig_get_dev(info); - if (!dev) - return -EINVAL; - - switch (hdr->cmd) { - case SWITCH_CMD_LIST_GLOBAL: - alist = &dev->ops->attr_global; - def_list = default_global; - def_active = &dev->def_global; - n_def = ARRAY_SIZE(default_global); - break; - case SWITCH_CMD_LIST_VLAN: - alist = &dev->ops->attr_vlan; - def_list = default_vlan; - def_active = &dev->def_vlan; - n_def = ARRAY_SIZE(default_vlan); - break; - case SWITCH_CMD_LIST_PORT: - alist = &dev->ops->attr_port; - def_list = default_port; - def_active = &dev->def_port; - n_def = ARRAY_SIZE(default_port); - break; - default: - WARN_ON(1); - goto out; - } - - memset(&cb, 0, sizeof(cb)); - cb.info = info; - cb.fill = swconfig_dump_attr; - for (i = 0; i < alist->n_attr; i++) { - if (alist->attr[i].disabled) - continue; - cb.args[0] = i; - err = swconfig_send_multipart(&cb, (void *) &alist->attr[i]); - if (err < 0) - goto error; - } - - /* defaults */ - for (i = 0; i < n_def; i++) { - if (!test_bit(i, def_active)) - continue; - cb.args[0] = SWITCH_ATTR_DEFAULTS_OFFSET + i; - err = swconfig_send_multipart(&cb, (void *) &def_list[i]); - if (err < 0) - goto error; - } - swconfig_put_dev(dev); - - if (!cb.msg) - return 0; - - return genlmsg_reply(cb.msg, info); - -error: - if (cb.msg) - nlmsg_free(cb.msg); -out: - swconfig_put_dev(dev); - return err; -} - -static const struct switch_attr * -swconfig_lookup_attr(struct switch_dev *dev, struct genl_info *info, - struct switch_val *val) -{ - struct genlmsghdr *hdr = nlmsg_data(info->nlhdr); - const struct switch_attrlist *alist; - const struct switch_attr *attr = NULL; - unsigned int attr_id; - - /* defaults */ - struct switch_attr *def_list; - unsigned long *def_active; - int n_def; - - if (!info->attrs[SWITCH_ATTR_OP_ID]) - goto done; - - switch (hdr->cmd) { - case SWITCH_CMD_SET_GLOBAL: - case SWITCH_CMD_GET_GLOBAL: - alist = &dev->ops->attr_global; - def_list = default_global; - def_active = &dev->def_global; - n_def = ARRAY_SIZE(default_global); - break; - case SWITCH_CMD_SET_VLAN: - case SWITCH_CMD_GET_VLAN: - alist = &dev->ops->attr_vlan; - def_list = default_vlan; - def_active = &dev->def_vlan; - n_def = ARRAY_SIZE(default_vlan); - if (!info->attrs[SWITCH_ATTR_OP_VLAN]) - goto done; - val->port_vlan = nla_get_u32(info->attrs[SWITCH_ATTR_OP_VLAN]); - if (val->port_vlan >= dev->vlans) - goto done; - break; - case SWITCH_CMD_SET_PORT: - case SWITCH_CMD_GET_PORT: - alist = &dev->ops->attr_port; - def_list = default_port; - def_active = &dev->def_port; - n_def = ARRAY_SIZE(default_port); - if (!info->attrs[SWITCH_ATTR_OP_PORT]) - goto done; - val->port_vlan = nla_get_u32(info->attrs[SWITCH_ATTR_OP_PORT]); - if (val->port_vlan >= dev->ports) - goto done; - break; - default: - WARN_ON(1); - goto done; - } - - if (!alist) - goto done; - - attr_id = nla_get_u32(info->attrs[SWITCH_ATTR_OP_ID]); - if (attr_id >= SWITCH_ATTR_DEFAULTS_OFFSET) { - attr_id -= SWITCH_ATTR_DEFAULTS_OFFSET; - if (attr_id >= n_def) - goto done; - if (!test_bit(attr_id, def_active)) - goto done; - attr = &def_list[attr_id]; - } else { - if (attr_id >= alist->n_attr) - goto done; - attr = &alist->attr[attr_id]; - } - - if (attr->disabled) - attr = NULL; - -done: - if (!attr) - pr_debug("attribute lookup failed\n"); - val->attr = attr; - return attr; -} - -static int -swconfig_parse_ports(struct sk_buff *msg, struct nlattr *head, - struct switch_val *val, int max) -{ - struct nlattr *nla; - int rem; - - val->len = 0; - nla_for_each_nested(nla, head, rem) { - struct nlattr *tb[SWITCH_PORT_ATTR_MAX+1]; - struct switch_port *port; - - if (val->len >= max) - return -EINVAL; - - port = &val->value.ports[val->len]; - - if (nla_parse_nested_deprecated(tb, SWITCH_PORT_ATTR_MAX, nla, - port_policy, NULL)) - return -EINVAL; - - if (!tb[SWITCH_PORT_ID]) - return -EINVAL; - - port->id = nla_get_u32(tb[SWITCH_PORT_ID]); - if (tb[SWITCH_PORT_FLAG_TAGGED]) - port->flags |= (1 << SWITCH_PORT_FLAG_TAGGED); - val->len++; - } - - return 0; -} - -static int -swconfig_parse_link(struct sk_buff *msg, struct nlattr *nla, - struct switch_port_link *link) -{ - struct nlattr *tb[SWITCH_LINK_ATTR_MAX + 1]; - - if (nla_parse_nested_deprecated(tb, SWITCH_LINK_ATTR_MAX, nla, link_policy, NULL)) - return -EINVAL; - - link->duplex = !!tb[SWITCH_LINK_FLAG_DUPLEX]; - link->aneg = !!tb[SWITCH_LINK_FLAG_ANEG]; - link->speed = nla_get_u32(tb[SWITCH_LINK_SPEED]); - - return 0; -} - -static int -swconfig_set_attr(struct sk_buff *skb, struct genl_info *info) -{ - const struct switch_attr *attr; - struct switch_dev *dev; - struct switch_val val; - int err = -EINVAL; - - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - dev = swconfig_get_dev(info); - if (!dev) - return -EINVAL; - - memset(&val, 0, sizeof(val)); - attr = swconfig_lookup_attr(dev, info, &val); - if (!attr || !attr->set) - goto error; - - val.attr = attr; - switch (attr->type) { - case SWITCH_TYPE_NOVAL: - break; - case SWITCH_TYPE_INT: - if (!info->attrs[SWITCH_ATTR_OP_VALUE_INT]) - goto error; - val.value.i = - nla_get_u32(info->attrs[SWITCH_ATTR_OP_VALUE_INT]); - break; - case SWITCH_TYPE_STRING: - if (!info->attrs[SWITCH_ATTR_OP_VALUE_STR]) - goto error; - val.value.s = - nla_data(info->attrs[SWITCH_ATTR_OP_VALUE_STR]); - break; - case SWITCH_TYPE_PORTS: - val.value.ports = dev->portbuf; - memset(dev->portbuf, 0, - sizeof(struct switch_port) * dev->ports); - - /* TODO: implement multipart? */ - if (info->attrs[SWITCH_ATTR_OP_VALUE_PORTS]) { - err = swconfig_parse_ports(skb, - info->attrs[SWITCH_ATTR_OP_VALUE_PORTS], - &val, dev->ports); - if (err < 0) - goto error; - } else { - val.len = 0; - err = 0; - } - break; - case SWITCH_TYPE_LINK: - val.value.link = &dev->linkbuf; - memset(&dev->linkbuf, 0, sizeof(struct switch_port_link)); - - if (info->attrs[SWITCH_ATTR_OP_VALUE_LINK]) { - err = swconfig_parse_link(skb, - info->attrs[SWITCH_ATTR_OP_VALUE_LINK], - val.value.link); - if (err < 0) - goto error; - } else { - val.len = 0; - err = 0; - } - break; - default: - goto error; - } - - err = attr->set(dev, attr, &val); -error: - swconfig_put_dev(dev); - return err; -} - -static int -swconfig_close_portlist(struct swconfig_callback *cb, void *arg) -{ - if (cb->nest[0]) - nla_nest_end(cb->msg, cb->nest[0]); - return 0; -} - -static int -swconfig_send_port(struct swconfig_callback *cb, void *arg) -{ - const struct switch_port *port = arg; - struct nlattr *p = NULL; - - if (!cb->nest[0]) { - cb->nest[0] = nla_nest_start(cb->msg, cb->cmd); - if (!cb->nest[0]) - return -1; - } - - p = nla_nest_start(cb->msg, SWITCH_ATTR_PORT); - if (!p) - goto error; - - if (nla_put_u32(cb->msg, SWITCH_PORT_ID, port->id)) - goto nla_put_failure; - if (port->flags & (1 << SWITCH_PORT_FLAG_TAGGED)) { - if (nla_put_flag(cb->msg, SWITCH_PORT_FLAG_TAGGED)) - goto nla_put_failure; - } - - nla_nest_end(cb->msg, p); - return 0; - -nla_put_failure: - nla_nest_cancel(cb->msg, p); -error: - nla_nest_cancel(cb->msg, cb->nest[0]); - return -1; -} - -static int -swconfig_send_ports(struct sk_buff **msg, struct genl_info *info, int attr, - const struct switch_val *val) -{ - struct swconfig_callback cb; - int err = 0; - int i; - - if (!val->value.ports) - return -EINVAL; - - memset(&cb, 0, sizeof(cb)); - cb.cmd = attr; - cb.msg = *msg; - cb.info = info; - cb.fill = swconfig_send_port; - cb.close = swconfig_close_portlist; - - cb.nest[0] = nla_nest_start(cb.msg, cb.cmd); - for (i = 0; i < val->len; i++) { - err = swconfig_send_multipart(&cb, &val->value.ports[i]); - if (err) - goto done; - } - err = val->len; - swconfig_close_portlist(&cb, NULL); - *msg = cb.msg; - -done: - return err; -} - -static int -swconfig_send_link(struct sk_buff *msg, struct genl_info *info, int attr, - const struct switch_port_link *link) -{ - struct nlattr *p = NULL; - int err = 0; - - p = nla_nest_start(msg, attr); - if (link->link) { - if (nla_put_flag(msg, SWITCH_LINK_FLAG_LINK)) - goto nla_put_failure; - } - if (link->duplex) { - if (nla_put_flag(msg, SWITCH_LINK_FLAG_DUPLEX)) - goto nla_put_failure; - } - if (link->aneg) { - if (nla_put_flag(msg, SWITCH_LINK_FLAG_ANEG)) - goto nla_put_failure; - } - if (link->tx_flow) { - if (nla_put_flag(msg, SWITCH_LINK_FLAG_TX_FLOW)) - goto nla_put_failure; - } - if (link->rx_flow) { - if (nla_put_flag(msg, SWITCH_LINK_FLAG_RX_FLOW)) - goto nla_put_failure; - } - if (nla_put_u32(msg, SWITCH_LINK_SPEED, link->speed)) - goto nla_put_failure; - if (link->eee & ADVERTISED_100baseT_Full) { - if (nla_put_flag(msg, SWITCH_LINK_FLAG_EEE_100BASET)) - goto nla_put_failure; - } - if (link->eee & ADVERTISED_1000baseT_Full) { - if (nla_put_flag(msg, SWITCH_LINK_FLAG_EEE_1000BASET)) - goto nla_put_failure; - } - nla_nest_end(msg, p); - - return err; - -nla_put_failure: - nla_nest_cancel(msg, p); - return -1; -} - -static int -swconfig_get_attr(struct sk_buff *skb, struct genl_info *info) -{ - struct genlmsghdr *hdr = nlmsg_data(info->nlhdr); - const struct switch_attr *attr; - struct switch_dev *dev; - struct sk_buff *msg = NULL; - struct switch_val val; - int err = -EINVAL; - int cmd = hdr->cmd; - - dev = swconfig_get_dev(info); - if (!dev) - return -EINVAL; - - memset(&val, 0, sizeof(val)); - attr = swconfig_lookup_attr(dev, info, &val); - if (!attr || !attr->get) - goto error; - - if (attr->type == SWITCH_TYPE_PORTS) { - val.value.ports = dev->portbuf; - memset(dev->portbuf, 0, - sizeof(struct switch_port) * dev->ports); - } else if (attr->type == SWITCH_TYPE_LINK) { - val.value.link = &dev->linkbuf; - memset(&dev->linkbuf, 0, sizeof(struct switch_port_link)); - } - - err = attr->get(dev, attr, &val); - if (err) - goto error; - - msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); - if (!msg) - goto error; - - hdr = genlmsg_put(msg, info->snd_portid, info->snd_seq, &switch_fam, - 0, cmd); - if (IS_ERR(hdr)) - goto nla_put_failure; - - switch (attr->type) { - case SWITCH_TYPE_INT: - if (nla_put_u32(msg, SWITCH_ATTR_OP_VALUE_INT, val.value.i)) - goto nla_put_failure; - break; - case SWITCH_TYPE_STRING: - if (nla_put_string(msg, SWITCH_ATTR_OP_VALUE_STR, val.value.s)) - goto nla_put_failure; - break; - case SWITCH_TYPE_PORTS: - err = swconfig_send_ports(&msg, info, - SWITCH_ATTR_OP_VALUE_PORTS, &val); - if (err < 0) - goto nla_put_failure; - break; - case SWITCH_TYPE_LINK: - err = swconfig_send_link(msg, info, - SWITCH_ATTR_OP_VALUE_LINK, val.value.link); - if (err < 0) - goto nla_put_failure; - break; - default: - pr_debug("invalid type in attribute\n"); - err = -EINVAL; - goto nla_put_failure; - } - genlmsg_end(msg, hdr); - err = msg->len; - if (err < 0) - goto nla_put_failure; - - swconfig_put_dev(dev); - return genlmsg_reply(msg, info); - -nla_put_failure: - if (msg) - nlmsg_free(msg); -error: - swconfig_put_dev(dev); - if (!err) - err = -ENOMEM; - return err; -} - -static int -swconfig_send_switch(struct sk_buff *msg, u32 pid, u32 seq, int flags, - const struct switch_dev *dev) -{ - struct nlattr *p = NULL, *m = NULL; - void *hdr; - int i; - - hdr = genlmsg_put(msg, pid, seq, &switch_fam, flags, - SWITCH_CMD_NEW_ATTR); - if (IS_ERR(hdr)) - return -1; - - if (nla_put_u32(msg, SWITCH_ATTR_ID, dev->id)) - goto nla_put_failure; - if (nla_put_string(msg, SWITCH_ATTR_DEV_NAME, dev->devname)) - goto nla_put_failure; - if (nla_put_string(msg, SWITCH_ATTR_ALIAS, dev->alias)) - goto nla_put_failure; - if (nla_put_string(msg, SWITCH_ATTR_NAME, dev->name)) - goto nla_put_failure; - if (nla_put_u32(msg, SWITCH_ATTR_VLANS, dev->vlans)) - goto nla_put_failure; - if (nla_put_u32(msg, SWITCH_ATTR_PORTS, dev->ports)) - goto nla_put_failure; - if (nla_put_u32(msg, SWITCH_ATTR_CPU_PORT, dev->cpu_port)) - goto nla_put_failure; - - m = nla_nest_start(msg, SWITCH_ATTR_PORTMAP); - if (!m) - goto nla_put_failure; - for (i = 0; i < dev->ports; i++) { - p = nla_nest_start(msg, SWITCH_ATTR_PORTS); - if (!p) - continue; - if (dev->portmap[i].s) { - if (nla_put_string(msg, SWITCH_PORTMAP_SEGMENT, - dev->portmap[i].s)) - goto nla_put_failure; - if (nla_put_u32(msg, SWITCH_PORTMAP_VIRT, - dev->portmap[i].virt)) - goto nla_put_failure; - } - nla_nest_end(msg, p); - } - nla_nest_end(msg, m); - genlmsg_end(msg, hdr); - return msg->len; -nla_put_failure: - genlmsg_cancel(msg, hdr); - return -EMSGSIZE; -} - -static int swconfig_dump_switches(struct sk_buff *skb, - struct netlink_callback *cb) -{ - struct switch_dev *dev; - int start = cb->args[0]; - int idx = 0; - - swconfig_lock(); - list_for_each_entry(dev, &swdevs, dev_list) { - if (++idx <= start) - continue; - if (swconfig_send_switch(skb, NETLINK_CB(cb->skb).portid, - cb->nlh->nlmsg_seq, NLM_F_MULTI, - dev) < 0) - break; - } - swconfig_unlock(); - cb->args[0] = idx; - - return skb->len; -} - -static int -swconfig_done(struct netlink_callback *cb) -{ - return 0; -} - -static struct genl_ops swconfig_ops[] = { - { - .cmd = SWITCH_CMD_LIST_GLOBAL, - .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, - .doit = swconfig_list_attrs, - }, - { - .cmd = SWITCH_CMD_LIST_VLAN, - .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, - .doit = swconfig_list_attrs, - }, - { - .cmd = SWITCH_CMD_LIST_PORT, - .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, - .doit = swconfig_list_attrs, - }, - { - .cmd = SWITCH_CMD_GET_GLOBAL, - .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, - .doit = swconfig_get_attr, - }, - { - .cmd = SWITCH_CMD_GET_VLAN, - .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, - .doit = swconfig_get_attr, - }, - { - .cmd = SWITCH_CMD_GET_PORT, - .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, - .doit = swconfig_get_attr, - }, - { - .cmd = SWITCH_CMD_SET_GLOBAL, - .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, - .flags = GENL_ADMIN_PERM, - .doit = swconfig_set_attr, - }, - { - .cmd = SWITCH_CMD_SET_VLAN, - .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, - .flags = GENL_ADMIN_PERM, - .doit = swconfig_set_attr, - }, - { - .cmd = SWITCH_CMD_SET_PORT, - .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, - .flags = GENL_ADMIN_PERM, - .doit = swconfig_set_attr, - }, - { - .cmd = SWITCH_CMD_GET_SWITCH, - .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, - .dumpit = swconfig_dump_switches, - .done = swconfig_done, - } -}; - -static struct genl_family switch_fam = { - .name = "switch", - .hdrsize = 0, - .version = 1, - .maxattr = SWITCH_ATTR_MAX, - .policy = switch_policy, - .module = THIS_MODULE, - .ops = swconfig_ops, - .n_ops = ARRAY_SIZE(swconfig_ops), - .resv_start_op = SWITCH_CMD_SET_VLAN + 1, -}; - -#ifdef CONFIG_OF -void -of_switch_load_portmap(struct switch_dev *dev) -{ - struct device_node *port; - - if (!dev->of_node) - return; - - for_each_child_of_node(dev->of_node, port) { - const __be32 *prop; - const char *segment; - int size, phys; - - if (!of_device_is_compatible(port, "swconfig,port")) - continue; - - if (of_property_read_string(port, "swconfig,segment", &segment)) - continue; - - prop = of_get_property(port, "swconfig,portmap", &size); - if (!prop) - continue; - - if (size != (2 * sizeof(*prop))) { - pr_err("%s: failed to parse port mapping\n", - port->name); - continue; - } - - phys = be32_to_cpup(prop++); - if ((phys < 0) | (phys >= dev->ports)) { - pr_err("%s: physical port index out of range\n", - port->name); - continue; - } - - dev->portmap[phys].s = kstrdup(segment, GFP_KERNEL); - dev->portmap[phys].virt = be32_to_cpup(prop); - pr_debug("Found port: %s, physical: %d, virtual: %d\n", - segment, phys, dev->portmap[phys].virt); - } -} -#endif - -int -register_switch(struct switch_dev *dev, struct net_device *netdev) -{ - struct switch_dev *sdev; - const int max_switches = 8 * sizeof(unsigned long); - unsigned long in_use = 0; - int err; - int i; - - INIT_LIST_HEAD(&dev->dev_list); - if (netdev) { - dev->netdev = netdev; - if (!dev->alias) - dev->alias = netdev->name; - } - BUG_ON(!dev->alias); - - /* Make sure swdev_id doesn't overflow */ - if (swdev_id == INT_MAX) { - return -ENOMEM; - } - - if (dev->ports > 0) { - dev->portbuf = kzalloc(sizeof(struct switch_port) * - dev->ports, GFP_KERNEL); - if (!dev->portbuf) - return -ENOMEM; - dev->portmap = kzalloc(sizeof(struct switch_portmap) * - dev->ports, GFP_KERNEL); - if (!dev->portmap) { - kfree(dev->portbuf); - return -ENOMEM; - } - } - swconfig_defaults_init(dev); - mutex_init(&dev->sw_mutex); - swconfig_lock(); - dev->id = ++swdev_id; - - list_for_each_entry(sdev, &swdevs, dev_list) { - if (!sscanf(sdev->devname, SWCONFIG_DEVNAME, &i)) - continue; - if (i < 0 || i > max_switches) - continue; - - set_bit(i, &in_use); - } - i = find_first_zero_bit(&in_use, max_switches); - - if (i == max_switches) { - swconfig_unlock(); - return -ENFILE; - } - -#ifdef CONFIG_OF - if (dev->ports) - of_switch_load_portmap(dev); -#endif - - /* fill device name */ - snprintf(dev->devname, IFNAMSIZ, SWCONFIG_DEVNAME, i); - - list_add_tail(&dev->dev_list, &swdevs); - swconfig_unlock(); - - err = swconfig_create_led_trigger(dev); - if (err) - return err; - - return 0; -} -EXPORT_SYMBOL_GPL(register_switch); - -void -unregister_switch(struct switch_dev *dev) -{ - swconfig_destroy_led_trigger(dev); - kfree(dev->portbuf); - mutex_lock(&dev->sw_mutex); - swconfig_lock(); - list_del(&dev->dev_list); - swconfig_unlock(); - mutex_unlock(&dev->sw_mutex); -} -EXPORT_SYMBOL_GPL(unregister_switch); - -int -switch_generic_set_link(struct switch_dev *dev, int port, - struct switch_port_link *link) -{ - if (WARN_ON(!dev->ops->phy_write16)) - return -ENOTSUPP; - - /* Generic implementation */ - if (link->aneg) { - dev->ops->phy_write16(dev, port, MII_BMCR, 0x0000); - dev->ops->phy_write16(dev, port, MII_BMCR, BMCR_ANENABLE | BMCR_ANRESTART); - } else { - u16 bmcr = 0; - - if (link->duplex) - bmcr |= BMCR_FULLDPLX; - - switch (link->speed) { - case SWITCH_PORT_SPEED_10: - break; - case SWITCH_PORT_SPEED_100: - bmcr |= BMCR_SPEED100; - break; - case SWITCH_PORT_SPEED_1000: - bmcr |= BMCR_SPEED1000; - break; - default: - return -ENOTSUPP; - } - - dev->ops->phy_write16(dev, port, MII_BMCR, bmcr); - } - - return 0; -} -EXPORT_SYMBOL_GPL(switch_generic_set_link); - -static int __init -swconfig_init(void) -{ - INIT_LIST_HEAD(&swdevs); - - return genl_register_family(&switch_fam); -} - -static void __exit -swconfig_exit(void) -{ - genl_unregister_family(&switch_fam); -} - -module_init(swconfig_init); -module_exit(swconfig_exit); diff --git a/target/linux/generic/files-6.12/drivers/net/phy/swconfig_leds.c b/target/linux/generic/files-6.12/drivers/net/phy/swconfig_leds.c deleted file mode 100644 index 1fcd4432b54ef8..00000000000000 --- a/target/linux/generic/files-6.12/drivers/net/phy/swconfig_leds.c +++ /dev/null @@ -1,555 +0,0 @@ -/* - * swconfig_led.c: LED trigger support for the switch configuration API - * - * Copyright (C) 2011 Gabor Juhos - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - */ - -#ifdef CONFIG_SWCONFIG_LEDS - -#include -#include -#include -#include - -#define SWCONFIG_LED_TIMER_INTERVAL (HZ / 10) -#define SWCONFIG_LED_NUM_PORTS 32 - -#define SWCONFIG_LED_PORT_SPEED_NA 0x01 /* unknown speed */ -#define SWCONFIG_LED_PORT_SPEED_10 0x02 /* 10 Mbps */ -#define SWCONFIG_LED_PORT_SPEED_100 0x04 /* 100 Mbps */ -#define SWCONFIG_LED_PORT_SPEED_1000 0x08 /* 1000 Mbps */ -#define SWCONFIG_LED_PORT_SPEED_ALL (SWCONFIG_LED_PORT_SPEED_NA | \ - SWCONFIG_LED_PORT_SPEED_10 | \ - SWCONFIG_LED_PORT_SPEED_100 | \ - SWCONFIG_LED_PORT_SPEED_1000) - -#define SWCONFIG_LED_MODE_LINK 0x01 -#define SWCONFIG_LED_MODE_TX 0x02 -#define SWCONFIG_LED_MODE_RX 0x04 -#define SWCONFIG_LED_MODE_TXRX (SWCONFIG_LED_MODE_TX | \ - SWCONFIG_LED_MODE_RX) -#define SWCONFIG_LED_MODE_ALL (SWCONFIG_LED_MODE_LINK | \ - SWCONFIG_LED_MODE_TX | \ - SWCONFIG_LED_MODE_RX) - -struct switch_led_trigger { - struct led_trigger trig; - struct switch_dev *swdev; - - struct delayed_work sw_led_work; - u32 port_mask; - u32 port_link; - unsigned long long port_tx_traffic[SWCONFIG_LED_NUM_PORTS]; - unsigned long long port_rx_traffic[SWCONFIG_LED_NUM_PORTS]; - u8 link_speed[SWCONFIG_LED_NUM_PORTS]; -}; - -struct swconfig_trig_data { - struct led_classdev *led_cdev; - struct switch_dev *swdev; - - rwlock_t lock; - u32 port_mask; - - bool prev_link; - unsigned long prev_traffic; - enum led_brightness prev_brightness; - u8 mode; - u8 speed_mask; -}; - -static void -swconfig_trig_set_brightness(struct swconfig_trig_data *trig_data, - enum led_brightness brightness) -{ - led_set_brightness(trig_data->led_cdev, brightness); - trig_data->prev_brightness = brightness; -} - -static void -swconfig_trig_update_port_mask(struct led_trigger *trigger) -{ - struct list_head *entry; - struct switch_led_trigger *sw_trig; - u32 port_mask; - - if (!trigger) - return; - - sw_trig = (void *) trigger; - - port_mask = 0; - spin_lock(&trigger->leddev_list_lock); - list_for_each(entry, &trigger->led_cdevs) { - struct led_classdev *led_cdev; - struct swconfig_trig_data *trig_data; - - led_cdev = list_entry(entry, struct led_classdev, trig_list); - trig_data = led_cdev->trigger_data; - if (trig_data) { - read_lock(&trig_data->lock); - port_mask |= trig_data->port_mask; - read_unlock(&trig_data->lock); - } - } - spin_unlock(&trigger->leddev_list_lock); - - sw_trig->port_mask = port_mask; - - if (port_mask) - schedule_delayed_work(&sw_trig->sw_led_work, - SWCONFIG_LED_TIMER_INTERVAL); - else - cancel_delayed_work_sync(&sw_trig->sw_led_work); -} - -static ssize_t -swconfig_trig_port_mask_store(struct device *dev, struct device_attribute *attr, - const char *buf, size_t size) -{ - struct led_classdev *led_cdev = dev_get_drvdata(dev); - struct swconfig_trig_data *trig_data = led_cdev->trigger_data; - unsigned long port_mask; - int ret; - bool changed; - - ret = kstrtoul(buf, 0, &port_mask); - if (ret) - return ret; - - write_lock(&trig_data->lock); - changed = (trig_data->port_mask != port_mask); - trig_data->port_mask = port_mask; - write_unlock(&trig_data->lock); - - if (changed) { - if (port_mask == 0) - swconfig_trig_set_brightness(trig_data, LED_OFF); - - swconfig_trig_update_port_mask(led_cdev->trigger); - } - - return size; -} - -static ssize_t -swconfig_trig_port_mask_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct led_classdev *led_cdev = dev_get_drvdata(dev); - struct swconfig_trig_data *trig_data = led_cdev->trigger_data; - u32 port_mask; - - read_lock(&trig_data->lock); - port_mask = trig_data->port_mask; - read_unlock(&trig_data->lock); - - sprintf(buf, "%#x\n", port_mask); - - return strlen(buf) + 1; -} - -static DEVICE_ATTR(port_mask, 0644, swconfig_trig_port_mask_show, - swconfig_trig_port_mask_store); - -/* speed_mask file handler - display value */ -static ssize_t swconfig_trig_speed_mask_show(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct led_classdev *led_cdev = dev_get_drvdata(dev); - struct swconfig_trig_data *trig_data = led_cdev->trigger_data; - u8 speed_mask; - - read_lock(&trig_data->lock); - speed_mask = trig_data->speed_mask; - read_unlock(&trig_data->lock); - - sprintf(buf, "%#x\n", speed_mask); - - return strlen(buf) + 1; -} - -/* speed_mask file handler - store value */ -static ssize_t swconfig_trig_speed_mask_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t size) -{ - struct led_classdev *led_cdev = dev_get_drvdata(dev); - struct swconfig_trig_data *trig_data = led_cdev->trigger_data; - u8 speed_mask; - int ret; - - ret = kstrtou8(buf, 0, &speed_mask); - if (ret) - return ret; - - write_lock(&trig_data->lock); - trig_data->speed_mask = speed_mask & SWCONFIG_LED_PORT_SPEED_ALL; - write_unlock(&trig_data->lock); - - return size; -} - -/* speed_mask special file */ -static DEVICE_ATTR(speed_mask, 0644, swconfig_trig_speed_mask_show, - swconfig_trig_speed_mask_store); - -static ssize_t swconfig_trig_mode_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct led_classdev *led_cdev = dev_get_drvdata(dev); - struct swconfig_trig_data *trig_data = led_cdev->trigger_data; - u8 mode; - - read_lock(&trig_data->lock); - mode = trig_data->mode; - read_unlock(&trig_data->lock); - - if (mode == 0) { - strcpy(buf, "none\n"); - } else { - if (mode & SWCONFIG_LED_MODE_LINK) - strcat(buf, "link "); - if (mode & SWCONFIG_LED_MODE_TX) - strcat(buf, "tx "); - if (mode & SWCONFIG_LED_MODE_RX) - strcat(buf, "rx "); - strcat(buf, "\n"); - } - - return strlen(buf)+1; -} - -static ssize_t swconfig_trig_mode_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t size) -{ - struct led_classdev *led_cdev = dev_get_drvdata(dev); - struct swconfig_trig_data *trig_data = led_cdev->trigger_data; - char copybuf[128]; - int new_mode = -1; - char *p, *token; - - /* take a copy since we don't want to trash the inbound buffer when using strsep */ - strncpy(copybuf, buf, sizeof(copybuf)); - copybuf[sizeof(copybuf) - 1] = 0; - p = copybuf; - - while ((token = strsep(&p, " \t\n")) != NULL) { - if (!*token) - continue; - - if (new_mode < 0) - new_mode = 0; - - if (!strcmp(token, "none")) - new_mode = 0; - else if (!strcmp(token, "tx")) - new_mode |= SWCONFIG_LED_MODE_TX; - else if (!strcmp(token, "rx")) - new_mode |= SWCONFIG_LED_MODE_RX; - else if (!strcmp(token, "link")) - new_mode |= SWCONFIG_LED_MODE_LINK; - else - return -EINVAL; - } - - if (new_mode < 0) - return -EINVAL; - - write_lock(&trig_data->lock); - trig_data->mode = (u8)new_mode; - write_unlock(&trig_data->lock); - - return size; -} - -/* mode special file */ -static DEVICE_ATTR(mode, 0644, swconfig_trig_mode_show, - swconfig_trig_mode_store); - -static int -swconfig_trig_activate(struct led_classdev *led_cdev) -{ - struct switch_led_trigger *sw_trig; - struct swconfig_trig_data *trig_data; - int err; - - trig_data = kzalloc(sizeof(struct swconfig_trig_data), GFP_KERNEL); - if (!trig_data) - return -ENOMEM; - - sw_trig = (void *) led_cdev->trigger; - - rwlock_init(&trig_data->lock); - trig_data->led_cdev = led_cdev; - trig_data->swdev = sw_trig->swdev; - trig_data->speed_mask = SWCONFIG_LED_PORT_SPEED_ALL; - trig_data->mode = SWCONFIG_LED_MODE_ALL; - led_cdev->trigger_data = trig_data; - - err = device_create_file(led_cdev->dev, &dev_attr_port_mask); - if (err) - goto err_free; - - err = device_create_file(led_cdev->dev, &dev_attr_speed_mask); - if (err) - goto err_dev_free; - - err = device_create_file(led_cdev->dev, &dev_attr_mode); - if (err) - goto err_mode_free; - - return 0; - -err_mode_free: - device_remove_file(led_cdev->dev, &dev_attr_speed_mask); - -err_dev_free: - device_remove_file(led_cdev->dev, &dev_attr_port_mask); - -err_free: - led_cdev->trigger_data = NULL; - kfree(trig_data); - - return err; -} - -static void -swconfig_trig_deactivate(struct led_classdev *led_cdev) -{ - struct swconfig_trig_data *trig_data; - - swconfig_trig_update_port_mask(led_cdev->trigger); - - trig_data = (void *) led_cdev->trigger_data; - if (trig_data) { - device_remove_file(led_cdev->dev, &dev_attr_port_mask); - device_remove_file(led_cdev->dev, &dev_attr_speed_mask); - device_remove_file(led_cdev->dev, &dev_attr_mode); - kfree(trig_data); - } -} - -/* - * link off -> led off (can't be any other reason to turn it on) - * link on: - * mode link: led on by default only if speed matches, else off - * mode txrx: blink only if speed matches, else off - */ -static void -swconfig_trig_led_event(struct switch_led_trigger *sw_trig, - struct led_classdev *led_cdev) -{ - struct swconfig_trig_data *trig_data; - u32 port_mask; - bool link; - u8 speed_mask, mode; - enum led_brightness led_base, led_blink; - - trig_data = led_cdev->trigger_data; - if (!trig_data) - return; - - read_lock(&trig_data->lock); - port_mask = trig_data->port_mask; - speed_mask = trig_data->speed_mask; - mode = trig_data->mode; - read_unlock(&trig_data->lock); - - link = !!(sw_trig->port_link & port_mask); - if (!link) { - if (trig_data->prev_brightness != LED_OFF) - swconfig_trig_set_brightness(trig_data, LED_OFF); /* and stop */ - } - else { - unsigned long traffic; - int speedok; /* link speed flag */ - int i; - - led_base = LED_FULL; - led_blink = LED_OFF; - traffic = 0; - speedok = 0; - for (i = 0; i < SWCONFIG_LED_NUM_PORTS; i++) { - if (port_mask & (1 << i)) { - if (sw_trig->link_speed[i] & speed_mask) { - traffic += ((mode & SWCONFIG_LED_MODE_TX) ? - sw_trig->port_tx_traffic[i] : 0) + - ((mode & SWCONFIG_LED_MODE_RX) ? - sw_trig->port_rx_traffic[i] : 0); - speedok = 1; - } - } - } - - if (speedok) { - /* At least one port speed matches speed_mask */ - if (!(mode & SWCONFIG_LED_MODE_LINK)) { - led_base = LED_OFF; - led_blink = LED_FULL; - } - - if (trig_data->prev_brightness != led_base) - swconfig_trig_set_brightness(trig_data, - led_base); - else if (traffic != trig_data->prev_traffic) - swconfig_trig_set_brightness(trig_data, - led_blink); - } else if (trig_data->prev_brightness != LED_OFF) - swconfig_trig_set_brightness(trig_data, LED_OFF); - - trig_data->prev_traffic = traffic; - } - - trig_data->prev_link = link; -} - -static void -swconfig_trig_update_leds(struct switch_led_trigger *sw_trig) -{ - struct list_head *entry; - struct led_trigger *trigger; - - trigger = &sw_trig->trig; - spin_lock(&trigger->leddev_list_lock); - list_for_each(entry, &trigger->led_cdevs) { - struct led_classdev *led_cdev; - - led_cdev = list_entry(entry, struct led_classdev, trig_list); - swconfig_trig_led_event(sw_trig, led_cdev); - } - spin_unlock(&trigger->leddev_list_lock); -} - -static void -swconfig_led_work_func(struct work_struct *work) -{ - struct switch_led_trigger *sw_trig; - struct switch_dev *swdev; - u32 port_mask; - u32 link; - int i; - - sw_trig = container_of(work, struct switch_led_trigger, - sw_led_work.work); - - port_mask = sw_trig->port_mask; - swdev = sw_trig->swdev; - - link = 0; - for (i = 0; i < SWCONFIG_LED_NUM_PORTS; i++) { - u32 port_bit; - - sw_trig->link_speed[i] = 0; - - port_bit = BIT(i); - if ((port_mask & port_bit) == 0) - continue; - - if (swdev->ops->get_port_link) { - struct switch_port_link port_link; - - memset(&port_link, '\0', sizeof(port_link)); - swdev->ops->get_port_link(swdev, i, &port_link); - - if (port_link.link) { - link |= port_bit; - switch (port_link.speed) { - case SWITCH_PORT_SPEED_UNKNOWN: - sw_trig->link_speed[i] = - SWCONFIG_LED_PORT_SPEED_NA; - break; - case SWITCH_PORT_SPEED_10: - sw_trig->link_speed[i] = - SWCONFIG_LED_PORT_SPEED_10; - break; - case SWITCH_PORT_SPEED_100: - sw_trig->link_speed[i] = - SWCONFIG_LED_PORT_SPEED_100; - break; - case SWITCH_PORT_SPEED_1000: - sw_trig->link_speed[i] = - SWCONFIG_LED_PORT_SPEED_1000; - break; - } - } - } - - if (swdev->ops->get_port_stats) { - struct switch_port_stats port_stats; - - memset(&port_stats, '\0', sizeof(port_stats)); - swdev->ops->get_port_stats(swdev, i, &port_stats); - sw_trig->port_tx_traffic[i] = port_stats.tx_bytes; - sw_trig->port_rx_traffic[i] = port_stats.rx_bytes; - } - } - - sw_trig->port_link = link; - - swconfig_trig_update_leds(sw_trig); - - schedule_delayed_work(&sw_trig->sw_led_work, - SWCONFIG_LED_TIMER_INTERVAL); -} - -static int -swconfig_create_led_trigger(struct switch_dev *swdev) -{ - struct switch_led_trigger *sw_trig; - int err; - - if (!swdev->ops->get_port_link) - return 0; - - sw_trig = kzalloc(sizeof(struct switch_led_trigger), GFP_KERNEL); - if (!sw_trig) - return -ENOMEM; - - sw_trig->swdev = swdev; - sw_trig->trig.name = swdev->devname; - sw_trig->trig.activate = swconfig_trig_activate; - sw_trig->trig.deactivate = swconfig_trig_deactivate; - - INIT_DELAYED_WORK(&sw_trig->sw_led_work, swconfig_led_work_func); - - err = led_trigger_register(&sw_trig->trig); - if (err) - goto err_free; - - swdev->led_trigger = sw_trig; - - return 0; - -err_free: - kfree(sw_trig); - return err; -} - -static void -swconfig_destroy_led_trigger(struct switch_dev *swdev) -{ - struct switch_led_trigger *sw_trig; - - sw_trig = swdev->led_trigger; - if (sw_trig) { - cancel_delayed_work_sync(&sw_trig->sw_led_work); - led_trigger_unregister(&sw_trig->trig); - kfree(sw_trig); - } -} - -#else /* SWCONFIG_LEDS */ -static inline int -swconfig_create_led_trigger(struct switch_dev *swdev) { return 0; } - -static inline void -swconfig_destroy_led_trigger(struct switch_dev *swdev) { } -#endif /* CONFIG_SWCONFIG_LEDS */ diff --git a/target/linux/generic/files-6.12/drivers/platform/mikrotik/Kconfig b/target/linux/generic/files-6.12/drivers/platform/mikrotik/Kconfig deleted file mode 100644 index 85fe7b20503cab..00000000000000 --- a/target/linux/generic/files-6.12/drivers/platform/mikrotik/Kconfig +++ /dev/null @@ -1,31 +0,0 @@ -menuconfig MIKROTIK - bool "Platform support for MikroTik RouterBoard virtual devices" - help - Say Y here to get to see options for the MikroTik RouterBoard platform. - This option alone does not add any kernel code. - - -if MIKROTIK - -config MIKROTIK_RB_SYSFS - tristate "RouterBoot sysfs support" - depends on MTD - select LZO_DECOMPRESS - select CRC32 - help - This driver exposes RouterBoot configuration in sysfs. - -config NVMEM_LAYOUT_MIKROTIK - tristate "RouterBoot NVMEM layout support" - depends on NVMEM_LAYOUTS - help - This driver exposes MikroTik hard_config via NVMEM layout. - -config MIKROTIK_WLAN_DECOMPRESS_LZ77 - tristate "Mikrotik factory Wi-Fi caldata LZ77 decompression support" - depends on MIKROTIK_RB_SYSFS - help - Allow Mikrotik LZ77 factory flashed Wi-Fi calibration data to be - decompressed - -endif # MIKROTIK diff --git a/target/linux/generic/files-6.12/drivers/platform/mikrotik/Makefile b/target/linux/generic/files-6.12/drivers/platform/mikrotik/Makefile deleted file mode 100644 index 9ffb355c1e3ddb..00000000000000 --- a/target/linux/generic/files-6.12/drivers/platform/mikrotik/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -# -# Makefile for MikroTik RouterBoard platform specific drivers -# -obj-$(CONFIG_MIKROTIK_RB_SYSFS) += routerboot.o rb_hardconfig.o rb_softconfig.o -obj-$(CONFIG_NVMEM_LAYOUT_MIKROTIK) += rb_nvmem.o -obj-$(CONFIG_MIKROTIK_WLAN_DECOMPRESS_LZ77) += rb_lz77.o diff --git a/target/linux/generic/files-6.12/drivers/platform/mikrotik/rb_hardconfig.c b/target/linux/generic/files-6.12/drivers/platform/mikrotik/rb_hardconfig.c deleted file mode 100644 index 4c1edad0817872..00000000000000 --- a/target/linux/generic/files-6.12/drivers/platform/mikrotik/rb_hardconfig.c +++ /dev/null @@ -1,844 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Driver for MikroTik RouterBoot hard config. - * - * Copyright (C) 2020 Thibaut VARÈNE - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published - * by the Free Software Foundation. - * - * This driver exposes the data encoded in the "hard_config" flash segment of - * MikroTik RouterBOARDs devices. It presents the data in a sysfs folder - * named "hard_config". The WLAN calibration data is available on demand via - * the 'wlan_data' sysfs file in that folder. - * - * This driver permanently allocates a chunk of RAM as large as the hard_config - * MTD partition, although it is technically possible to operate entirely from - * the MTD device without using a local buffer (except when requesting WLAN - * calibration data), at the cost of a performance penalty. - * - * Note: PAGE_SIZE is assumed to be >= 4K, hence the device attribute show - * routines need not check for output overflow. - * - * Some constant defines extracted from routerboot.{c,h} by Gabor Juhos - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "rb_hardconfig.h" -#include "routerboot.h" -#include "rb_lz77.h" - -#define RB_HARDCONFIG_VER "0.08" -#define RB_HC_PR_PFX "[rb_hardconfig] " - -/* Bit definitions for hardware options */ -#define RB_HW_OPT_NO_UART BIT(0) -#define RB_HW_OPT_HAS_VOLTAGE BIT(1) -#define RB_HW_OPT_HAS_USB BIT(2) -#define RB_HW_OPT_HAS_ATTINY BIT(3) -#define RB_HW_OPT_PULSE_DUTY_CYCLE BIT(9) -#define RB_HW_OPT_NO_NAND BIT(14) -#define RB_HW_OPT_HAS_LCD BIT(15) -#define RB_HW_OPT_HAS_POE_OUT BIT(16) -#define RB_HW_OPT_HAS_uSD BIT(17) -#define RB_HW_OPT_HAS_SIM BIT(18) -#define RB_HW_OPT_HAS_SFP BIT(20) -#define RB_HW_OPT_HAS_WIFI BIT(21) -#define RB_HW_OPT_HAS_TS_FOR_ADC BIT(22) -#define RB_HW_OPT_HAS_PLC BIT(29) - -/* - * Tag ID values for ERD data. - * Mikrotik used to pack all calibration data under a single tag id 0x1, but - * recently switched to a new scheme where each radio calibration gets a - * separate tag. The new scheme has tag id bit 15 always set and seems to be - * mutually exclusive with the old scheme. - */ -#define RB_WLAN_ERD_ID_SOLO 0x0001 -#define RB_WLAN_ERD_ID_MULTI_8001 0x8001 -#define RB_WLAN_ERD_ID_MULTI_8201 0x8201 - -static struct kobject *hc_kobj; -static u8 *hc_buf; // ro buffer after init(): no locking required -static size_t hc_buflen; - -/* - * For LZOR style WLAN data unpacking. - * This binary blob is prepended to the data encoded on some devices as - * RB_ID_WLAN_DATA, the result is then first decompressed with LZO, and then - * finally RLE-decoded. - * This binary blob has been extracted from RouterOS by - * https://forum.openwrt.org/u/ius - */ -static const u8 hc_lzor_prefix[] = { - 0x00, 0x05, 0x4c, 0x4c, 0x44, 0x00, 0x34, 0xfe, - 0xfe, 0x34, 0x11, 0x3c, 0x1e, 0x3c, 0x2e, 0x3c, - 0x4c, 0x34, 0x00, 0x52, 0x62, 0x92, 0xa2, 0xb2, - 0xc3, 0x2a, 0x14, 0x00, 0x00, 0x05, 0xfe, 0x6a, - 0x3c, 0x16, 0x32, 0x16, 0x11, 0x1e, 0x12, 0x46, - 0x32, 0x46, 0x11, 0x4e, 0x12, 0x36, 0x32, 0x36, - 0x11, 0x3e, 0x12, 0x5a, 0x9a, 0x64, 0x00, 0x04, - 0xfe, 0x10, 0x3c, 0x00, 0x01, 0x00, 0x00, 0x28, - 0x0c, 0x00, 0x0f, 0xfe, 0x14, 0x00, 0x24, 0x24, - 0x23, 0x24, 0x24, 0x23, 0x25, 0x22, 0x21, 0x21, - 0x23, 0x22, 0x21, 0x22, 0x21, 0x2d, 0x38, 0x00, - 0x0c, 0x25, 0x25, 0x24, 0x25, 0x25, 0x24, 0x23, - 0x22, 0x21, 0x20, 0x23, 0x21, 0x21, 0x22, 0x21, - 0x2d, 0x38, 0x00, 0x28, 0xb0, 0x00, 0x00, 0x22, - 0x00, 0x00, 0xc0, 0xfe, 0x03, 0x00, 0xc0, 0x00, - 0x62, 0xff, 0x62, 0xff, 0xfe, 0x06, 0x00, 0xbb, - 0xff, 0xba, 0xff, 0xfe, 0x08, 0x00, 0x9e, 0xff, - 0xfe, 0x0a, 0x00, 0x53, 0xff, 0xfe, 0x02, 0x00, - 0x20, 0xff, 0xb1, 0xfe, 0xfe, 0xb2, 0xfe, 0xfe, - 0xed, 0xfe, 0xfe, 0xfe, 0x04, 0x00, 0x3a, 0xff, - 0x3a, 0xff, 0xde, 0xfd, 0x5f, 0x04, 0x33, 0xff, - 0x4c, 0x74, 0x03, 0x05, 0x05, 0xff, 0x6d, 0xfe, - 0xfe, 0x6d, 0xfe, 0xfe, 0xaf, 0x08, 0x63, 0xff, - 0x64, 0x6f, 0x08, 0xac, 0xff, 0xbf, 0x6d, 0x08, - 0x7a, 0x6d, 0x08, 0x96, 0x74, 0x04, 0x00, 0x08, - 0x79, 0xff, 0xda, 0xfe, 0xfe, 0xdb, 0xfe, 0xfe, - 0x56, 0xff, 0xfe, 0x04, 0x00, 0x5e, 0xff, 0x5e, - 0xff, 0x6c, 0xfe, 0xfe, 0xfe, 0x06, 0x00, 0x41, - 0xff, 0x7f, 0x74, 0x03, 0x00, 0x11, 0x44, 0xff, - 0xa9, 0xfe, 0xfe, 0xa9, 0xfe, 0xfe, 0xa5, 0x8f, - 0x01, 0x00, 0x08, 0x01, 0x01, 0x02, 0x04, 0x08, - 0x02, 0x04, 0x08, 0x08, 0x01, 0x01, 0xfe, 0x22, - 0x00, 0x4c, 0x60, 0x64, 0x8c, 0x90, 0xd0, 0xd4, - 0xd8, 0x5c, 0x10, 0x09, 0xd8, 0xff, 0xb0, 0xff, - 0x00, 0x00, 0xba, 0xff, 0x14, 0x00, 0xba, 0xff, - 0x64, 0x00, 0x00, 0x08, 0xfe, 0x06, 0x00, 0x74, - 0xff, 0x42, 0xff, 0xce, 0xff, 0x60, 0xff, 0x0a, - 0x00, 0xb4, 0x00, 0xa0, 0x00, 0xa0, 0xfe, 0x07, - 0x00, 0x0a, 0x00, 0xb0, 0xff, 0x96, 0x4d, 0x00, - 0x56, 0x57, 0x18, 0xa6, 0xff, 0x92, 0x70, 0x11, - 0x00, 0x12, 0x90, 0x90, 0x76, 0x5a, 0x54, 0x54, - 0x4c, 0x46, 0x38, 0x00, 0x10, 0x10, 0x08, 0xfe, - 0x05, 0x00, 0x38, 0x29, 0x25, 0x23, 0x22, 0x22, - 0x1f, 0x00, 0x00, 0x00, 0xf6, 0xe1, 0xdd, 0xf8, - 0xfe, 0x00, 0xfe, 0x15, 0x00, 0x00, 0xd0, 0x02, - 0x74, 0x02, 0x08, 0xf8, 0xe5, 0xde, 0x02, 0x04, - 0x04, 0xfd, 0x00, 0x00, 0x00, 0x07, 0x50, 0x2d, - 0x01, 0x90, 0x90, 0x76, 0x60, 0xb0, 0x07, 0x07, - 0x0c, 0x0c, 0x04, 0xfe, 0x05, 0x00, 0x66, 0x66, - 0x5a, 0x56, 0xbc, 0x01, 0x06, 0xfc, 0xfc, 0xf1, - 0xfe, 0x07, 0x00, 0x24, 0x95, 0x70, 0x64, 0x18, - 0x06, 0x2c, 0xff, 0xb5, 0xfe, 0xfe, 0xb5, 0xfe, - 0xfe, 0xe2, 0x8c, 0x24, 0x02, 0x2f, 0xff, 0x2f, - 0xff, 0xb4, 0x78, 0x02, 0x05, 0x73, 0xff, 0xed, - 0xfe, 0xfe, 0x4f, 0xff, 0x36, 0x74, 0x1e, 0x09, - 0x4f, 0xff, 0x50, 0xff, 0xfe, 0x16, 0x00, 0x70, - 0xac, 0x70, 0x8e, 0xac, 0x40, 0x0e, 0x01, 0x70, - 0x7f, 0x8e, 0xac, 0x6c, 0x00, 0x0b, 0xfe, 0x02, - 0x00, 0xfe, 0x0a, 0x2c, 0x2a, 0x2a, 0x28, 0x26, - 0x1e, 0x1e, 0xfe, 0x02, 0x20, 0x65, 0x20, 0x00, - 0x00, 0x05, 0x12, 0x00, 0x11, 0x1e, 0x11, 0x11, - 0x41, 0x1e, 0x41, 0x11, 0x31, 0x1e, 0x31, 0x11, - 0x70, 0x75, 0x7a, 0x7f, 0x84, 0x89, 0x8e, 0x93, - 0x98, 0x30, 0x20, 0x00, 0x02, 0x00, 0xfe, 0x06, - 0x3c, 0xbc, 0x32, 0x0c, 0x00, 0x00, 0x2a, 0x12, - 0x1e, 0x12, 0x2e, 0x12, 0xcc, 0x12, 0x11, 0x1a, - 0x1e, 0x1a, 0x2e, 0x1a, 0x4c, 0x10, 0x1e, 0x10, - 0x11, 0x18, 0x1e, 0x42, 0x1e, 0x42, 0x2e, 0x42, - 0xcc, 0x42, 0x11, 0x4a, 0x1e, 0x4a, 0x2e, 0x4a, - 0x4c, 0x40, 0x1e, 0x40, 0x11, 0x48, 0x1e, 0x32, - 0x1e, 0x32, 0x2e, 0x32, 0xcc, 0x32, 0x11, 0x3a, - 0x1e, 0x3a, 0x2e, 0x3a, 0x4c, 0x30, 0x1e, 0x30, - 0x11, 0x38, 0x1e, 0x27, 0x9a, 0x01, 0x9d, 0xa2, - 0x2f, 0x28, 0x00, 0x00, 0x46, 0xde, 0xc4, 0xbf, - 0xa6, 0x9d, 0x81, 0x7b, 0x5c, 0x61, 0x40, 0xc7, - 0xc0, 0xae, 0xa9, 0x8c, 0x83, 0x6a, 0x62, 0x50, - 0x3e, 0xce, 0xc2, 0xae, 0xa3, 0x8c, 0x7b, 0x6a, - 0x5a, 0x50, 0x35, 0xd7, 0xc2, 0xb7, 0xa4, 0x95, - 0x7e, 0x72, 0x5a, 0x59, 0x37, 0xfe, 0x02, 0xf8, - 0x8c, 0x95, 0x90, 0x8f, 0x00, 0xd7, 0xc0, 0xb7, - 0xa2, 0x95, 0x7b, 0x72, 0x56, 0x59, 0x32, 0xc7, - 0xc3, 0xae, 0xad, 0x8c, 0x85, 0x6a, 0x63, 0x50, - 0x3e, 0xce, 0xc3, 0xae, 0xa4, 0x8c, 0x7c, 0x6a, - 0x59, 0x50, 0x34, 0xd7, 0xc2, 0xb7, 0xa5, 0x95, - 0x7e, 0x72, 0x59, 0x59, 0x36, 0xfc, 0x05, 0x00, - 0x02, 0xce, 0xc5, 0xae, 0xa5, 0x95, 0x83, 0x72, - 0x5c, 0x59, 0x36, 0xbf, 0xc6, 0xa5, 0xab, 0x8c, - 0x8c, 0x6a, 0x67, 0x50, 0x41, 0x64, 0x07, 0x00, - 0x02, 0x95, 0x8c, 0x72, 0x65, 0x59, 0x3f, 0xce, - 0xc7, 0xae, 0xa8, 0x95, 0x86, 0x72, 0x5f, 0x59, - 0x39, 0xfe, 0x02, 0xf8, 0x8b, 0x7c, 0x0b, 0x09, - 0xb7, 0xc2, 0x9d, 0xa4, 0x83, 0x85, 0x6a, 0x6b, - 0x50, 0x44, 0xb7, 0xc1, 0x64, 0x01, 0x00, 0x06, - 0x61, 0x5d, 0x48, 0x3d, 0xae, 0xc4, 0x9d, 0xad, - 0x7b, 0x85, 0x61, 0x66, 0x48, 0x46, 0xae, 0xc3, - 0x95, 0xa3, 0x72, 0x7c, 0x59, 0x56, 0x38, 0x31, - 0x7c, 0x0b, 0x00, 0x0c, 0x96, 0x91, 0x8f, 0x00, - 0xb7, 0xc0, 0xa5, 0xab, 0x8c, 0x8a, 0x6a, 0x64, - 0x50, 0x3c, 0xb7, 0xc0, 0x9d, 0xa0, 0x83, 0x80, - 0x6a, 0x64, 0x50, 0x3d, 0xb7, 0xc5, 0x9d, 0xa5, - 0x83, 0x87, 0x6c, 0x08, 0x07, 0xae, 0xc0, 0x9d, - 0xa8, 0x83, 0x88, 0x6a, 0x6d, 0x50, 0x46, 0xfc, - 0x05, 0x00, 0x16, 0xbf, 0xc0, 0xa5, 0xa2, 0x8c, - 0x7f, 0x6a, 0x57, 0x50, 0x2f, 0xb7, 0xc7, 0xa5, - 0xb1, 0x8c, 0x8e, 0x72, 0x6d, 0x59, 0x45, 0xbf, - 0xc6, 0xa5, 0xa8, 0x8c, 0x87, 0x6a, 0x5f, 0x50, - 0x37, 0xbf, 0xc2, 0xa5, 0xa4, 0x8c, 0x83, 0x6a, - 0x5c, 0x50, 0x34, 0xbc, 0x05, 0x00, 0x0e, 0x90, - 0x00, 0xc7, 0xc2, 0xae, 0xaa, 0x95, 0x82, 0x7b, - 0x60, 0x61, 0x3f, 0xb7, 0xc6, 0xa5, 0xb1, 0x8c, - 0x8d, 0x72, 0x6b, 0x61, 0x51, 0xbf, 0xc4, 0xa5, - 0xa5, 0x8c, 0x82, 0x72, 0x61, 0x59, 0x39, 0x6c, - 0x26, 0x03, 0x95, 0x82, 0x7b, 0x61, 0x61, 0x40, - 0xfc, 0x05, 0x00, 0x00, 0x7e, 0xd7, 0xc3, 0xb7, - 0xa8, 0x9d, 0x80, 0x83, 0x5d, 0x6a, 0x3f, 0xbf, - 0xc7, 0xa5, 0xa8, 0x8c, 0x84, 0x72, 0x60, 0x61, - 0x46, 0xbf, 0xc2, 0xae, 0xb0, 0x9d, 0x92, 0x83, - 0x6f, 0x6a, 0x50, 0xd7, 0xc3, 0xb7, 0xa7, 0x9d, - 0x80, 0x83, 0x5e, 0x6a, 0x40, 0xfe, 0x02, 0xf8, - 0x8d, 0x96, 0x90, 0x90, 0xfe, 0x05, 0x00, 0x8a, - 0xc4, 0x63, 0xb8, 0x3c, 0xa6, 0x29, 0x97, 0x16, - 0x81, 0x84, 0xb7, 0x5b, 0xa9, 0x33, 0x94, 0x1e, - 0x83, 0x11, 0x70, 0xb8, 0xc2, 0x70, 0xb1, 0x4d, - 0xa3, 0x2a, 0x8d, 0x1b, 0x7b, 0xa8, 0xbc, 0x68, - 0xab, 0x47, 0x9d, 0x27, 0x87, 0x18, 0x75, 0xae, - 0xc6, 0x7d, 0xbb, 0x4d, 0xaa, 0x1c, 0x84, 0x11, - 0x72, 0xa3, 0xbb, 0x6e, 0xad, 0x3c, 0x97, 0x24, - 0x85, 0x16, 0x71, 0x80, 0xb2, 0x57, 0xa4, 0x30, - 0x8e, 0x1c, 0x7c, 0x10, 0x68, 0xbb, 0xbd, 0x75, - 0xac, 0x4f, 0x9e, 0x2b, 0x87, 0x1a, 0x76, 0x96, - 0xc5, 0x5e, 0xb5, 0x3e, 0xa5, 0x1f, 0x8c, 0x12, - 0x7a, 0xc1, 0xc6, 0x42, 0x9f, 0x27, 0x8c, 0x16, - 0x77, 0x0f, 0x67, 0x9d, 0xbc, 0x68, 0xad, 0x36, - 0x95, 0x20, 0x83, 0x11, 0x6d, 0x9b, 0xb8, 0x67, - 0xa8, 0x34, 0x90, 0x1f, 0x7c, 0x10, 0x67, 0x9e, - 0xc9, 0x6a, 0xbb, 0x37, 0xa4, 0x20, 0x90, 0x11, - 0x7b, 0xc6, 0xc8, 0x47, 0xa4, 0x2a, 0x90, 0x18, - 0x7b, 0x10, 0x6c, 0xae, 0xc4, 0x5d, 0xad, 0x37, - 0x9a, 0x1f, 0x85, 0x13, 0x75, 0x70, 0xad, 0x42, - 0x99, 0x25, 0x84, 0x17, 0x74, 0x0b, 0x56, 0x87, - 0xc8, 0x57, 0xb8, 0x2b, 0x9e, 0x19, 0x8a, 0x0d, - 0x74, 0xa7, 0xc8, 0x6e, 0xb9, 0x36, 0xa0, 0x1f, - 0x8b, 0x11, 0x75, 0x94, 0xbe, 0x4b, 0xa5, 0x2a, - 0x92, 0x18, 0x7c, 0x0f, 0x6b, 0xaf, 0xc0, 0x58, - 0xa8, 0x34, 0x94, 0x1d, 0x7d, 0x12, 0x6d, 0x82, - 0xc0, 0x52, 0xb0, 0x25, 0x94, 0x14, 0x7f, 0x0c, - 0x68, 0x84, 0xbf, 0x3e, 0xa4, 0x22, 0x8e, 0x10, - 0x76, 0x0b, 0x65, 0x88, 0xb6, 0x42, 0x9b, 0x26, - 0x87, 0x14, 0x70, 0x0c, 0x5f, 0xc5, 0xc2, 0x3e, - 0x97, 0x23, 0x83, 0x13, 0x6c, 0x0c, 0x5c, 0xb1, - 0xc9, 0x76, 0xbc, 0x4a, 0xaa, 0x20, 0x8d, 0x12, - 0x78, 0x93, 0xbf, 0x46, 0xa3, 0x26, 0x8d, 0x14, - 0x74, 0x0c, 0x62, 0xc8, 0xc4, 0x3b, 0x97, 0x21, - 0x82, 0x11, 0x6a, 0x0a, 0x59, 0xa3, 0xb9, 0x68, - 0xa9, 0x30, 0x8d, 0x1a, 0x78, 0x0f, 0x61, 0xa0, - 0xc9, 0x73, 0xbe, 0x50, 0xb1, 0x30, 0x9f, 0x14, - 0x80, 0x83, 0xb7, 0x3c, 0x9a, 0x20, 0x84, 0x0e, - 0x6a, 0x0a, 0x57, 0xac, 0xc2, 0x68, 0xb0, 0x2e, - 0x92, 0x19, 0x7c, 0x0d, 0x63, 0x93, 0xbe, 0x62, - 0xb0, 0x3c, 0x9e, 0x1a, 0x80, 0x0e, 0x6b, 0xbb, - 0x02, 0xa0, 0x02, 0xa0, 0x02, 0x6f, 0x00, 0x75, - 0x00, 0x75, 0x00, 0x00, 0x00, 0xad, 0x02, 0xb3, - 0x02, 0x6f, 0x00, 0x87, 0x00, 0x85, 0xfe, 0x03, - 0x00, 0xc2, 0x02, 0x82, 0x4d, 0x92, 0x6e, 0x4d, - 0xb1, 0xa8, 0x84, 0x01, 0x00, 0x07, 0x7e, 0x00, - 0xa8, 0x02, 0xa4, 0x02, 0xa4, 0x02, 0xa2, 0x00, - 0xa6, 0x00, 0xa6, 0x00, 0x00, 0x00, 0xb4, 0x02, - 0xb4, 0x02, 0x92, 0x00, 0x96, 0x00, 0x96, 0x46, - 0x04, 0xb0, 0x02, 0x64, 0x02, 0x0a, 0x8c, 0x00, - 0x90, 0x02, 0x98, 0x02, 0x98, 0x02, 0x0e, 0x01, - 0x11, 0x01, 0x11, 0x50, 0xc3, 0x08, 0x88, 0x02, - 0x88, 0x02, 0x19, 0x01, 0x02, 0x01, 0x02, 0x01, - 0xf3, 0x2d, 0x00, 0x00 -}; - -/* Array of known hw_options bits with human-friendly parsing */ -static struct hc_hwopt { - const u32 bit; - const char *str; -} const hc_hwopts[] = { - { - .bit = RB_HW_OPT_NO_UART, - .str = "no UART\t\t", - }, { - .bit = RB_HW_OPT_HAS_VOLTAGE, - .str = "has Vreg\t", - }, { - .bit = RB_HW_OPT_HAS_USB, - .str = "has usb\t\t", - }, { - .bit = RB_HW_OPT_HAS_ATTINY, - .str = "has ATtiny\t", - }, { - .bit = RB_HW_OPT_NO_NAND, - .str = "no NAND\t\t", - }, { - .bit = RB_HW_OPT_HAS_LCD, - .str = "has LCD\t\t", - }, { - .bit = RB_HW_OPT_HAS_POE_OUT, - .str = "has POE out\t", - }, { - .bit = RB_HW_OPT_HAS_uSD, - .str = "has MicroSD\t", - }, { - .bit = RB_HW_OPT_HAS_SIM, - .str = "has SIM\t\t", - }, { - .bit = RB_HW_OPT_HAS_SFP, - .str = "has SFP\t\t", - }, { - .bit = RB_HW_OPT_HAS_WIFI, - .str = "has WiFi\t", - }, { - .bit = RB_HW_OPT_HAS_TS_FOR_ADC, - .str = "has TS ADC\t", - }, { - .bit = RB_HW_OPT_HAS_PLC, - .str = "has PLC\t\t", - }, -}; - -/* - * The MAC is stored network-endian on all devices, in 2 32-bit segments: - * . Kernel print has us covered. - */ -static ssize_t hc_tag_show_mac(const u8 *pld, u16 pld_len, char *buf) -{ - if (8 != pld_len) - return -EINVAL; - - return sprintf(buf, "%pM\n", pld); -} - -/* - * Print HW options in a human readable way: - * The raw number and in decoded form - */ -static ssize_t hc_tag_show_hwoptions(const u8 *pld, u16 pld_len, char *buf) -{ - char *out = buf; - u32 data; // cpu-endian - int i; - - if (sizeof(data) != pld_len) - return -EINVAL; - - data = *(u32 *)pld; - out += sprintf(out, "raw\t\t: 0x%08x\n\n", data); - - for (i = 0; i < ARRAY_SIZE(hc_hwopts); i++) - out += sprintf(out, "%s: %s\n", hc_hwopts[i].str, - (data & hc_hwopts[i].bit) ? "true" : "false"); - - return out - buf; -} - -static ssize_t hc_wlan_data_bin_read(struct file *filp, struct kobject *kobj, - struct bin_attribute *attr, char *buf, - loff_t off, size_t count); - -static struct hc_wlan_attr { - const u16 erd_tag_id; - struct bin_attribute battr; - u16 pld_ofs; - u16 pld_len; -} hc_wd_multi_battrs[] = { - { - .erd_tag_id = RB_WLAN_ERD_ID_MULTI_8001, - .battr = __BIN_ATTR(data_0, S_IRUSR, hc_wlan_data_bin_read, NULL, 0), - }, { - .erd_tag_id = RB_WLAN_ERD_ID_MULTI_8201, - .battr = __BIN_ATTR(data_2, S_IRUSR, hc_wlan_data_bin_read, NULL, 0), - } -}; - -static struct hc_wlan_attr hc_wd_solo_battr = { - .erd_tag_id = RB_WLAN_ERD_ID_SOLO, - .battr = __BIN_ATTR(wlan_data, S_IRUSR, hc_wlan_data_bin_read, NULL, 0), -}; - -static ssize_t hc_attr_show(struct kobject *kobj, struct kobj_attribute *attr, - char *buf); - -/* Array of known tags to publish in sysfs */ -static struct hc_attr { - const u16 tag_id; - ssize_t (* const tshow)(const u8 *pld, u16 pld_len, char *buf); - struct kobj_attribute kattr; - u16 pld_ofs; - u16 pld_len; -} hc_attrs[] = { - { - .tag_id = RB_ID_FLASH_INFO, - .tshow = routerboot_tag_show_u32s, - .kattr = __ATTR(flash_info, S_IRUSR, hc_attr_show, NULL), - }, { - .tag_id = RB_ID_MAC_ADDRESS_PACK, - .tshow = hc_tag_show_mac, - .kattr = __ATTR(mac_base, S_IRUSR, hc_attr_show, NULL), - }, { - .tag_id = RB_ID_BOARD_PRODUCT_CODE, - .tshow = routerboot_tag_show_string, - .kattr = __ATTR(board_product_code, S_IRUSR, hc_attr_show, NULL), - }, { - .tag_id = RB_ID_BIOS_VERSION, - .tshow = routerboot_tag_show_string, - .kattr = __ATTR(booter_version, S_IRUSR, hc_attr_show, NULL), - }, { - .tag_id = RB_ID_SERIAL_NUMBER, - .tshow = routerboot_tag_show_string, - .kattr = __ATTR(board_serial, S_IRUSR, hc_attr_show, NULL), - }, { - .tag_id = RB_ID_MEMORY_SIZE, - .tshow = routerboot_tag_show_u32s, - .kattr = __ATTR(mem_size, S_IRUSR, hc_attr_show, NULL), - }, { - .tag_id = RB_ID_MAC_ADDRESS_COUNT, - .tshow = routerboot_tag_show_u32s, - .kattr = __ATTR(mac_count, S_IRUSR, hc_attr_show, NULL), - }, { - .tag_id = RB_ID_HW_OPTIONS, - .tshow = hc_tag_show_hwoptions, - .kattr = __ATTR(hw_options, S_IRUSR, hc_attr_show, NULL), - }, { - .tag_id = RB_ID_WLAN_DATA, - .tshow = NULL, - }, { - .tag_id = RB_ID_BOARD_IDENTIFIER, - .tshow = routerboot_tag_show_string, - .kattr = __ATTR(board_identifier, S_IRUSR, hc_attr_show, NULL), - }, { - .tag_id = RB_ID_PRODUCT_NAME, - .tshow = routerboot_tag_show_string, - .kattr = __ATTR(product_name, S_IRUSR, hc_attr_show, NULL), - }, { - .tag_id = RB_ID_DEFCONF, - .tshow = routerboot_tag_show_string, - .kattr = __ATTR(defconf, S_IRUSR, hc_attr_show, NULL), - }, { - .tag_id = RB_ID_BOARD_REVISION, - .tshow = routerboot_tag_show_string, - .kattr = __ATTR(board_revision, S_IRUSR, hc_attr_show, NULL), - } -}; - -/* - * If the RB_ID_WLAN_DATA payload starts with RB_MAGIC_ERD, then past - * that magic number the payload itself contains a routerboot tag node - * locating the LZO-compressed calibration data. So far this scheme is only - * known to use a single tag at id 0x1. - */ -static int hc_wlan_data_unpack_erd(const u16 tag_id, const u8 *inbuf, size_t inlen, - void *outbuf, size_t *outlen) -{ - u16 lzo_ofs, lzo_len; - int ret; - - /* Find embedded tag */ - ret = routerboot_tag_find(inbuf, inlen, tag_id, &lzo_ofs, &lzo_len); - if (ret) { - pr_debug(RB_HC_PR_PFX "no ERD data for id 0x%04x\n", tag_id); - goto fail; - } - - if (lzo_len > inlen) { - pr_debug(RB_HC_PR_PFX "Invalid ERD data length\n"); - ret = -EINVAL; - goto fail; - } - - ret = lzo1x_decompress_safe(inbuf+lzo_ofs, lzo_len, outbuf, outlen); - if (ret) - pr_debug(RB_HC_PR_PFX "LZO decompression error (%d)\n", ret); - -fail: - return ret; -} - -/* - * If the RB_ID_WLAN_DATA payload starts with RB_MAGIC_LZOR, then past - * that magic number is a payload that must be appended to the hc_lzor_prefix, - * the resulting blob is LZO-compressed. - * If payload starts with RB_MAGIC_LZ77, a separate (bit level LZ77) - * decompression function needs to be used. In the decompressed result, - * the RB_MAGIC_ERD magic number (aligned) must be located. Following that - * magic, there is one or more routerboot tag node(s) locating the RLE-encoded - * calibration data payload. - */ -static int hc_wlan_data_unpack_lzor_lz77(const u16 tag_id, const u8 *inbuf, size_t inlen, - void *outbuf, size_t *outlen, u32 magic) -{ - u16 rle_ofs, rle_len; - const u32 *needle; - u8 *tempbuf; - size_t templen, lzo_len; - int ret; - const char lzor[] = "LZOR"; - const char lz77[] = "LZ77"; - const char *lz_type; - - /* Temporary buffer same size as the outbuf */ - templen = *outlen; - tempbuf = kmalloc(templen, GFP_KERNEL); - if (!tempbuf) - return -ENOMEM; - - lzo_len = inlen; - if (magic == RB_MAGIC_LZOR) - lzo_len += sizeof(hc_lzor_prefix); - if (lzo_len > *outlen) - return -EFBIG; - - switch (magic) { - case RB_MAGIC_LZOR: - lz_type = lzor; - - /* Concatenate into the outbuf */ - memcpy(outbuf, hc_lzor_prefix, sizeof(hc_lzor_prefix)); - memcpy(outbuf + sizeof(hc_lzor_prefix), inbuf, inlen); - - /* LZO-decompress lzo_len bytes of outbuf into the tempbuf */ - ret = lzo1x_decompress_safe(outbuf, lzo_len, tempbuf, &templen); - if (ret) { - if (LZO_E_INPUT_NOT_CONSUMED == ret) { - /* - * The tag length is always aligned thus the LZO payload may be padded, - * which can trigger a spurious error which we ignore here. - */ - pr_debug(RB_HC_PR_PFX "LZOR: LZO EOF before buffer end - this may be harmless\n"); - } else { - pr_debug(RB_HC_PR_PFX "LZOR: LZO decompression error (%d)\n", ret); - goto fail; - } - } - break; - case RB_MAGIC_LZ77: - lz_type = lz77; - /* LZO-decompress lzo_len bytes of inbuf into the tempbuf */ - ret = rb_lz77_decompress(inbuf, inlen, tempbuf, &templen); - if (ret) { - pr_err(RB_HC_PR_PFX "LZ77: LZ77 decompress error %d\n", ret); - goto fail; - } - - pr_debug(RB_HC_PR_PFX "LZ77: decompressed from %zu to %zu\n", - inlen, templen); - break; - default: - return -EINVAL; - break; - } - - /* - * Post decompression we have a blob (possibly byproduct of the lzo - * dictionary). We need to find RB_MAGIC_ERD. The magic number seems to - * be 32bit-aligned in the decompression output. - */ - needle = (const u32 *)tempbuf; - while (RB_MAGIC_ERD != *needle++) { - if ((u8 *)needle >= tempbuf+templen) { - pr_warn(RB_HC_PR_PFX "%s: ERD magic not found. Decompressed first word: 0x%08x\n", lz_type, *(u32 *)tempbuf); - ret = -ENODATA; - goto fail; - } - }; - templen -= (u8 *)needle - tempbuf; - - /* Past magic. Look for tag node */ - ret = routerboot_tag_find((u8 *)needle, templen, tag_id, &rle_ofs, &rle_len); - if (ret) { - pr_debug(RB_HC_PR_PFX "%s: no RLE data for id 0x%04x\n", lz_type, tag_id); - goto fail; - } - - if (rle_len > templen) { - pr_debug(RB_HC_PR_PFX "%s: Invalid RLE data length\n", lz_type); - ret = -EINVAL; - goto fail; - } - - /* RLE-decode tempbuf from needle back into the outbuf */ - ret = routerboot_rle_decode((u8 *)needle+rle_ofs, rle_len, outbuf, outlen); - if (ret) - pr_debug(RB_HC_PR_PFX "%s: RLE decoding error (%d)\n", lz_type, ret); - -fail: - kfree(tempbuf); - return ret; -} - -static int hc_wlan_data_unpack(const u16 tag_id, const size_t tofs, size_t tlen, - void *outbuf, size_t *outlen) -{ - const u8 *lbuf; - u32 magic; - int ret; - - /* Caller ensure tlen > 0. tofs is aligned */ - if ((tofs + tlen) > hc_buflen) - return -EIO; - - lbuf = hc_buf + tofs; - magic = *(u32 *)lbuf; - - ret = -ENODATA; - switch (magic) { - case RB_MAGIC_LZ77: - /* no known instances of lz77 without 8001/8201 data, skip SOLO */ - if (tag_id == RB_WLAN_ERD_ID_SOLO) { - pr_debug(RB_HC_PR_PFX "skipped LZ77 decompress in search for SOLO tag\n"); - break; - } - fallthrough; - case RB_MAGIC_LZOR: - /* Skip magic */ - lbuf += sizeof(magic); - tlen -= sizeof(magic); - ret = hc_wlan_data_unpack_lzor_lz77(tag_id, lbuf, tlen, outbuf, outlen, magic); - break; - case RB_MAGIC_ERD: - /* Skip magic */ - lbuf += sizeof(magic); - tlen -= sizeof(magic); - ret = hc_wlan_data_unpack_erd(tag_id, lbuf, tlen, outbuf, outlen); - break; - default: - /* - * If the RB_ID_WLAN_DATA payload doesn't start with a - * magic number, the payload itself is the raw RLE-encoded - * calibration data. Only RB_WLAN_ERD_ID_SOLO makes sense here. - */ - if (RB_WLAN_ERD_ID_SOLO == tag_id) { - ret = routerboot_rle_decode(lbuf, tlen, outbuf, outlen); - if (ret) - pr_debug(RB_HC_PR_PFX "RLE decoding error (%d)\n", ret); - } - break; - } - - return ret; -} - -static ssize_t hc_attr_show(struct kobject *kobj, struct kobj_attribute *attr, - char *buf) -{ - const struct hc_attr *hc_attr; - const u8 *pld; - u16 pld_len; - - hc_attr = container_of(attr, typeof(*hc_attr), kattr); - - if (!hc_attr->pld_len) - return -ENOENT; - - pld = hc_buf + hc_attr->pld_ofs; - pld_len = hc_attr->pld_len; - - return hc_attr->tshow(pld, pld_len, buf); -} - -/* - * This function will allocate and free memory every time it is called. This - * is not the fastest way to do this, but since the data is rarely read (mainly - * at boot time to load wlan caldata), this makes it possible to save memory for - * the system. - */ -static ssize_t hc_wlan_data_bin_read(struct file *filp, struct kobject *kobj, - struct bin_attribute *attr, char *buf, - loff_t off, size_t count) -{ - struct hc_wlan_attr *hc_wattr; - size_t outlen; - void *outbuf; - int ret; - - hc_wattr = container_of(attr, typeof(*hc_wattr), battr); - - if (!hc_wattr->pld_len) - return -ENOENT; - - outlen = RB_ART_SIZE; - - /* Don't bother unpacking if the source is already too large */ - if (hc_wattr->pld_len > outlen) - return -EFBIG; - - outbuf = kmalloc(outlen, GFP_KERNEL); - if (!outbuf) - return -ENOMEM; - - ret = hc_wlan_data_unpack(hc_wattr->erd_tag_id, hc_wattr->pld_ofs, hc_wattr->pld_len, outbuf, &outlen); - if (ret) { - kfree(outbuf); - return ret; - } - - if (off >= outlen) { - kfree(outbuf); - return 0; - } - - if (off + count > outlen) - count = outlen - off; - - memcpy(buf, outbuf + off, count); - - kfree(outbuf); - return count; -} - -int rb_hardconfig_init(struct kobject *rb_kobj, struct mtd_info *mtd) -{ - struct kobject *hc_wlan_kobj; - size_t bytes_read, buflen, outlen; - const u8 *buf; - void *outbuf; - int i, j, ret; - u32 magic; - - hc_buf = NULL; - hc_kobj = NULL; - hc_wlan_kobj = NULL; - - ret = __get_mtd_device(mtd); - if (ret) - return -ENODEV; - - hc_buflen = mtd->size; - hc_buf = kmalloc(hc_buflen, GFP_KERNEL); - if (!hc_buf) { - __put_mtd_device(mtd); - return -ENOMEM; - } - - ret = mtd_read(mtd, 0, hc_buflen, &bytes_read, hc_buf); - __put_mtd_device(mtd); - - if (ret) - goto fail; - - if (bytes_read != hc_buflen) { - ret = -EIO; - goto fail; - } - - /* Check we have what we expect */ - magic = *(const u32 *)hc_buf; - if (RB_MAGIC_HARD != magic) { - ret = -EINVAL; - goto fail; - } - - /* Skip magic */ - buf = hc_buf + sizeof(magic); - buflen = hc_buflen - sizeof(magic); - - /* Populate sysfs */ - ret = -ENOMEM; - hc_kobj = kobject_create_and_add(RB_MTD_HARD_CONFIG, rb_kobj); - if (!hc_kobj) - goto fail; - - /* Locate and publish all known tags */ - for (i = 0; i < ARRAY_SIZE(hc_attrs); i++) { - ret = routerboot_tag_find(buf, buflen, hc_attrs[i].tag_id, - &hc_attrs[i].pld_ofs, &hc_attrs[i].pld_len); - if (ret) { - hc_attrs[i].pld_ofs = hc_attrs[i].pld_len = 0; - continue; - } - - /* Account for skipped magic */ - hc_attrs[i].pld_ofs += sizeof(magic); - - /* - * Special case RB_ID_WLAN_DATA to prep and create the binary attribute. - * We first check if the data is "old style" within a single tag (or no tag at all): - * If it is we publish this single blob as a binary attribute child of hc_kobj to - * preserve backward compatibility. - * If it isn't and instead uses multiple ERD tags, we create a subfolder and - * publish the known ones there. - */ - if ((RB_ID_WLAN_DATA == hc_attrs[i].tag_id) && hc_attrs[i].pld_len) { - outlen = RB_ART_SIZE; - outbuf = kmalloc(outlen, GFP_KERNEL); - if (!outbuf) { - pr_warn(RB_HC_PR_PFX "Out of memory parsing WLAN tag\n"); - continue; - } - - /* Test ID_SOLO first, if found: done */ - ret = hc_wlan_data_unpack(RB_WLAN_ERD_ID_SOLO, hc_attrs[i].pld_ofs, hc_attrs[i].pld_len, outbuf, &outlen); - if (!ret) { - hc_wd_solo_battr.pld_ofs = hc_attrs[i].pld_ofs; - hc_wd_solo_battr.pld_len = hc_attrs[i].pld_len; - - ret = sysfs_create_bin_file(hc_kobj, &hc_wd_solo_battr.battr); - if (ret) - pr_warn(RB_HC_PR_PFX "Could not create %s sysfs entry (%d)\n", - hc_wd_solo_battr.battr.attr.name, ret); - } - /* Otherwise, create "wlan_data" subtree and publish known data */ - else { - hc_wlan_kobj = kobject_create_and_add("wlan_data", hc_kobj); - if (!hc_wlan_kobj) { - kfree(outbuf); - pr_warn(RB_HC_PR_PFX "Could not create wlan_data sysfs folder\n"); - continue; - } - - for (j = 0; j < ARRAY_SIZE(hc_wd_multi_battrs); j++) { - outlen = RB_ART_SIZE; - ret = hc_wlan_data_unpack(hc_wd_multi_battrs[j].erd_tag_id, - hc_attrs[i].pld_ofs, hc_attrs[i].pld_len, outbuf, &outlen); - if (ret) { - hc_wd_multi_battrs[j].pld_ofs = hc_wd_multi_battrs[j].pld_len = 0; - continue; - } - - hc_wd_multi_battrs[j].pld_ofs = hc_attrs[i].pld_ofs; - hc_wd_multi_battrs[j].pld_len = hc_attrs[i].pld_len; - - ret = sysfs_create_bin_file(hc_wlan_kobj, &hc_wd_multi_battrs[j].battr); - if (ret) - pr_warn(RB_HC_PR_PFX "Could not create wlan_data/%s sysfs entry (%d)\n", - hc_wd_multi_battrs[j].battr.attr.name, ret); - } - } - - kfree(outbuf); - } - /* All other tags are published via standard attributes */ - else { - ret = sysfs_create_file(hc_kobj, &hc_attrs[i].kattr.attr); - if (ret) - pr_warn(RB_HC_PR_PFX "Could not create %s sysfs entry (%d)\n", - hc_attrs[i].kattr.attr.name, ret); - } - } - - pr_info("MikroTik RouterBOARD hardware configuration sysfs driver v" RB_HARDCONFIG_VER "\n"); - - return 0; - -fail: - kfree(hc_buf); - hc_buf = NULL; - return ret; -} - -void rb_hardconfig_exit(void) -{ - kobject_put(hc_kobj); - hc_kobj = NULL; - kfree(hc_buf); - hc_buf = NULL; -} diff --git a/target/linux/generic/files-6.12/drivers/platform/mikrotik/rb_hardconfig.h b/target/linux/generic/files-6.12/drivers/platform/mikrotik/rb_hardconfig.h deleted file mode 100644 index 328f4fe3c32a8e..00000000000000 --- a/target/linux/generic/files-6.12/drivers/platform/mikrotik/rb_hardconfig.h +++ /dev/null @@ -1,32 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Common definitions for MikroTik RouterBoot hard config data. - * - * Copyright (C) 2020 Thibaut VARÈNE - * - * Some constant defines extracted from routerboot.{c,h} by Gabor Juhos - * - */ - -#ifndef _ROUTERBOOT_HARD_CONFIG_H_ -#define _ROUTERBOOT_HARD_CONFIG_H_ - -/* ID values for hardware settings */ -#define RB_ID_FLASH_INFO 0x03 -#define RB_ID_MAC_ADDRESS_PACK 0x04 -#define RB_ID_BOARD_PRODUCT_CODE 0x05 -#define RB_ID_BIOS_VERSION 0x06 -#define RB_ID_SDRAM_TIMINGS 0x08 -#define RB_ID_DEVICE_TIMINGS 0x09 -#define RB_ID_SOFTWARE_ID 0x0A -#define RB_ID_SERIAL_NUMBER 0x0B -#define RB_ID_MEMORY_SIZE 0x0D -#define RB_ID_MAC_ADDRESS_COUNT 0x0E -#define RB_ID_HW_OPTIONS 0x15 -#define RB_ID_WLAN_DATA 0x16 -#define RB_ID_BOARD_IDENTIFIER 0x17 -#define RB_ID_PRODUCT_NAME 0x21 -#define RB_ID_DEFCONF 0x26 -#define RB_ID_BOARD_REVISION 0x27 - -#endif /* _ROUTERBOOT_HARD_CONFIG_H_ */ diff --git a/target/linux/generic/files-6.12/drivers/platform/mikrotik/rb_lz77.c b/target/linux/generic/files-6.12/drivers/platform/mikrotik/rb_lz77.c deleted file mode 100644 index d443adb128ee31..00000000000000 --- a/target/linux/generic/files-6.12/drivers/platform/mikrotik/rb_lz77.c +++ /dev/null @@ -1,446 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * Copyright (C) 2023 John Thomson - */ - -#include -#include -#include -#include -#include - -#include "rb_lz77.h" - -#define MIKRO_LZ77 "[rb lz77] " - -/* - * The maximum number of bits used in a counter. - * For the look behind window, long instruction match offsets - * up to 6449 have been seen in provided compressed caldata blobs - * (that would need 21 counter bits: 4 to 12 + 11 to 0). - * conservative value here: 27 provides offset up to 0x8000 bytes - * uses a u8 in this code - */ -#define MIKRO_LZ77_MAX_COUNT_BIT_LEN 27 - -enum rb_lz77_instruction { - INSTR_ERROR = -1, - INSTR_LITERAL_BYTE = 0, - /* a (non aligned) byte follows this instruction, - * which is directly copied into output - */ - INSTR_PREVIOUS_OFFSET = 1, - /* this group is a match, with a bytes length defined by - * following counter bits, starting at bitshift 0, - * less the built-in count of 1 - * using the previous offset as source - */ - INSTR_LONG = 2 - /* this group has two counters, - * the first counter starts at bitshift 4, - * if this counter == 0, this is a non-matching group - * the second counter (bytes length) starts at bitshift 4, - * less the built-in count of 11+1. - * The final match group has this count 0, - * and following bits which pad to byte-alignment. - * - * if this counter > 0, this is a matching group - * this first count is the match offset (in bytes) - * the second count is the match length (in bytes), - * less the built-in count of 2 - * these groups can source bytes that are part of this group - */ -}; - -struct rb_lz77_instr_opcodes { - /* group instruction */ - enum rb_lz77_instruction instruction; - /* if >0, a match group, - * which starts at byte output_position - 1*offset - */ - size_t offset; - /* how long the match group is, - * or how long the (following counter) non-match group is - */ - size_t length; - /* how many bits were used for this instruction + op code(s) */ - size_t bits_used; - /* input char */ - u8 *in; - /* offset where this instruction started */ - size_t in_pos; -}; - -/** - * rb_lz77_get_bit - * - * @in: compressed data ptr - * @in_offset_bit: bit offset to extract - * - * convert the bit offset to byte offset, - * shift to modulo of bits per bytes, so that wanted bit is lsb - * and to extract only that bit. - * Caller is responsible for ensuring that in_offset_bit/8 - * does not exceed input length - */ -static inline u8 rb_lz77_get_bit(const u8 *in, const size_t in_offset_bit) -{ - return ((in[in_offset_bit / BITS_PER_BYTE] >> - (in_offset_bit % BITS_PER_BYTE)) & - 1); -} - -/** - * rb_lz77_get_byte - * - * @in: compressed data - * @in_offset_bit: bit offset to extract byte - */ -static inline u8 rb_lz77_get_byte(const u8 *in, const size_t in_offset_bit) -{ - u8 buf = 0; - int i; - - /* built a reversed byte from (likely) unaligned bits */ - for (i = 0; i <= 7; ++i) - buf += rb_lz77_get_bit(in, in_offset_bit + i) << (7 - i); - return buf; -} - -/** - * rb_lz77_decode_count - decode bits at given offset as a count - * - * @in: compressed data - * @in_len: length of compressed data - * @in_offset_bit: bit offset where count starts - * @shift: left shift operand value of first count bit - * @count: initial count - * @bits_used: how many bits were consumed by this count - * @max_bits: maximum bit count for this counter - * - * Returns the decoded count - */ -static int rb_lz77_decode_count(const u8 *in, const size_t in_len, - const size_t in_offset_bit, u8 shift, - size_t count, u8 *bits_used, const u8 max_bits) -{ - size_t pos = in_offset_bit; - const size_t max_pos = min(pos + max_bits, in_len * BITS_PER_BYTE); - bool up = true; - - *bits_used = 0; - pr_debug(MIKRO_LZ77 - "decode_count inbit: %zu, start shift:%u, initial count:%zu\n", - in_offset_bit, shift, count); - - while (true) { - /* check the input offset bit does not overflow the minimum of - * a reasonable length for this encoded count, and - * the end of the input */ - if (unlikely(pos >= max_pos)) { - pr_err(MIKRO_LZ77 - "max bit index reached before count completed\n"); - return -EFBIG; - } - - /* if the bit value at offset is set */ - if (rb_lz77_get_bit(in, pos)) - count += (1 << shift); - - /* shift increases until we find an unsed bit */ - else if (up) - up = false; - - if (up) - ++shift; - else { - if (!shift) { - *bits_used = pos - in_offset_bit + 1; - return count; - } - --shift; - } - - ++pos; - } - - return -EINVAL; -} - -/** - * rb_lz77_decode_instruction - * - * @in: compressed data - * @in_offset_bit: bit offset where instruction starts - * @bits_used: how many bits were consumed by this count - * - * Returns the decoded instruction - */ -static enum rb_lz77_instruction -rb_lz77_decode_instruction(const u8 *in, size_t in_offset_bit, u8 *bits_used) -{ - if (rb_lz77_get_bit(in, in_offset_bit)) { - *bits_used = 2; - if (rb_lz77_get_bit(in, ++in_offset_bit)) - return INSTR_LONG; - else - return INSTR_PREVIOUS_OFFSET; - } else { - *bits_used = 1; - return INSTR_LITERAL_BYTE; - } - return INSTR_ERROR; -} - -/** - * rb_lz77_decode_instruction_operators - * - * @in: compressed data - * @in_len: length of compressed data - * @in_offset_bit: bit offset where instruction starts - * @previous_offset: last used match offset - * @opcode: struct to hold instruction & operators - * - * Returns error code - */ -static int rb_lz77_decode_instruction_operators( - const u8 *in, const size_t in_len, const size_t in_offset_bit, - const size_t previous_offset, struct rb_lz77_instr_opcodes *opcode) -{ - enum rb_lz77_instruction instruction; - u8 bit_count = 0; - u8 bits_used = 0; - int offset = 0; - int length = 0; - - instruction = rb_lz77_decode_instruction(in, in_offset_bit, &bit_count); - - /* skip bits used by instruction */ - bits_used += bit_count; - - switch (instruction) { - case INSTR_LITERAL_BYTE: - /* non-matching char */ - offset = 0; - length = 1; - break; - - case INSTR_PREVIOUS_OFFSET: - /* matching group uses previous offset */ - offset = previous_offset; - - length = rb_lz77_decode_count(in, in_len, - in_offset_bit + bits_used, 0, 1, - &bit_count, - MIKRO_LZ77_MAX_COUNT_BIT_LEN); - if (unlikely(length < 0)) - return length; - /* skip bits used by count */ - bits_used += bit_count; - break; - - case INSTR_LONG: - offset = rb_lz77_decode_count(in, in_len, - in_offset_bit + bits_used, 4, 0, - &bit_count, - MIKRO_LZ77_MAX_COUNT_BIT_LEN); - if (unlikely(offset < 0)) - return offset; - - /* skip bits used by offset count */ - bits_used += bit_count; - - if (offset == 0) { - /* non-matching long group */ - length = rb_lz77_decode_count( - in, in_len, in_offset_bit + bits_used, 4, 12, - &bit_count, MIKRO_LZ77_MAX_COUNT_BIT_LEN); - if (unlikely(length < 0)) - return length; - /* skip bits used by length count */ - bits_used += bit_count; - } else { - /* matching group */ - length = rb_lz77_decode_count( - in, in_len, in_offset_bit + bits_used, 0, 2, - &bit_count, MIKRO_LZ77_MAX_COUNT_BIT_LEN); - if (unlikely(length < 0)) - return length; - /* skip bits used by length count */ - bits_used += bit_count; - } - - break; - - case INSTR_ERROR: - return -EINVAL; - } - - opcode->instruction = instruction; - opcode->offset = offset; - opcode->length = length; - opcode->bits_used = bits_used; - opcode->in = (u8 *)in; - opcode->in_pos = in_offset_bit; - return 0; -} - -/** - * rb_lz77_decompress - * - * @in: compressed data ptr - * @in_len: length of compressed data - * @out: buffer ptr to decompress into - * @out_len: length of decompressed buffer in input, - * length of decompressed data in success - * - * Returns 0 on success, or negative error - */ -int rb_lz77_decompress(const u8 *in, const size_t in_len, u8 *out, - size_t *out_len) -{ - u8 *output_ptr; - size_t input_bit = 0; - const u8 *output_end = out + *out_len; - struct rb_lz77_instr_opcodes *opcode; - size_t match_offset = 0; - int rc = 0; - size_t match_length, partial_count, i; - - output_ptr = out; - - if (unlikely((in_len * BITS_PER_BYTE) > SIZE_MAX)) { - pr_err(MIKRO_LZ77 "input longer than expected\n"); - return -EFBIG; - } - - opcode = kmalloc(sizeof(*opcode), GFP_KERNEL); - if (!opcode) - return -ENOMEM; - - while (true) { - if (unlikely(output_ptr > output_end)) { - pr_err(MIKRO_LZ77 "output overrun\n"); - rc = -EOVERFLOW; - goto free_lz77_struct; - } - if (unlikely(input_bit > in_len * BITS_PER_BYTE)) { - pr_err(MIKRO_LZ77 "input overrun\n"); - rc = -ENODATA; - goto free_lz77_struct; - } - - rc = rb_lz77_decode_instruction_operators(in, in_len, input_bit, - match_offset, opcode); - if (unlikely(rc < 0)) { - pr_err(MIKRO_LZ77 - "instruction operands decode error\n"); - goto free_lz77_struct; - } - - pr_debug(MIKRO_LZ77 "inbit:0x%zx->outbyte:0x%zx", input_bit, - output_ptr - out); - - input_bit += opcode->bits_used; - switch (opcode->instruction) { - case INSTR_LITERAL_BYTE: - pr_debug(" short"); - fallthrough; - case INSTR_LONG: - if (opcode->offset == 0) { - /* this is a non-matching group */ - pr_debug(" non-match, len: 0x%zx\n", - opcode->length); - /* test end marker */ - if (opcode->length == 0xc && - ((input_bit + - opcode->length * BITS_PER_BYTE) > - in_len)) { - *out_len = output_ptr - out; - pr_debug( - MIKRO_LZ77 - "lz77 decompressed from %zu to %zu\n", - in_len, *out_len); - rc = 0; - goto free_lz77_struct; - } - for (i = opcode->length; i > 0; --i) { - *output_ptr = - rb_lz77_get_byte(in, input_bit); - ++output_ptr; - input_bit += BITS_PER_BYTE; - } - /* do no fallthrough if a non-match group */ - break; - } - match_offset = opcode->offset; - fallthrough; - case INSTR_PREVIOUS_OFFSET: - match_length = opcode->length; - partial_count = 0; - - pr_debug(" match, offset: 0x%zx, len: 0x%zx", - opcode->offset, match_length); - - if (unlikely(opcode->offset == 0)) { - pr_err(MIKRO_LZ77 - "match group missing opcode->offset\n"); - rc = -EBADMSG; - goto free_lz77_struct; - } - - /* overflow */ - if (unlikely((output_ptr + match_length) > - output_end)) { - pr_err(MIKRO_LZ77 - "match group output overflow\n"); - rc = -ENOBUFS; - goto free_lz77_struct; - } - - /* underflow */ - if (unlikely((output_ptr - opcode->offset) < out)) { - pr_err(MIKRO_LZ77 - "match group offset underflow\n"); - rc = -ESPIPE; - goto free_lz77_struct; - } - - /* there are cases where the match (length) includes - * data that is a part of the same match - */ - while (opcode->offset < match_length) { - ++partial_count; - memcpy(output_ptr, output_ptr - opcode->offset, - opcode->offset); - output_ptr += opcode->offset; - match_length -= opcode->offset; - } - memcpy(output_ptr, output_ptr - opcode->offset, - match_length); - output_ptr += match_length; - if (partial_count) - pr_debug(" (%zu partial memcpy)", - partial_count); - pr_debug("\n"); - - break; - - case INSTR_ERROR: - rc = -EINVAL; - goto free_lz77_struct; - } - } - - pr_err(MIKRO_LZ77 "decode loop broken\n"); - rc = -EINVAL; - -free_lz77_struct: - kfree(opcode); - return rc; -} -EXPORT_SYMBOL_GPL(rb_lz77_decompress); - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("Mikrotik Wi-Fi caldata LZ77 decompressor"); -MODULE_AUTHOR("John Thomson"); diff --git a/target/linux/generic/files-6.12/drivers/platform/mikrotik/rb_lz77.h b/target/linux/generic/files-6.12/drivers/platform/mikrotik/rb_lz77.h deleted file mode 100644 index 55179fcbc8e01c..00000000000000 --- a/target/linux/generic/files-6.12/drivers/platform/mikrotik/rb_lz77.h +++ /dev/null @@ -1,35 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* - * Copyright (C) 2024 John Thomson - */ - -#ifndef __MIKROTIK_WLAN_LZ77_H__ -#define __MIKROTIK_WLAN_LZ77_H__ - -#include - -#ifdef CONFIG_MIKROTIK_WLAN_DECOMPRESS_LZ77 -/** - * rb_lz77_decompress - * - * @in: compressed data ptr - * @in_len: length of compressed data - * @out: buffer ptr to decompress into - * @out_len: length of decompressed buffer in input, - * length of decompressed data in success - * - * Returns 0 on success, or negative error - */ -int rb_lz77_decompress(const u8 *in, const size_t in_len, u8 *out, - size_t *out_len); - -#else /* CONFIG_MIKROTIK_WLAN_DECOMPRESS_LZ77 */ - -static inline int rb_lz77_decompress(const u8 *in, const size_t in_len, u8 *out, - size_t *out_len) -{ - return -EOPNOTSUPP; -} - -#endif /* CONFIG_MIKROTIK_WLAN_DECOMPRESS_LZ77 */ -#endif /* __MIKROTIK_WLAN_LZ77_H__ */ diff --git a/target/linux/generic/files-6.12/drivers/platform/mikrotik/rb_nvmem.c b/target/linux/generic/files-6.12/drivers/platform/mikrotik/rb_nvmem.c deleted file mode 100644 index 6f785ce7d14dbe..00000000000000 --- a/target/linux/generic/files-6.12/drivers/platform/mikrotik/rb_nvmem.c +++ /dev/null @@ -1,230 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * NVMEM layout driver for MikroTik Routerboard hard config cells - * - * Copyright (C) 2024 Robert Marko - * Based on the sysfs hard config driver by Thibaut VARÈNE - * Comments documenting the format carried over from routerboot.c - */ - -#include -#include -#include -#include -#include -#include -#include - -#include "rb_hardconfig.h" -#include "routerboot.h" - -#define TLV_TAG_MASK GENMASK(15, 0) -#define TLV_LEN_MASK GENMASK(31, 16) - -static const char *rb_tlv_cell_name(u16 tag) -{ - switch (tag) { - case RB_ID_FLASH_INFO: - return "flash-info"; - case RB_ID_MAC_ADDRESS_PACK: - return "base-mac-address"; - case RB_ID_BOARD_PRODUCT_CODE: - return "board-product-code"; - case RB_ID_BIOS_VERSION: - return "booter-version"; - case RB_ID_SERIAL_NUMBER: - return "board-serial"; - case RB_ID_MEMORY_SIZE: - return "mem-size"; - case RB_ID_MAC_ADDRESS_COUNT: - return "mac-count"; - case RB_ID_HW_OPTIONS: - return "hw-options"; - case RB_ID_WLAN_DATA: - return "wlan-data"; - case RB_ID_BOARD_IDENTIFIER: - return "board-identifier"; - case RB_ID_PRODUCT_NAME: - return "product-name"; - case RB_ID_DEFCONF: - return "defconf"; - case RB_ID_BOARD_REVISION: - return "board-revision"; - default: - break; - } - - return NULL; -} - -static int rb_tlv_mac_read_cb(void *priv, const char *id, int index, - unsigned int offset, void *buf, - size_t bytes) -{ - if (index < 0) - return -EINVAL; - - if (!is_valid_ether_addr(buf)) - return -EINVAL; - - eth_addr_add(buf, index); - - return 0; -} - -static nvmem_cell_post_process_t rb_tlv_read_cb(u16 tag) -{ - switch (tag) { - case RB_ID_MAC_ADDRESS_PACK: - return &rb_tlv_mac_read_cb; - default: - break; - } - - return NULL; -} - -static int rb_add_cells(struct device *dev, struct nvmem_device *nvmem, - const size_t data_len, u8 *data) -{ - u32 node, offset = sizeof(RB_MAGIC_HARD); - struct nvmem_cell_info cell = {}; - struct device_node *layout; - u16 tlv_tag, tlv_len; - int ret; - - layout = of_nvmem_layout_get_container(nvmem); - if (!layout) - return -ENOENT; - - /* - * Routerboot tag nodes are u32 values: - * - The low nibble is the tag identification number, - * - The high nibble is the tag payload length (node excluded) in bytes. - * Tag nodes are CPU-endian. - * Tag nodes are 32bit-aligned. - * - * The payload immediately follows the tag node. - * Payload offset will always be aligned. while length may not end on 32bit - * boundary (the only known case is when parsing ERD data). - * The payload is CPU-endian when applicable. - * Tag nodes are not ordered (by ID) on flash. - */ - while ((offset + sizeof(node)) <= data_len) { - node = *((const u32 *) (data + offset)); - /* Tag list ends with null node */ - if (!node) - break; - - tlv_tag = FIELD_GET(TLV_TAG_MASK, node); - tlv_len = FIELD_GET(TLV_LEN_MASK, node); - - offset += sizeof(node); - if (offset + tlv_len > data_len) { - dev_err(dev, "Out of bounds field (0x%x bytes at 0x%x)\n", - tlv_len, offset); - break; - } - - cell.name = rb_tlv_cell_name(tlv_tag); - if (!cell.name) - goto skip; - - cell.offset = offset; - /* - * MikroTik stores MAC-s with length of 8 bytes, - * but kernel expects it to be ETH_ALEN (6 bytes), - * so we need to make sure that is the case. - */ - if (tlv_tag == RB_ID_MAC_ADDRESS_PACK) - cell.bytes = ETH_ALEN; - else - cell.bytes = tlv_len; - cell.np = of_get_child_by_name(layout, cell.name); - cell.read_post_process = rb_tlv_read_cb(tlv_tag); - - ret = nvmem_add_one_cell(nvmem, &cell); - if (ret) { - of_node_put(layout); - return ret; - } - - /* - * The only known situation where len may not end on 32bit - * boundary is within ERD data. Since we're only extracting - * one tag (the first and only one) from that data, we should - * never need to forcefully ALIGN(). Do it anyway, this is not a - * performance path. - */ -skip: - offset += ALIGN(tlv_len, sizeof(offset)); - } - - of_node_put(layout); - - return 0; -} - -static int rb_parse_table(struct nvmem_layout *layout) -{ - struct nvmem_device *nvmem = layout->nvmem; - struct device *dev = &layout->dev; - size_t mtd_size; - u8 *data; - u32 hdr; - int ret; - - ret = nvmem_device_read(nvmem, 0, sizeof(hdr), &hdr); - if (ret < 0) - return ret; - - if (hdr != RB_MAGIC_HARD) { - dev_err(dev, "Invalid header\n"); - return -EINVAL; - } - - mtd_size = nvmem_dev_size(nvmem); - - data = devm_kmalloc(dev, mtd_size, GFP_KERNEL); - if (!data) - return -ENOMEM; - - ret = nvmem_device_read(nvmem, 0, mtd_size, data); - if (ret != mtd_size) - return ret; - - return rb_add_cells(dev, nvmem, mtd_size, data); -} - -static int rb_nvmem_probe(struct nvmem_layout *layout) -{ - layout->add_cells = rb_parse_table; - - return nvmem_layout_register(layout); -} - -static void rb_nvmem_remove(struct nvmem_layout *layout) -{ - nvmem_layout_unregister(layout); -} - -static const struct of_device_id rb_nvmem_of_match_table[] = { - { .compatible = "mikrotik,routerboot-nvmem", }, - {}, -}; -MODULE_DEVICE_TABLE(of, rb_nvmem_of_match_table); - -static struct nvmem_layout_driver rb_nvmem_layout = { - .probe = rb_nvmem_probe, - .remove = rb_nvmem_remove, - .driver = { - .owner = THIS_MODULE, - .name = "rb_nvmem", - .of_match_table = rb_nvmem_of_match_table, - }, -}; -module_nvmem_layout_driver(rb_nvmem_layout); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Robert Marko "); -MODULE_DESCRIPTION("NVMEM layout driver for MikroTik Routerboard hard config cells"); diff --git a/target/linux/generic/files-6.12/drivers/platform/mikrotik/rb_softconfig.c b/target/linux/generic/files-6.12/drivers/platform/mikrotik/rb_softconfig.c deleted file mode 100644 index 5acff6aa9184de..00000000000000 --- a/target/linux/generic/files-6.12/drivers/platform/mikrotik/rb_softconfig.c +++ /dev/null @@ -1,795 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Driver for MikroTik RouterBoot soft config. - * - * Copyright (C) 2020 Thibaut VARÈNE - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published - * by the Free Software Foundation. - * - * This driver exposes the data encoded in the "soft_config" flash segment of - * MikroTik RouterBOARDs devices. It presents the data in a sysfs folder - * named "soft_config". The data is presented in a user/machine-friendly way - * with just as much parsing as can be generalized across mikrotik platforms - * (as inferred from reverse-engineering). - * - * The known soft_config tags are presented in the "soft_config" sysfs folder, - * with the addition of one specific file named "commit", which is only - * available if the driver supports writes to the mtd device: no modifications - * made to any of the other attributes are actually written back to flash media - * until a true value is input into this file (e.g. [Yy1]). This is to avoid - * unnecessary flash wear, and to permit to revert all changes by issuing a - * false value ([Nn0]). Reading the content of this file shows the current - * status of the driver: if the data in sysfs matches the content of the - * soft_config partition, the file will read "clean". Otherwise, it will read - * "dirty". - * - * The writeable sysfs files presented by this driver will accept only inputs - * which are in a valid range for the given tag. As a design choice, the driver - * will not assess whether the inputs are identical to the existing data. - * - * Note: PAGE_SIZE is assumed to be >= 4K, hence the device attribute show - * routines need not check for output overflow. - * - * Some constant defines extracted from rbcfg.h by Gabor Juhos - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef CONFIG_ATH79 - #include -#endif - -#include "routerboot.h" - -#define RB_SOFTCONFIG_VER "0.05" -#define RB_SC_PR_PFX "[rb_softconfig] " - -#define RB_SC_HAS_WRITE_SUPPORT true -#define RB_SC_WMODE S_IWUSR -#define RB_SC_RMODE S_IRUSR - -/* ID values for software settings */ -#define RB_SCID_UART_SPEED 0x01 // u32*1 -#define RB_SCID_BOOT_DELAY 0x02 // u32*1 -#define RB_SCID_BOOT_DEVICE 0x03 // u32*1 -#define RB_SCID_BOOT_KEY 0x04 // u32*1 -#define RB_SCID_CPU_MODE 0x05 // u32*1 -#define RB_SCID_BIOS_VERSION 0x06 // str -#define RB_SCID_BOOT_PROTOCOL 0x09 // u32*1 -#define RB_SCID_CPU_FREQ_IDX 0x0C // u32*1 -#define RB_SCID_BOOTER 0x0D // u32*1 -#define RB_SCID_SILENT_BOOT 0x0F // u32*1 -/* - * protected_routerboot seems to use tag 0x1F. It only works in combination with - * RouterOS, resulting in a wiped board otherwise, so it's not implemented here. - * The tag values are as follows: - * - off: 0x0 - * - on: the lower halfword encodes the max value in s for the reset feature, - * the higher halfword encodes the min value in s for the reset feature. - * Default value when on: 0x00140258: 0x14 = 20s / 0x258= 600s - * See details here: https://wiki.mikrotik.com/wiki/Manual:RouterBOARD_settings#Protected_bootloader - */ - -/* Tag values */ - -#define RB_UART_SPEED_115200 0 -#define RB_UART_SPEED_57600 1 -#define RB_UART_SPEED_38400 2 -#define RB_UART_SPEED_19200 3 -#define RB_UART_SPEED_9600 4 -#define RB_UART_SPEED_4800 5 -#define RB_UART_SPEED_2400 6 -#define RB_UART_SPEED_1200 7 -#define RB_UART_SPEED_OFF 8 - -/* valid boot delay: 1 - 9s in 1s increment */ -#define RB_BOOT_DELAY_MIN 1 -#define RB_BOOT_DELAY_MAX 9 - -#define RB_BOOT_DEVICE_ETHER 0 // "boot over Ethernet" -#define RB_BOOT_DEVICE_NANDETH 1 // "boot from NAND, if fail then Ethernet" -#define RB_BOOT_DEVICE_CFCARD 2 // (not available in rbcfg) -#define RB_BOOT_DEVICE_ETHONCE 3 // "boot Ethernet once, then NAND" -#define RB_BOOT_DEVICE_NANDONLY 5 // "boot from NAND only" -#define RB_BOOT_DEVICE_FLASHCFG 7 // "boot in flash configuration mode" -#define RB_BOOT_DEVICE_FLSHONCE 8 // "boot in flash configuration mode once, then NAND" - -/* - * ATH79 9xxx CPU frequency indices. - * It is unknown if they apply to all ATH79 RBs, and some do not seem to feature - * the upper levels (QCA955x), while F is presumably AR9344-only. - */ -#define RB_CPU_FREQ_IDX_ATH79_9X_A (0 << 3) -#define RB_CPU_FREQ_IDX_ATH79_9X_B (1 << 3) // 0x8 -#define RB_CPU_FREQ_IDX_ATH79_9X_C (2 << 3) // 0x10 - factory freq for many devices -#define RB_CPU_FREQ_IDX_ATH79_9X_D (3 << 3) // 0x18 -#define RB_CPU_FREQ_IDX_ATH79_9X_E (4 << 3) // 0x20 -#define RB_CPU_FREQ_IDX_ATH79_9X_F (5 << 3) // 0x28 - -#define RB_CPU_FREQ_IDX_ATH79_9X_MIN 0 // all devices support lowest setting -#define RB_CPU_FREQ_IDX_ATH79_9X_AR9334_MAX 5 // stops at F -#define RB_CPU_FREQ_IDX_ATH79_9X_QCA953X_MAX 4 // stops at E -#define RB_CPU_FREQ_IDX_ATH79_9X_QCA9556_MAX 2 // stops at C -#define RB_CPU_FREQ_IDX_ATH79_9X_QCA9558_MAX 3 // stops at D - -/* ATH79 7xxx CPU frequency indices. */ -#define RB_CPU_FREQ_IDX_ATH79_7X_A ((0 * 9) << 4) -#define RB_CPU_FREQ_IDX_ATH79_7X_B ((1 * 9) << 4) -#define RB_CPU_FREQ_IDX_ATH79_7X_C ((2 * 9) << 4) -#define RB_CPU_FREQ_IDX_ATH79_7X_D ((3 * 9) << 4) -#define RB_CPU_FREQ_IDX_ATH79_7X_E ((4 * 9) << 4) -#define RB_CPU_FREQ_IDX_ATH79_7X_F ((5 * 9) << 4) -#define RB_CPU_FREQ_IDX_ATH79_7X_G ((6 * 9) << 4) -#define RB_CPU_FREQ_IDX_ATH79_7X_H ((7 * 9) << 4) - -#define RB_CPU_FREQ_IDX_ATH79_7X_MIN 0 // all devices support lowest setting -#define RB_CPU_FREQ_IDX_ATH79_7X_AR724X_MAX 3 // stops at D -#define RB_CPU_FREQ_IDX_ATH79_7X_AR7161_MAX 7 // stops at H - check if applies to all AR71xx devices - -#define RB_SC_CRC32_OFFSET 4 // located right after magic - -static struct kobject *sc_kobj; -static u8 *sc_buf; -static size_t sc_buflen; -static rwlock_t sc_bufrwl; // rw lock to sc_buf - -/* MUST be used with lock held */ -#define RB_SC_CLRCRC() *(u32 *)(sc_buf + RB_SC_CRC32_OFFSET) = 0 -#define RB_SC_GETCRC() *(u32 *)(sc_buf + RB_SC_CRC32_OFFSET) -#define RB_SC_SETCRC(_crc) *(u32 *)(sc_buf + RB_SC_CRC32_OFFSET) = (_crc) - -struct sc_u32tvs { - const u32 val; - const char *str; -}; - -#define RB_SC_TVS(_val, _str) { \ - .val = (_val), \ - .str = (_str), \ -} - -static ssize_t sc_tag_show_u32tvs(const u8 *pld, u16 pld_len, char *buf, - const struct sc_u32tvs tvs[], const int tvselmts) -{ - const char *fmt; - char *out = buf; - u32 data; // cpu-endian - int i; - - // fallback to raw hex output if we can't handle the input - if (tvselmts < 0) - return routerboot_tag_show_u32s(pld, pld_len, buf); - - if (sizeof(data) != pld_len) - return -EINVAL; - - read_lock(&sc_bufrwl); - data = *(u32 *)pld; // pld aliases sc_buf - read_unlock(&sc_bufrwl); - - for (i = 0; i < tvselmts; i++) { - fmt = (tvs[i].val == data) ? "[%s] " : "%s "; - out += sprintf(out, fmt, tvs[i].str); - } - - out += sprintf(out, "\n"); - return out - buf; -} - -static ssize_t sc_tag_store_u32tvs(const u8 *pld, u16 pld_len, const char *buf, size_t count, - const struct sc_u32tvs tvs[], const int tvselmts) -{ - int i; - - if (tvselmts < 0) - return tvselmts; - - if (sizeof(u32) != pld_len) - return -EINVAL; - - for (i = 0; i < tvselmts; i++) { - if (sysfs_streq(buf, tvs[i].str)) { - write_lock(&sc_bufrwl); - *(u32 *)pld = tvs[i].val; // pld aliases sc_buf - RB_SC_CLRCRC(); - write_unlock(&sc_bufrwl); - return count; - } - } - - return -EINVAL; -} - -struct sc_boolts { - const char *strfalse; - const char *strtrue; -}; - -static ssize_t sc_tag_show_boolts(const u8 *pld, u16 pld_len, char *buf, - const struct sc_boolts *bts) -{ - const char *fmt; - char *out = buf; - u32 data; // cpu-endian - - if (sizeof(data) != pld_len) - return -EINVAL; - - read_lock(&sc_bufrwl); - data = *(u32 *)pld; // pld aliases sc_buf - read_unlock(&sc_bufrwl); - - fmt = (data) ? "%s [%s]\n" : "[%s] %s\n"; - out += sprintf(out, fmt, bts->strfalse, bts->strtrue); - - return out - buf; -} - -static ssize_t sc_tag_store_boolts(const u8 *pld, u16 pld_len, const char *buf, size_t count, - const struct sc_boolts *bts) -{ - u32 data; // cpu-endian - - if (sizeof(data) != pld_len) - return -EINVAL; - - if (sysfs_streq(buf, bts->strfalse)) - data = 0; - else if (sysfs_streq(buf, bts->strtrue)) - data = 1; - else - return -EINVAL; - - write_lock(&sc_bufrwl); - *(u32 *)pld = data; // pld aliases sc_buf - RB_SC_CLRCRC(); - write_unlock(&sc_bufrwl); - - return count; -} -static struct sc_u32tvs const sc_uartspeeds[] = { - RB_SC_TVS(RB_UART_SPEED_OFF, "off"), - RB_SC_TVS(RB_UART_SPEED_1200, "1200"), - RB_SC_TVS(RB_UART_SPEED_2400, "2400"), - RB_SC_TVS(RB_UART_SPEED_4800, "4800"), - RB_SC_TVS(RB_UART_SPEED_9600, "9600"), - RB_SC_TVS(RB_UART_SPEED_19200, "19200"), - RB_SC_TVS(RB_UART_SPEED_38400, "38400"), - RB_SC_TVS(RB_UART_SPEED_57600, "57600"), - RB_SC_TVS(RB_UART_SPEED_115200, "115200"), -}; - -/* - * While the defines are carried over from rbcfg, use strings that more clearly - * show the actual setting purpose (especially since the NAND* settings apply - * to both nand- and nor-based devices). "cfcard" was disabled in rbcfg: disable - * it here too. - */ -static struct sc_u32tvs const sc_bootdevices[] = { - RB_SC_TVS(RB_BOOT_DEVICE_ETHER, "eth"), - RB_SC_TVS(RB_BOOT_DEVICE_NANDETH, "flasheth"), - //RB_SC_TVS(RB_BOOT_DEVICE_CFCARD, "cfcard"), - RB_SC_TVS(RB_BOOT_DEVICE_ETHONCE, "ethonce"), - RB_SC_TVS(RB_BOOT_DEVICE_NANDONLY, "flash"), - RB_SC_TVS(RB_BOOT_DEVICE_FLASHCFG, "cfg"), - RB_SC_TVS(RB_BOOT_DEVICE_FLSHONCE, "cfgonce"), -}; - -static struct sc_boolts const sc_bootkey = { - .strfalse = "any", - .strtrue = "del", -}; - -static struct sc_boolts const sc_cpumode = { - .strfalse = "powersave", - .strtrue = "regular", -}; - -static struct sc_boolts const sc_bootproto = { - .strfalse = "bootp", - .strtrue = "dhcp", -}; - -static struct sc_boolts const sc_booter = { - .strfalse = "regular", - .strtrue = "backup", -}; - -static struct sc_boolts const sc_silent_boot = { - .strfalse = "off", - .strtrue = "on", -}; - -#define SC_TAG_SHOW_STORE_U32TVS_FUNCS(_name) \ -static ssize_t sc_tag_show_##_name(const u8 *pld, u16 pld_len, char *buf) \ -{ \ - return sc_tag_show_u32tvs(pld, pld_len, buf, sc_##_name, ARRAY_SIZE(sc_##_name)); \ -} \ -static ssize_t sc_tag_store_##_name(const u8 *pld, u16 pld_len, const char *buf, size_t count) \ -{ \ - return sc_tag_store_u32tvs(pld, pld_len, buf, count, sc_##_name, ARRAY_SIZE(sc_##_name)); \ -} - -#define SC_TAG_SHOW_STORE_BOOLTS_FUNCS(_name) \ -static ssize_t sc_tag_show_##_name(const u8 *pld, u16 pld_len, char *buf) \ -{ \ - return sc_tag_show_boolts(pld, pld_len, buf, &sc_##_name); \ -} \ -static ssize_t sc_tag_store_##_name(const u8 *pld, u16 pld_len, const char *buf, size_t count) \ -{ \ - return sc_tag_store_boolts(pld, pld_len, buf, count, &sc_##_name); \ -} - -SC_TAG_SHOW_STORE_U32TVS_FUNCS(uartspeeds) -SC_TAG_SHOW_STORE_U32TVS_FUNCS(bootdevices) -SC_TAG_SHOW_STORE_BOOLTS_FUNCS(bootkey) -SC_TAG_SHOW_STORE_BOOLTS_FUNCS(cpumode) -SC_TAG_SHOW_STORE_BOOLTS_FUNCS(bootproto) -SC_TAG_SHOW_STORE_BOOLTS_FUNCS(booter) -SC_TAG_SHOW_STORE_BOOLTS_FUNCS(silent_boot) - -static ssize_t sc_tag_show_bootdelays(const u8 *pld, u16 pld_len, char *buf) -{ - const char *fmt; - char *out = buf; - u32 data; // cpu-endian - int i; - - if (sizeof(data) != pld_len) - return -EINVAL; - - read_lock(&sc_bufrwl); - data = *(u32 *)pld; // pld aliases sc_buf - read_unlock(&sc_bufrwl); - - for (i = RB_BOOT_DELAY_MIN; i <= RB_BOOT_DELAY_MAX; i++) { - fmt = (i == data) ? "[%d] " : "%d "; - out += sprintf(out, fmt, i); - } - - out += sprintf(out, "\n"); - return out - buf; -} - -static ssize_t sc_tag_store_bootdelays(const u8 *pld, u16 pld_len, const char *buf, size_t count) -{ - u32 data; // cpu-endian - int ret; - - if (sizeof(data) != pld_len) - return -EINVAL; - - ret = kstrtou32(buf, 10, &data); - if (ret) - return ret; - - if ((data < RB_BOOT_DELAY_MIN) || (RB_BOOT_DELAY_MAX < data)) - return -EINVAL; - - write_lock(&sc_bufrwl); - *(u32 *)pld = data; // pld aliases sc_buf - RB_SC_CLRCRC(); - write_unlock(&sc_bufrwl); - - return count; -} - -/* Support CPU frequency accessors only when the tag format has been asserted */ -#if defined(CONFIG_ATH79) -/* Use the same letter-based nomenclature as RouterBOOT */ -static struct sc_u32tvs const sc_cpufreq_indexes_ath79_9x[] = { - RB_SC_TVS(RB_CPU_FREQ_IDX_ATH79_9X_A, "a"), - RB_SC_TVS(RB_CPU_FREQ_IDX_ATH79_9X_B, "b"), - RB_SC_TVS(RB_CPU_FREQ_IDX_ATH79_9X_C, "c"), - RB_SC_TVS(RB_CPU_FREQ_IDX_ATH79_9X_D, "d"), - RB_SC_TVS(RB_CPU_FREQ_IDX_ATH79_9X_E, "e"), - RB_SC_TVS(RB_CPU_FREQ_IDX_ATH79_9X_F, "f"), -}; - -static struct sc_u32tvs const sc_cpufreq_indexes_ath79_7x[] = { - RB_SC_TVS(RB_CPU_FREQ_IDX_ATH79_7X_A, "a"), - RB_SC_TVS(RB_CPU_FREQ_IDX_ATH79_7X_B, "b"), - RB_SC_TVS(RB_CPU_FREQ_IDX_ATH79_7X_C, "c"), - RB_SC_TVS(RB_CPU_FREQ_IDX_ATH79_7X_D, "d"), - RB_SC_TVS(RB_CPU_FREQ_IDX_ATH79_7X_E, "e"), - RB_SC_TVS(RB_CPU_FREQ_IDX_ATH79_7X_F, "f"), - RB_SC_TVS(RB_CPU_FREQ_IDX_ATH79_7X_G, "g"), - RB_SC_TVS(RB_CPU_FREQ_IDX_ATH79_7X_H, "h"), -}; - -static int sc_tag_cpufreq_ath79_arraysize(void) -{ - int idx_max; - - if (ATH79_SOC_AR7161 == ath79_soc) - idx_max = RB_CPU_FREQ_IDX_ATH79_7X_AR7161_MAX+1; - else if (soc_is_ar724x()) - idx_max = RB_CPU_FREQ_IDX_ATH79_7X_AR724X_MAX+1; - else if (soc_is_ar9344()) - idx_max = RB_CPU_FREQ_IDX_ATH79_9X_AR9334_MAX+1; - else if (soc_is_qca953x()) - idx_max = RB_CPU_FREQ_IDX_ATH79_9X_QCA953X_MAX+1; - else if (soc_is_qca9556()) - idx_max = RB_CPU_FREQ_IDX_ATH79_9X_QCA9556_MAX+1; - else if (soc_is_qca9558()) - idx_max = RB_CPU_FREQ_IDX_ATH79_9X_QCA9558_MAX+1; - else - idx_max = -EOPNOTSUPP; - - return idx_max; -} - -static ssize_t sc_tag_show_cpufreq_indexes(const u8 *pld, u16 pld_len, char *buf) -{ - const struct sc_u32tvs *tvs; - - if (soc_is_ar71xx() || soc_is_ar724x()) - tvs = sc_cpufreq_indexes_ath79_7x; - else - tvs = sc_cpufreq_indexes_ath79_9x; - - return sc_tag_show_u32tvs(pld, pld_len, buf, tvs, sc_tag_cpufreq_ath79_arraysize()); -} - -static ssize_t sc_tag_store_cpufreq_indexes(const u8 *pld, u16 pld_len, const char *buf, size_t count) -{ - const struct sc_u32tvs *tvs; - - if (soc_is_ar71xx() || soc_is_ar724x()) - tvs = sc_cpufreq_indexes_ath79_7x; - else - tvs = sc_cpufreq_indexes_ath79_9x; - - return sc_tag_store_u32tvs(pld, pld_len, buf, count, tvs, sc_tag_cpufreq_ath79_arraysize()); -} -#else - /* By default we only show the raw value to help with reverse-engineering */ - #define sc_tag_show_cpufreq_indexes routerboot_tag_show_u32s - #define sc_tag_store_cpufreq_indexes NULL -#endif - -static ssize_t sc_attr_show(struct kobject *kobj, struct kobj_attribute *attr, - char *buf); -static ssize_t sc_attr_store(struct kobject *kobj, struct kobj_attribute *attr, - const char *buf, size_t count); - -/* Array of known tags to publish in sysfs */ -static struct sc_attr { - const u16 tag_id; - /* sysfs tag show attribute. Must lock sc_buf when dereferencing pld */ - ssize_t (* const tshow)(const u8 *pld, u16 pld_len, char *buf); - /* sysfs tag store attribute. Must lock sc_buf when dereferencing pld */ - ssize_t (* const tstore)(const u8 *pld, u16 pld_len, const char *buf, size_t count); - struct kobj_attribute kattr; - u16 pld_ofs; - u16 pld_len; -} sc_attrs[] = { - { - .tag_id = RB_SCID_UART_SPEED, - .tshow = sc_tag_show_uartspeeds, - .tstore = sc_tag_store_uartspeeds, - .kattr = __ATTR(uart_speed, RB_SC_RMODE|RB_SC_WMODE, sc_attr_show, sc_attr_store), - }, { - .tag_id = RB_SCID_BOOT_DELAY, - .tshow = sc_tag_show_bootdelays, - .tstore = sc_tag_store_bootdelays, - .kattr = __ATTR(boot_delay, RB_SC_RMODE|RB_SC_WMODE, sc_attr_show, sc_attr_store), - }, { - .tag_id = RB_SCID_BOOT_DEVICE, - .tshow = sc_tag_show_bootdevices, - .tstore = sc_tag_store_bootdevices, - .kattr = __ATTR(boot_device, RB_SC_RMODE|RB_SC_WMODE, sc_attr_show, sc_attr_store), - }, { - .tag_id = RB_SCID_BOOT_KEY, - .tshow = sc_tag_show_bootkey, - .tstore = sc_tag_store_bootkey, - .kattr = __ATTR(boot_key, RB_SC_RMODE|RB_SC_WMODE, sc_attr_show, sc_attr_store), - }, { - .tag_id = RB_SCID_CPU_MODE, - .tshow = sc_tag_show_cpumode, - .tstore = sc_tag_store_cpumode, - .kattr = __ATTR(cpu_mode, RB_SC_RMODE|RB_SC_WMODE, sc_attr_show, sc_attr_store), - }, { - .tag_id = RB_SCID_BIOS_VERSION, - .tshow = routerboot_tag_show_string, - .tstore = NULL, - .kattr = __ATTR(bios_version, RB_SC_RMODE, sc_attr_show, NULL), - }, { - .tag_id = RB_SCID_BOOT_PROTOCOL, - .tshow = sc_tag_show_bootproto, - .tstore = sc_tag_store_bootproto, - .kattr = __ATTR(boot_proto, RB_SC_RMODE|RB_SC_WMODE, sc_attr_show, sc_attr_store), - }, { - .tag_id = RB_SCID_CPU_FREQ_IDX, - .tshow = sc_tag_show_cpufreq_indexes, - .tstore = sc_tag_store_cpufreq_indexes, - .kattr = __ATTR(cpufreq_index, RB_SC_RMODE|RB_SC_WMODE, sc_attr_show, sc_attr_store), - }, { - .tag_id = RB_SCID_BOOTER, - .tshow = sc_tag_show_booter, - .tstore = sc_tag_store_booter, - .kattr = __ATTR(booter, RB_SC_RMODE|RB_SC_WMODE, sc_attr_show, sc_attr_store), - }, { - .tag_id = RB_SCID_SILENT_BOOT, - .tshow = sc_tag_show_silent_boot, - .tstore = sc_tag_store_silent_boot, - .kattr = __ATTR(silent_boot, RB_SC_RMODE|RB_SC_WMODE, sc_attr_show, sc_attr_store), - }, -}; - -static ssize_t sc_attr_show(struct kobject *kobj, struct kobj_attribute *attr, - char *buf) -{ - const struct sc_attr *sc_attr; - const u8 *pld; - u16 pld_len; - - sc_attr = container_of(attr, typeof(*sc_attr), kattr); - - if (!sc_attr->pld_len) - return -ENOENT; - - pld = sc_buf + sc_attr->pld_ofs; // pld aliases sc_buf -> lock! - pld_len = sc_attr->pld_len; - - return sc_attr->tshow(pld, pld_len, buf); -} - -static ssize_t sc_attr_store(struct kobject *kobj, struct kobj_attribute *attr, - const char *buf, size_t count) -{ - const struct sc_attr *sc_attr; - const u8 *pld; - u16 pld_len; - - if (!RB_SC_HAS_WRITE_SUPPORT) - return -EOPNOTSUPP; - - if (!capable(CAP_SYS_ADMIN)) - return -EACCES; - - sc_attr = container_of(attr, typeof(*sc_attr), kattr); - - if (!sc_attr->tstore) - return -EOPNOTSUPP; - - if (!sc_attr->pld_len) - return -ENOENT; - - pld = sc_buf + sc_attr->pld_ofs; // pld aliases sc_buf -> lock! - pld_len = sc_attr->pld_len; - - return sc_attr->tstore(pld, pld_len, buf, count); -} - -/* - * Shows the current buffer status: - * "clean": the buffer is in sync with the mtd data - * "dirty": the buffer is out of sync with the mtd data - */ -static ssize_t sc_commit_show(struct kobject *kobj, struct kobj_attribute *attr, - char *buf) -{ - const char *str; - char *out = buf; - u32 crc; - - read_lock(&sc_bufrwl); - crc = RB_SC_GETCRC(); - read_unlock(&sc_bufrwl); - - str = (crc) ? "clean" : "dirty"; - out += sprintf(out, "%s\n", str); - - return out - buf; -} - -/* - * Performs buffer flushing: - * This routine expects an input compatible with kstrtobool(). - * - a "false" input discards the current changes and reads data back from mtd. - * - a "true" input commits the current changes to mtd. - * If there is no pending changes, this routine is a no-op. - * Handling failures is left as an exercise to userspace. - */ -static ssize_t sc_commit_store(struct kobject *kobj, struct kobj_attribute *attr, - const char *buf, size_t count) -{ - struct mtd_info *mtd; - struct erase_info ei; - size_t bytes_rw, ret = count; - bool flush; - u32 crc; - - if (!RB_SC_HAS_WRITE_SUPPORT) - return -EOPNOTSUPP; - - read_lock(&sc_bufrwl); - crc = RB_SC_GETCRC(); - read_unlock(&sc_bufrwl); - - if (crc) - return count; // NO-OP - - ret = kstrtobool(buf, &flush); - if (ret) - return ret; - - mtd = get_mtd_device_nm(RB_MTD_SOFT_CONFIG); // TODO allow override - if (IS_ERR(mtd)) - return -ENODEV; - - write_lock(&sc_bufrwl); - if (!flush) // reread - ret = mtd_read(mtd, 0, mtd->size, &bytes_rw, sc_buf); - else { // crc32 + commit - /* - * CRC32 is computed on the entire buffer, excluding the CRC - * value itself. CRC is already null when we reach this point, - * so we can compute the CRC32 on the buffer as is. - * The expected CRC32 is Ethernet FCS style, meaning the seed is - * ~0 and the final result is also bitflipped. - */ - - crc = ~crc32(~0, sc_buf, sc_buflen); - RB_SC_SETCRC(crc); - - /* - * The soft_config partition is assumed to be entirely contained - * in a single eraseblock. - */ - - ei.addr = 0; - ei.len = mtd->size; - ret = mtd_erase(mtd, &ei); - if (!ret) - ret = mtd_write(mtd, 0, mtd->size, &bytes_rw, sc_buf); - - /* - * Handling mtd_write() failure here is a tricky situation. The - * proposed approach is to let userspace deal with retrying, - * with the caveat that it must try to flush the buffer again as - * rereading the mtd contents could potentially read garbage. - * The rationale is: even if we keep a shadow buffer of the - * original content, there is no guarantee that we will ever be - * able to write it anyway. - * Regardless, it appears that RouterBOOT will ignore an invalid - * soft_config (including a completely wiped segment) and will - * write back factory defaults when it happens. - */ - } - write_unlock(&sc_bufrwl); - - put_mtd_device(mtd); - - if (ret) - goto mtdfail; - - if (bytes_rw != sc_buflen) { - ret = -EIO; - goto mtdfail; - } - - return count; - -mtdfail: - RB_SC_CLRCRC(); // mark buffer content as dirty/invalid - return ret; -} - -static struct kobj_attribute sc_kattrcommit = __ATTR(commit, RB_SC_RMODE|RB_SC_WMODE, sc_commit_show, sc_commit_store); - -int rb_softconfig_init(struct kobject *rb_kobj, struct mtd_info *mtd) -{ - size_t bytes_read, buflen; - const u8 *buf; - int i, ret; - u32 magic; - - sc_buf = NULL; - sc_kobj = NULL; - - ret = __get_mtd_device(mtd); - if (ret) - return -ENODEV; - - sc_buflen = mtd->size; - sc_buf = kmalloc(sc_buflen, GFP_KERNEL); - if (!sc_buf) { - __put_mtd_device(mtd); - return -ENOMEM; - } - - ret = mtd_read(mtd, 0, sc_buflen, &bytes_read, sc_buf); - __put_mtd_device(mtd); - - if (ret) - goto fail; - - if (bytes_read != sc_buflen) { - ret = -EIO; - goto fail; - } - - /* Check we have what we expect */ - magic = *(const u32 *)sc_buf; - if (RB_MAGIC_SOFT != magic) { - ret = -EINVAL; - goto fail; - } - - /* Skip magic and 32bit CRC located immediately after */ - buf = sc_buf + (sizeof(magic) + sizeof(u32)); - buflen = sc_buflen - (sizeof(magic) + sizeof(u32)); - - /* Populate sysfs */ - ret = -ENOMEM; - sc_kobj = kobject_create_and_add(RB_MTD_SOFT_CONFIG, rb_kobj); - if (!sc_kobj) - goto fail; - - rwlock_init(&sc_bufrwl); - - /* Locate and publish all known tags */ - for (i = 0; i < ARRAY_SIZE(sc_attrs); i++) { - ret = routerboot_tag_find(buf, buflen, sc_attrs[i].tag_id, - &sc_attrs[i].pld_ofs, &sc_attrs[i].pld_len); - if (ret) { - sc_attrs[i].pld_ofs = sc_attrs[i].pld_len = 0; - continue; - } - - /* Account for skipped magic and crc32 */ - sc_attrs[i].pld_ofs += sizeof(magic) + sizeof(u32); - - ret = sysfs_create_file(sc_kobj, &sc_attrs[i].kattr.attr); - if (ret) - pr_warn(RB_SC_PR_PFX "Could not create %s sysfs entry (%d)\n", - sc_attrs[i].kattr.attr.name, ret); - } - - /* Finally add the 'commit' attribute */ - if (RB_SC_HAS_WRITE_SUPPORT) { - ret = sysfs_create_file(sc_kobj, &sc_kattrcommit.attr); - if (ret) { - pr_err(RB_SC_PR_PFX "Could not create %s sysfs entry (%d), aborting!\n", - sc_kattrcommit.attr.name, ret); - goto sysfsfail; // required attribute - } - } - - pr_info("MikroTik RouterBOARD software configuration sysfs driver v" RB_SOFTCONFIG_VER "\n"); - - return 0; - -sysfsfail: - kobject_put(sc_kobj); - sc_kobj = NULL; -fail: - kfree(sc_buf); - sc_buf = NULL; - return ret; -} - -void rb_softconfig_exit(void) -{ - kobject_put(sc_kobj); - sc_kobj = NULL; - kfree(sc_buf); - sc_buf = NULL; -} diff --git a/target/linux/generic/files-6.12/drivers/platform/mikrotik/routerboot.c b/target/linux/generic/files-6.12/drivers/platform/mikrotik/routerboot.c deleted file mode 100644 index 96f24609161bab..00000000000000 --- a/target/linux/generic/files-6.12/drivers/platform/mikrotik/routerboot.c +++ /dev/null @@ -1,251 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Driver for MikroTik RouterBoot flash data. Common routines. - * - * Copyright (C) 2020 Thibaut VARÈNE - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published - * by the Free Software Foundation. - */ - -#include -#include -#include -#include -#include - -#include "routerboot.h" - -static struct kobject *rb_kobj; - -/** - * routerboot_tag_find() - Locate a given tag in routerboot config data. - * @bufhead: the buffer to look into. Must start with a tag node. - * @buflen: size of bufhead - * @tag_id: the tag identifier to look for - * @pld_ofs: will be updated with tag payload offset in bufhead, if tag found - * @pld_len: will be updated with tag payload size, if tag found - * - * This incarnation of tag_find() does only that: it finds a specific routerboot - * tag node in the input buffer. Routerboot tag nodes are u32 values: - * - The low nibble is the tag identification number, - * - The high nibble is the tag payload length (node excluded) in bytes. - * The payload immediately follows the tag node. Tag nodes are 32bit-aligned. - * The returned pld_ofs will always be aligned. pld_len may not end on 32bit - * boundary (the only known case is when parsing ERD data). - * The nodes are cpu-endian on the flash media. The payload is cpu-endian when - * applicable. Tag nodes are not ordered (by ID) on flash. - * - * Return: 0 on success (tag found) or errno - */ -int routerboot_tag_find(const u8 *bufhead, const size_t buflen, const u16 tag_id, - u16 *pld_ofs, u16 *pld_len) -{ - const u32 *datum, *bufend; - u32 node; - u16 id, len; - int ret; - - if (!bufhead || !tag_id) - return -EINVAL; - - ret = -ENOENT; - datum = (const u32 *)bufhead; - bufend = (const u32 *)(bufhead + buflen); - - while (datum < bufend) { - node = *datum++; - - /* Tag list ends with null node */ - if (!node) - break; - - id = node & 0xFFFF; - len = node >> 16; - - if (tag_id == id) { - if (datum >= bufend) - break; - - if (pld_ofs) - *pld_ofs = (u16)((u8 *)datum - bufhead); - if (pld_len) - *pld_len = len; - - ret = 0; - break; - } - - /* - * The only known situation where len may not end on 32bit - * boundary is within ERD data. Since we're only extracting - * one tag (the first and only one) from that data, we should - * never need to forcefully ALIGN(). Do it anyway, this is not a - * performance path. - */ - len = ALIGN(len, sizeof(*datum)); - datum += len / sizeof(*datum); - } - - return ret; -} - -/** - * routerboot_rle_decode() - Simple RLE (MikroTik variant) decoding routine. - * @in: input buffer to decode - * @inlen: size of in - * @out: output buffer to write decoded data to - * @outlen: pointer to out size when function is called, will be updated with - * size of decoded output on return - * - * MikroTik's variant of RLE operates as follows, considering a signed run byte: - * - positive run => classic RLE - * - negative run => the next - bytes must be copied verbatim - * The API is matched to the lzo1x routines for convenience. - * - * NB: The output buffer cannot overlap with the input buffer. - * - * Return: 0 on success or errno - */ -int routerboot_rle_decode(const u8 *in, size_t inlen, u8 *out, size_t *outlen) -{ - int ret, run, nbytes; // use native types for speed - u8 byte; - - if (!in || (inlen < 2) || !out) - return -EINVAL; - - ret = -ENOSPC; - nbytes = 0; - while (inlen >= 2) { - run = *in++; - inlen--; - - /* Verbatim copies */ - if (run & 0x80) { - /* Invert run byte sign */ - run = ~run & 0xFF; - run++; - - if (run > inlen) - goto fail; - - inlen -= run; - - nbytes += run; - if (nbytes > *outlen) - goto fail; - - /* Basic memcpy */ - while (run-- > 0) - *out++ = *in++; - } - /* Stream of half-words RLE: . run == 0 is ignored */ - else { - byte = *in++; - inlen--; - - nbytes += run; - if (nbytes > *outlen) - goto fail; - - while (run-- > 0) - *out++ = byte; - } - } - - ret = 0; -fail: - *outlen = nbytes; - return ret; -} - -static void routerboot_mtd_notifier_add(struct mtd_info *mtd) -{ - /* Currently routerboot is only known to live on NOR flash */ - if (mtd->type != MTD_NORFLASH) - return; - - /* - * We ignore the following return values and always register. - * These init() routines are designed so that their failed state is - * always manageable by the corresponding exit() calls. - * Notifier is called with MTD mutex held: use __get/__put variants. - * TODO: allow partition names override - */ - if (!strcmp(mtd->name, RB_MTD_HARD_CONFIG)) - rb_hardconfig_init(rb_kobj, mtd); - else if (!strcmp(mtd->name, RB_MTD_SOFT_CONFIG)) - rb_softconfig_init(rb_kobj, mtd); -} - -static void routerboot_mtd_notifier_remove(struct mtd_info *mtd) -{ - if (mtd->type != MTD_NORFLASH) - return; - - if (!strcmp(mtd->name, RB_MTD_HARD_CONFIG)) - rb_hardconfig_exit(); - else if (!strcmp(mtd->name, RB_MTD_SOFT_CONFIG)) - rb_softconfig_exit(); -} - -/* Note: using a notifier prevents qualifying init()/exit() functions with __init/__exit */ -static struct mtd_notifier routerboot_mtd_notifier = { - .add = routerboot_mtd_notifier_add, - .remove = routerboot_mtd_notifier_remove, -}; - -static int __init routerboot_init(void) -{ - rb_kobj = kobject_create_and_add("mikrotik", firmware_kobj); - if (!rb_kobj) - return -ENOMEM; - - register_mtd_user(&routerboot_mtd_notifier); - - return 0; -} - -static void __exit routerboot_exit(void) -{ - unregister_mtd_user(&routerboot_mtd_notifier); - /* Exit routines are idempotent */ - rb_softconfig_exit(); - rb_hardconfig_exit(); - kobject_put(rb_kobj); // recursive afaict -} - -/* Common routines */ - -ssize_t routerboot_tag_show_string(const u8 *pld, u16 pld_len, char *buf) -{ - return scnprintf(buf, pld_len+1, "%s\n", pld); -} - -ssize_t routerboot_tag_show_u32s(const u8 *pld, u16 pld_len, char *buf) -{ - char *out = buf; - u32 *data; // cpu-endian - - /* Caller ensures pld_len > 0 */ - if (pld_len % sizeof(*data)) - return -EINVAL; - - data = (u32 *)pld; - - do { - out += sprintf(out, "0x%08x\n", *data); - data++; - } while ((pld_len -= sizeof(*data))); - - return out - buf; -} - -module_init(routerboot_init); -module_exit(routerboot_exit); - -MODULE_LICENSE("GPL v2"); -MODULE_DESCRIPTION("MikroTik RouterBoot sysfs support"); -MODULE_AUTHOR("Thibaut VARENE"); diff --git a/target/linux/generic/files-6.12/drivers/platform/mikrotik/routerboot.h b/target/linux/generic/files-6.12/drivers/platform/mikrotik/routerboot.h deleted file mode 100644 index 723f993eebe2c1..00000000000000 --- a/target/linux/generic/files-6.12/drivers/platform/mikrotik/routerboot.h +++ /dev/null @@ -1,38 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Common definitions for MikroTik RouterBoot data. - * - * Copyright (C) 2020 Thibaut VARÈNE - */ - - -#ifndef _ROUTERBOOT_H_ -#define _ROUTERBOOT_H_ - -#include - -// these magic values are stored in cpu-endianness on flash -#define RB_MAGIC_HARD (('H') | ('a' << 8) | ('r' << 16) | ('d' << 24)) -#define RB_MAGIC_SOFT (('S') | ('o' << 8) | ('f' << 16) | ('t' << 24)) -#define RB_MAGIC_LZOR (('L') | ('Z' << 8) | ('O' << 16) | ('R' << 24)) -#define RB_MAGIC_LZ77 (('L' << 24) | ('Z' << 16) | ('7' << 8) | ('7')) -#define RB_MAGIC_ERD (('E' << 16) | ('R' << 8) | ('D')) - -#define RB_ART_SIZE 0x10000 - -#define RB_MTD_HARD_CONFIG "hard_config" -#define RB_MTD_SOFT_CONFIG "soft_config" - -int routerboot_tag_find(const u8 *bufhead, const size_t buflen, const u16 tag_id, u16 *pld_ofs, u16 *pld_len); -int routerboot_rle_decode(const u8 *in, size_t inlen, u8 *out, size_t *outlen); - -int rb_hardconfig_init(struct kobject *rb_kobj, struct mtd_info *mtd); -void rb_hardconfig_exit(void); - -int rb_softconfig_init(struct kobject *rb_kobj, struct mtd_info *mtd); -void rb_softconfig_exit(void); - -ssize_t routerboot_tag_show_string(const u8 *pld, u16 pld_len, char *buf); -ssize_t routerboot_tag_show_u32s(const u8 *pld, u16 pld_len, char *buf); - -#endif /* _ROUTERBOOT_H_ */ diff --git a/target/linux/generic/files-6.12/drivers/ssb/fallback-sprom.c b/target/linux/generic/files-6.12/drivers/ssb/fallback-sprom.c deleted file mode 100644 index b8a4dcedcf4f1c..00000000000000 --- a/target/linux/generic/files-6.12/drivers/ssb/fallback-sprom.c +++ /dev/null @@ -1,744 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * SSB Fallback SPROM Driver - * - * Copyright (C) 2020 Álvaro Fernández Rojas - * Copyright (C) 2014 Jonas Gorski - * Copyright (C) 2008 Maxime Bizon - * Copyright (C) 2008 Florian Fainelli - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#define SSB_FBS_MAX_SIZE 440 - -/* Get the word-offset for a SSB_SPROM_XXX define. */ -#define SPOFF(offset) ((offset) / sizeof(u16)) -/* Helper to extract some _offset, which is one of the SSB_SPROM_XXX defines. */ -#define SPEX16(_outvar, _offset, _mask, _shift) \ - out->_outvar = ((in[SPOFF(_offset)] & (_mask)) >> (_shift)) -#define SPEX32(_outvar, _offset, _mask, _shift) \ - out->_outvar = ((((u32)in[SPOFF((_offset)+2)] << 16 | \ - in[SPOFF(_offset)]) & (_mask)) >> (_shift)) -#define SPEX(_outvar, _offset, _mask, _shift) \ - SPEX16(_outvar, _offset, _mask, _shift) - -#define SPEX_ARRAY8(_field, _offset, _mask, _shift) \ - do { \ - SPEX(_field[0], _offset + 0, _mask, _shift); \ - SPEX(_field[1], _offset + 2, _mask, _shift); \ - SPEX(_field[2], _offset + 4, _mask, _shift); \ - SPEX(_field[3], _offset + 6, _mask, _shift); \ - SPEX(_field[4], _offset + 8, _mask, _shift); \ - SPEX(_field[5], _offset + 10, _mask, _shift); \ - SPEX(_field[6], _offset + 12, _mask, _shift); \ - SPEX(_field[7], _offset + 14, _mask, _shift); \ - } while (0) - -struct ssb_fbs { - struct device *dev; - struct list_head list; - struct ssb_sprom sprom; - u32 pci_bus; - u32 pci_dev; - bool devid_override; -}; - -static DEFINE_SPINLOCK(ssb_fbs_lock); -static struct list_head ssb_fbs_list = LIST_HEAD_INIT(ssb_fbs_list); - -int ssb_get_fallback_sprom(struct ssb_bus *bus, struct ssb_sprom *out) -{ - struct ssb_fbs *pos; - u32 pci_bus, pci_dev; - - if (bus->bustype != SSB_BUSTYPE_PCI) - return -ENOENT; - - pci_bus = bus->host_pci->bus->number; - pci_dev = PCI_SLOT(bus->host_pci->devfn); - - list_for_each_entry(pos, &ssb_fbs_list, list) { - if (pos->pci_bus != pci_bus || - pos->pci_dev != pci_dev) - continue; - - if (pos->devid_override) - bus->host_pci->device = pos->sprom.dev_id; - - memcpy(out, &pos->sprom, sizeof(struct ssb_sprom)); - dev_info(pos->dev, "requested by [%x:%x]", - pos->pci_bus, pos->pci_dev); - - return 0; - } - - pr_err("unable to fill SPROM for [%x:%x]\n", pci_bus, pci_dev); - - return -EINVAL; -} - -static s8 sprom_extract_antgain(u8 sprom_revision, const u16 *in, u16 offset, - u16 mask, u16 shift) -{ - u16 v; - u8 gain; - - v = in[SPOFF(offset)]; - gain = (v & mask) >> shift; - if (gain == 0xFF) - gain = 2; /* If unset use 2dBm */ - if (sprom_revision == 1) { - /* Convert to Q5.2 */ - gain <<= 2; - } else { - /* Q5.2 Fractional part is stored in 0xC0 */ - gain = ((gain & 0xC0) >> 6) | ((gain & 0x3F) << 2); - } - - return (s8)gain; -} - -static void sprom_extract_r23(struct ssb_sprom *out, const u16 *in) -{ - SPEX(boardflags_hi, SSB_SPROM2_BFLHI, 0xFFFF, 0); - SPEX(opo, SSB_SPROM2_OPO, SSB_SPROM2_OPO_VALUE, 0); - SPEX(pa1lob0, SSB_SPROM2_PA1LOB0, 0xFFFF, 0); - SPEX(pa1lob1, SSB_SPROM2_PA1LOB1, 0xFFFF, 0); - SPEX(pa1lob2, SSB_SPROM2_PA1LOB2, 0xFFFF, 0); - SPEX(pa1hib0, SSB_SPROM2_PA1HIB0, 0xFFFF, 0); - SPEX(pa1hib1, SSB_SPROM2_PA1HIB1, 0xFFFF, 0); - SPEX(pa1hib2, SSB_SPROM2_PA1HIB2, 0xFFFF, 0); - SPEX(maxpwr_ah, SSB_SPROM2_MAXP_A, SSB_SPROM2_MAXP_A_HI, 0); - SPEX(maxpwr_al, SSB_SPROM2_MAXP_A, SSB_SPROM2_MAXP_A_LO, - SSB_SPROM2_MAXP_A_LO_SHIFT); -} - -static void sprom_extract_r123(struct ssb_sprom *out, const u16 *in) -{ - SPEX(et0phyaddr, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET0A, 0); - SPEX(et1phyaddr, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET1A, - SSB_SPROM1_ETHPHY_ET1A_SHIFT); - SPEX(et0mdcport, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET0M, 14); - SPEX(et1mdcport, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET1M, 15); - SPEX(board_rev, SSB_SPROM1_BINF, SSB_SPROM1_BINF_BREV, 0); - SPEX(board_type, SSB_SPROM1_SPID, 0xFFFF, 0); - if (out->revision == 1) - SPEX(country_code, SSB_SPROM1_BINF, SSB_SPROM1_BINF_CCODE, - SSB_SPROM1_BINF_CCODE_SHIFT); - SPEX(ant_available_a, SSB_SPROM1_BINF, SSB_SPROM1_BINF_ANTA, - SSB_SPROM1_BINF_ANTA_SHIFT); - SPEX(ant_available_bg, SSB_SPROM1_BINF, SSB_SPROM1_BINF_ANTBG, - SSB_SPROM1_BINF_ANTBG_SHIFT); - SPEX(pa0b0, SSB_SPROM1_PA0B0, 0xFFFF, 0); - SPEX(pa0b1, SSB_SPROM1_PA0B1, 0xFFFF, 0); - SPEX(pa0b2, SSB_SPROM1_PA0B2, 0xFFFF, 0); - SPEX(pa1b0, SSB_SPROM1_PA1B0, 0xFFFF, 0); - SPEX(pa1b1, SSB_SPROM1_PA1B1, 0xFFFF, 0); - SPEX(pa1b2, SSB_SPROM1_PA1B2, 0xFFFF, 0); - SPEX(gpio0, SSB_SPROM1_GPIOA, SSB_SPROM1_GPIOA_P0, 0); - SPEX(gpio1, SSB_SPROM1_GPIOA, SSB_SPROM1_GPIOA_P1, - SSB_SPROM1_GPIOA_P1_SHIFT); - SPEX(gpio2, SSB_SPROM1_GPIOB, SSB_SPROM1_GPIOB_P2, 0); - SPEX(gpio3, SSB_SPROM1_GPIOB, SSB_SPROM1_GPIOB_P3, - SSB_SPROM1_GPIOB_P3_SHIFT); - SPEX(maxpwr_a, SSB_SPROM1_MAXPWR, SSB_SPROM1_MAXPWR_A, - SSB_SPROM1_MAXPWR_A_SHIFT); - SPEX(maxpwr_bg, SSB_SPROM1_MAXPWR, SSB_SPROM1_MAXPWR_BG, 0); - SPEX(itssi_a, SSB_SPROM1_ITSSI, SSB_SPROM1_ITSSI_A, - SSB_SPROM1_ITSSI_A_SHIFT); - SPEX(itssi_bg, SSB_SPROM1_ITSSI, SSB_SPROM1_ITSSI_BG, 0); - SPEX(boardflags_lo, SSB_SPROM1_BFLLO, 0xFFFF, 0); - - SPEX(alpha2[0], SSB_SPROM1_CCODE, 0xff00, 8); - SPEX(alpha2[1], SSB_SPROM1_CCODE, 0x00ff, 0); - - /* Extract the antenna gain values. */ - out->antenna_gain.a0 = sprom_extract_antgain(out->revision, in, - SSB_SPROM1_AGAIN, - SSB_SPROM1_AGAIN_BG, - SSB_SPROM1_AGAIN_BG_SHIFT); - out->antenna_gain.a1 = sprom_extract_antgain(out->revision, in, - SSB_SPROM1_AGAIN, - SSB_SPROM1_AGAIN_A, - SSB_SPROM1_AGAIN_A_SHIFT); - if (out->revision >= 2) - sprom_extract_r23(out, in); -} - -/* Revs 4 5 and 8 have partially shared layout */ -static void sprom_extract_r458(struct ssb_sprom *out, const u16 *in) -{ - SPEX(txpid2g[0], SSB_SPROM4_TXPID2G01, - SSB_SPROM4_TXPID2G0, SSB_SPROM4_TXPID2G0_SHIFT); - SPEX(txpid2g[1], SSB_SPROM4_TXPID2G01, - SSB_SPROM4_TXPID2G1, SSB_SPROM4_TXPID2G1_SHIFT); - SPEX(txpid2g[2], SSB_SPROM4_TXPID2G23, - SSB_SPROM4_TXPID2G2, SSB_SPROM4_TXPID2G2_SHIFT); - SPEX(txpid2g[3], SSB_SPROM4_TXPID2G23, - SSB_SPROM4_TXPID2G3, SSB_SPROM4_TXPID2G3_SHIFT); - - SPEX(txpid5gl[0], SSB_SPROM4_TXPID5GL01, - SSB_SPROM4_TXPID5GL0, SSB_SPROM4_TXPID5GL0_SHIFT); - SPEX(txpid5gl[1], SSB_SPROM4_TXPID5GL01, - SSB_SPROM4_TXPID5GL1, SSB_SPROM4_TXPID5GL1_SHIFT); - SPEX(txpid5gl[2], SSB_SPROM4_TXPID5GL23, - SSB_SPROM4_TXPID5GL2, SSB_SPROM4_TXPID5GL2_SHIFT); - SPEX(txpid5gl[3], SSB_SPROM4_TXPID5GL23, - SSB_SPROM4_TXPID5GL3, SSB_SPROM4_TXPID5GL3_SHIFT); - - SPEX(txpid5g[0], SSB_SPROM4_TXPID5G01, - SSB_SPROM4_TXPID5G0, SSB_SPROM4_TXPID5G0_SHIFT); - SPEX(txpid5g[1], SSB_SPROM4_TXPID5G01, - SSB_SPROM4_TXPID5G1, SSB_SPROM4_TXPID5G1_SHIFT); - SPEX(txpid5g[2], SSB_SPROM4_TXPID5G23, - SSB_SPROM4_TXPID5G2, SSB_SPROM4_TXPID5G2_SHIFT); - SPEX(txpid5g[3], SSB_SPROM4_TXPID5G23, - SSB_SPROM4_TXPID5G3, SSB_SPROM4_TXPID5G3_SHIFT); - - SPEX(txpid5gh[0], SSB_SPROM4_TXPID5GH01, - SSB_SPROM4_TXPID5GH0, SSB_SPROM4_TXPID5GH0_SHIFT); - SPEX(txpid5gh[1], SSB_SPROM4_TXPID5GH01, - SSB_SPROM4_TXPID5GH1, SSB_SPROM4_TXPID5GH1_SHIFT); - SPEX(txpid5gh[2], SSB_SPROM4_TXPID5GH23, - SSB_SPROM4_TXPID5GH2, SSB_SPROM4_TXPID5GH2_SHIFT); - SPEX(txpid5gh[3], SSB_SPROM4_TXPID5GH23, - SSB_SPROM4_TXPID5GH3, SSB_SPROM4_TXPID5GH3_SHIFT); -} - -static void sprom_extract_r45(struct ssb_sprom *out, const u16 *in) -{ - static const u16 pwr_info_offset[] = { - SSB_SPROM4_PWR_INFO_CORE0, SSB_SPROM4_PWR_INFO_CORE1, - SSB_SPROM4_PWR_INFO_CORE2, SSB_SPROM4_PWR_INFO_CORE3 - }; - int i; - - BUILD_BUG_ON(ARRAY_SIZE(pwr_info_offset) != - ARRAY_SIZE(out->core_pwr_info)); - - SPEX(et0phyaddr, SSB_SPROM4_ETHPHY, SSB_SPROM4_ETHPHY_ET0A, 0); - SPEX(et1phyaddr, SSB_SPROM4_ETHPHY, SSB_SPROM4_ETHPHY_ET1A, - SSB_SPROM4_ETHPHY_ET1A_SHIFT); - SPEX(board_rev, SSB_SPROM4_BOARDREV, 0xFFFF, 0); - SPEX(board_type, SSB_SPROM1_SPID, 0xFFFF, 0); - if (out->revision == 4) { - SPEX(alpha2[0], SSB_SPROM4_CCODE, 0xff00, 8); - SPEX(alpha2[1], SSB_SPROM4_CCODE, 0x00ff, 0); - SPEX(boardflags_lo, SSB_SPROM4_BFLLO, 0xFFFF, 0); - SPEX(boardflags_hi, SSB_SPROM4_BFLHI, 0xFFFF, 0); - SPEX(boardflags2_lo, SSB_SPROM4_BFL2LO, 0xFFFF, 0); - SPEX(boardflags2_hi, SSB_SPROM4_BFL2HI, 0xFFFF, 0); - } else { - SPEX(alpha2[0], SSB_SPROM5_CCODE, 0xff00, 8); - SPEX(alpha2[1], SSB_SPROM5_CCODE, 0x00ff, 0); - SPEX(boardflags_lo, SSB_SPROM5_BFLLO, 0xFFFF, 0); - SPEX(boardflags_hi, SSB_SPROM5_BFLHI, 0xFFFF, 0); - SPEX(boardflags2_lo, SSB_SPROM5_BFL2LO, 0xFFFF, 0); - SPEX(boardflags2_hi, SSB_SPROM5_BFL2HI, 0xFFFF, 0); - } - SPEX(ant_available_a, SSB_SPROM4_ANTAVAIL, SSB_SPROM4_ANTAVAIL_A, - SSB_SPROM4_ANTAVAIL_A_SHIFT); - SPEX(ant_available_bg, SSB_SPROM4_ANTAVAIL, SSB_SPROM4_ANTAVAIL_BG, - SSB_SPROM4_ANTAVAIL_BG_SHIFT); - SPEX(maxpwr_bg, SSB_SPROM4_MAXP_BG, SSB_SPROM4_MAXP_BG_MASK, 0); - SPEX(itssi_bg, SSB_SPROM4_MAXP_BG, SSB_SPROM4_ITSSI_BG, - SSB_SPROM4_ITSSI_BG_SHIFT); - SPEX(maxpwr_a, SSB_SPROM4_MAXP_A, SSB_SPROM4_MAXP_A_MASK, 0); - SPEX(itssi_a, SSB_SPROM4_MAXP_A, SSB_SPROM4_ITSSI_A, - SSB_SPROM4_ITSSI_A_SHIFT); - if (out->revision == 4) { - SPEX(gpio0, SSB_SPROM4_GPIOA, SSB_SPROM4_GPIOA_P0, 0); - SPEX(gpio1, SSB_SPROM4_GPIOA, SSB_SPROM4_GPIOA_P1, - SSB_SPROM4_GPIOA_P1_SHIFT); - SPEX(gpio2, SSB_SPROM4_GPIOB, SSB_SPROM4_GPIOB_P2, 0); - SPEX(gpio3, SSB_SPROM4_GPIOB, SSB_SPROM4_GPIOB_P3, - SSB_SPROM4_GPIOB_P3_SHIFT); - } else { - SPEX(gpio0, SSB_SPROM5_GPIOA, SSB_SPROM5_GPIOA_P0, 0); - SPEX(gpio1, SSB_SPROM5_GPIOA, SSB_SPROM5_GPIOA_P1, - SSB_SPROM5_GPIOA_P1_SHIFT); - SPEX(gpio2, SSB_SPROM5_GPIOB, SSB_SPROM5_GPIOB_P2, 0); - SPEX(gpio3, SSB_SPROM5_GPIOB, SSB_SPROM5_GPIOB_P3, - SSB_SPROM5_GPIOB_P3_SHIFT); - } - - /* Extract the antenna gain values. */ - out->antenna_gain.a0 = sprom_extract_antgain(out->revision, in, - SSB_SPROM4_AGAIN01, - SSB_SPROM4_AGAIN0, - SSB_SPROM4_AGAIN0_SHIFT); - out->antenna_gain.a1 = sprom_extract_antgain(out->revision, in, - SSB_SPROM4_AGAIN01, - SSB_SPROM4_AGAIN1, - SSB_SPROM4_AGAIN1_SHIFT); - out->antenna_gain.a2 = sprom_extract_antgain(out->revision, in, - SSB_SPROM4_AGAIN23, - SSB_SPROM4_AGAIN2, - SSB_SPROM4_AGAIN2_SHIFT); - out->antenna_gain.a3 = sprom_extract_antgain(out->revision, in, - SSB_SPROM4_AGAIN23, - SSB_SPROM4_AGAIN3, - SSB_SPROM4_AGAIN3_SHIFT); - - /* Extract cores power info info */ - for (i = 0; i < ARRAY_SIZE(pwr_info_offset); i++) { - u16 o = pwr_info_offset[i]; - - SPEX(core_pwr_info[i].itssi_2g, o + SSB_SPROM4_2G_MAXP_ITSSI, - SSB_SPROM4_2G_ITSSI, SSB_SPROM4_2G_ITSSI_SHIFT); - SPEX(core_pwr_info[i].maxpwr_2g, o + SSB_SPROM4_2G_MAXP_ITSSI, - SSB_SPROM4_2G_MAXP, 0); - - SPEX(core_pwr_info[i].pa_2g[0], o + SSB_SPROM4_2G_PA_0, ~0, 0); - SPEX(core_pwr_info[i].pa_2g[1], o + SSB_SPROM4_2G_PA_1, ~0, 0); - SPEX(core_pwr_info[i].pa_2g[2], o + SSB_SPROM4_2G_PA_2, ~0, 0); - SPEX(core_pwr_info[i].pa_2g[3], o + SSB_SPROM4_2G_PA_3, ~0, 0); - - SPEX(core_pwr_info[i].itssi_5g, o + SSB_SPROM4_5G_MAXP_ITSSI, - SSB_SPROM4_5G_ITSSI, SSB_SPROM4_5G_ITSSI_SHIFT); - SPEX(core_pwr_info[i].maxpwr_5g, o + SSB_SPROM4_5G_MAXP_ITSSI, - SSB_SPROM4_5G_MAXP, 0); - SPEX(core_pwr_info[i].maxpwr_5gh, o + SSB_SPROM4_5GHL_MAXP, - SSB_SPROM4_5GH_MAXP, 0); - SPEX(core_pwr_info[i].maxpwr_5gl, o + SSB_SPROM4_5GHL_MAXP, - SSB_SPROM4_5GL_MAXP, SSB_SPROM4_5GL_MAXP_SHIFT); - - SPEX(core_pwr_info[i].pa_5gl[0], o + SSB_SPROM4_5GL_PA_0, ~0, 0); - SPEX(core_pwr_info[i].pa_5gl[1], o + SSB_SPROM4_5GL_PA_1, ~0, 0); - SPEX(core_pwr_info[i].pa_5gl[2], o + SSB_SPROM4_5GL_PA_2, ~0, 0); - SPEX(core_pwr_info[i].pa_5gl[3], o + SSB_SPROM4_5GL_PA_3, ~0, 0); - SPEX(core_pwr_info[i].pa_5g[0], o + SSB_SPROM4_5G_PA_0, ~0, 0); - SPEX(core_pwr_info[i].pa_5g[1], o + SSB_SPROM4_5G_PA_1, ~0, 0); - SPEX(core_pwr_info[i].pa_5g[2], o + SSB_SPROM4_5G_PA_2, ~0, 0); - SPEX(core_pwr_info[i].pa_5g[3], o + SSB_SPROM4_5G_PA_3, ~0, 0); - SPEX(core_pwr_info[i].pa_5gh[0], o + SSB_SPROM4_5GH_PA_0, ~0, 0); - SPEX(core_pwr_info[i].pa_5gh[1], o + SSB_SPROM4_5GH_PA_1, ~0, 0); - SPEX(core_pwr_info[i].pa_5gh[2], o + SSB_SPROM4_5GH_PA_2, ~0, 0); - SPEX(core_pwr_info[i].pa_5gh[3], o + SSB_SPROM4_5GH_PA_3, ~0, 0); - } - - sprom_extract_r458(out, in); - - /* TODO - get remaining rev 4 stuff needed */ -} - -static void sprom_extract_r8(struct ssb_sprom *out, const u16 *in) -{ - int i; - u16 o; - static const u16 pwr_info_offset[] = { - SSB_SROM8_PWR_INFO_CORE0, SSB_SROM8_PWR_INFO_CORE1, - SSB_SROM8_PWR_INFO_CORE2, SSB_SROM8_PWR_INFO_CORE3 - }; - BUILD_BUG_ON(ARRAY_SIZE(pwr_info_offset) != - ARRAY_SIZE(out->core_pwr_info)); - - SPEX(board_rev, SSB_SPROM8_BOARDREV, 0xFFFF, 0); - SPEX(board_type, SSB_SPROM1_SPID, 0xFFFF, 0); - SPEX(alpha2[0], SSB_SPROM8_CCODE, 0xff00, 8); - SPEX(alpha2[1], SSB_SPROM8_CCODE, 0x00ff, 0); - SPEX(boardflags_lo, SSB_SPROM8_BFLLO, 0xFFFF, 0); - SPEX(boardflags_hi, SSB_SPROM8_BFLHI, 0xFFFF, 0); - SPEX(boardflags2_lo, SSB_SPROM8_BFL2LO, 0xFFFF, 0); - SPEX(boardflags2_hi, SSB_SPROM8_BFL2HI, 0xFFFF, 0); - SPEX(ant_available_a, SSB_SPROM8_ANTAVAIL, SSB_SPROM8_ANTAVAIL_A, - SSB_SPROM8_ANTAVAIL_A_SHIFT); - SPEX(ant_available_bg, SSB_SPROM8_ANTAVAIL, SSB_SPROM8_ANTAVAIL_BG, - SSB_SPROM8_ANTAVAIL_BG_SHIFT); - SPEX(maxpwr_bg, SSB_SPROM8_MAXP_BG, SSB_SPROM8_MAXP_BG_MASK, 0); - SPEX(itssi_bg, SSB_SPROM8_MAXP_BG, SSB_SPROM8_ITSSI_BG, - SSB_SPROM8_ITSSI_BG_SHIFT); - SPEX(maxpwr_a, SSB_SPROM8_MAXP_A, SSB_SPROM8_MAXP_A_MASK, 0); - SPEX(itssi_a, SSB_SPROM8_MAXP_A, SSB_SPROM8_ITSSI_A, - SSB_SPROM8_ITSSI_A_SHIFT); - SPEX(maxpwr_ah, SSB_SPROM8_MAXP_AHL, SSB_SPROM8_MAXP_AH_MASK, 0); - SPEX(maxpwr_al, SSB_SPROM8_MAXP_AHL, SSB_SPROM8_MAXP_AL_MASK, - SSB_SPROM8_MAXP_AL_SHIFT); - SPEX(gpio0, SSB_SPROM8_GPIOA, SSB_SPROM8_GPIOA_P0, 0); - SPEX(gpio1, SSB_SPROM8_GPIOA, SSB_SPROM8_GPIOA_P1, - SSB_SPROM8_GPIOA_P1_SHIFT); - SPEX(gpio2, SSB_SPROM8_GPIOB, SSB_SPROM8_GPIOB_P2, 0); - SPEX(gpio3, SSB_SPROM8_GPIOB, SSB_SPROM8_GPIOB_P3, - SSB_SPROM8_GPIOB_P3_SHIFT); - SPEX(tri2g, SSB_SPROM8_TRI25G, SSB_SPROM8_TRI2G, 0); - SPEX(tri5g, SSB_SPROM8_TRI25G, SSB_SPROM8_TRI5G, - SSB_SPROM8_TRI5G_SHIFT); - SPEX(tri5gl, SSB_SPROM8_TRI5GHL, SSB_SPROM8_TRI5GL, 0); - SPEX(tri5gh, SSB_SPROM8_TRI5GHL, SSB_SPROM8_TRI5GH, - SSB_SPROM8_TRI5GH_SHIFT); - SPEX(rxpo2g, SSB_SPROM8_RXPO, SSB_SPROM8_RXPO2G, 0); - SPEX(rxpo5g, SSB_SPROM8_RXPO, SSB_SPROM8_RXPO5G, - SSB_SPROM8_RXPO5G_SHIFT); - SPEX(rssismf2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_RSSISMF2G, 0); - SPEX(rssismc2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_RSSISMC2G, - SSB_SPROM8_RSSISMC2G_SHIFT); - SPEX(rssisav2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_RSSISAV2G, - SSB_SPROM8_RSSISAV2G_SHIFT); - SPEX(bxa2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_BXA2G, - SSB_SPROM8_BXA2G_SHIFT); - SPEX(rssismf5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_RSSISMF5G, 0); - SPEX(rssismc5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_RSSISMC5G, - SSB_SPROM8_RSSISMC5G_SHIFT); - SPEX(rssisav5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_RSSISAV5G, - SSB_SPROM8_RSSISAV5G_SHIFT); - SPEX(bxa5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_BXA5G, - SSB_SPROM8_BXA5G_SHIFT); - SPEX(pa0b0, SSB_SPROM8_PA0B0, 0xFFFF, 0); - SPEX(pa0b1, SSB_SPROM8_PA0B1, 0xFFFF, 0); - SPEX(pa0b2, SSB_SPROM8_PA0B2, 0xFFFF, 0); - SPEX(pa1b0, SSB_SPROM8_PA1B0, 0xFFFF, 0); - SPEX(pa1b1, SSB_SPROM8_PA1B1, 0xFFFF, 0); - SPEX(pa1b2, SSB_SPROM8_PA1B2, 0xFFFF, 0); - SPEX(pa1lob0, SSB_SPROM8_PA1LOB0, 0xFFFF, 0); - SPEX(pa1lob1, SSB_SPROM8_PA1LOB1, 0xFFFF, 0); - SPEX(pa1lob2, SSB_SPROM8_PA1LOB2, 0xFFFF, 0); - SPEX(pa1hib0, SSB_SPROM8_PA1HIB0, 0xFFFF, 0); - SPEX(pa1hib1, SSB_SPROM8_PA1HIB1, 0xFFFF, 0); - SPEX(pa1hib2, SSB_SPROM8_PA1HIB2, 0xFFFF, 0); - SPEX(cck2gpo, SSB_SPROM8_CCK2GPO, 0xFFFF, 0); - SPEX32(ofdm2gpo, SSB_SPROM8_OFDM2GPO, 0xFFFFFFFF, 0); - SPEX32(ofdm5glpo, SSB_SPROM8_OFDM5GLPO, 0xFFFFFFFF, 0); - SPEX32(ofdm5gpo, SSB_SPROM8_OFDM5GPO, 0xFFFFFFFF, 0); - SPEX32(ofdm5ghpo, SSB_SPROM8_OFDM5GHPO, 0xFFFFFFFF, 0); - - /* Extract the antenna gain values. */ - out->antenna_gain.a0 = sprom_extract_antgain(out->revision, in, - SSB_SPROM8_AGAIN01, - SSB_SPROM8_AGAIN0, - SSB_SPROM8_AGAIN0_SHIFT); - out->antenna_gain.a1 = sprom_extract_antgain(out->revision, in, - SSB_SPROM8_AGAIN01, - SSB_SPROM8_AGAIN1, - SSB_SPROM8_AGAIN1_SHIFT); - out->antenna_gain.a2 = sprom_extract_antgain(out->revision, in, - SSB_SPROM8_AGAIN23, - SSB_SPROM8_AGAIN2, - SSB_SPROM8_AGAIN2_SHIFT); - out->antenna_gain.a3 = sprom_extract_antgain(out->revision, in, - SSB_SPROM8_AGAIN23, - SSB_SPROM8_AGAIN3, - SSB_SPROM8_AGAIN3_SHIFT); - - /* Extract cores power info info */ - for (i = 0; i < ARRAY_SIZE(pwr_info_offset); i++) { - o = pwr_info_offset[i]; - SPEX(core_pwr_info[i].itssi_2g, o + SSB_SROM8_2G_MAXP_ITSSI, - SSB_SPROM8_2G_ITSSI, SSB_SPROM8_2G_ITSSI_SHIFT); - SPEX(core_pwr_info[i].maxpwr_2g, o + SSB_SROM8_2G_MAXP_ITSSI, - SSB_SPROM8_2G_MAXP, 0); - - SPEX(core_pwr_info[i].pa_2g[0], o + SSB_SROM8_2G_PA_0, ~0, 0); - SPEX(core_pwr_info[i].pa_2g[1], o + SSB_SROM8_2G_PA_1, ~0, 0); - SPEX(core_pwr_info[i].pa_2g[2], o + SSB_SROM8_2G_PA_2, ~0, 0); - - SPEX(core_pwr_info[i].itssi_5g, o + SSB_SROM8_5G_MAXP_ITSSI, - SSB_SPROM8_5G_ITSSI, SSB_SPROM8_5G_ITSSI_SHIFT); - SPEX(core_pwr_info[i].maxpwr_5g, o + SSB_SROM8_5G_MAXP_ITSSI, - SSB_SPROM8_5G_MAXP, 0); - SPEX(core_pwr_info[i].maxpwr_5gh, o + SSB_SPROM8_5GHL_MAXP, - SSB_SPROM8_5GH_MAXP, 0); - SPEX(core_pwr_info[i].maxpwr_5gl, o + SSB_SPROM8_5GHL_MAXP, - SSB_SPROM8_5GL_MAXP, SSB_SPROM8_5GL_MAXP_SHIFT); - - SPEX(core_pwr_info[i].pa_5gl[0], o + SSB_SROM8_5GL_PA_0, ~0, 0); - SPEX(core_pwr_info[i].pa_5gl[1], o + SSB_SROM8_5GL_PA_1, ~0, 0); - SPEX(core_pwr_info[i].pa_5gl[2], o + SSB_SROM8_5GL_PA_2, ~0, 0); - SPEX(core_pwr_info[i].pa_5g[0], o + SSB_SROM8_5G_PA_0, ~0, 0); - SPEX(core_pwr_info[i].pa_5g[1], o + SSB_SROM8_5G_PA_1, ~0, 0); - SPEX(core_pwr_info[i].pa_5g[2], o + SSB_SROM8_5G_PA_2, ~0, 0); - SPEX(core_pwr_info[i].pa_5gh[0], o + SSB_SROM8_5GH_PA_0, ~0, 0); - SPEX(core_pwr_info[i].pa_5gh[1], o + SSB_SROM8_5GH_PA_1, ~0, 0); - SPEX(core_pwr_info[i].pa_5gh[2], o + SSB_SROM8_5GH_PA_2, ~0, 0); - } - - /* Extract FEM info */ - SPEX(fem.ghz2.tssipos, SSB_SPROM8_FEM2G, - SSB_SROM8_FEM_TSSIPOS, SSB_SROM8_FEM_TSSIPOS_SHIFT); - SPEX(fem.ghz2.extpa_gain, SSB_SPROM8_FEM2G, - SSB_SROM8_FEM_EXTPA_GAIN, SSB_SROM8_FEM_EXTPA_GAIN_SHIFT); - SPEX(fem.ghz2.pdet_range, SSB_SPROM8_FEM2G, - SSB_SROM8_FEM_PDET_RANGE, SSB_SROM8_FEM_PDET_RANGE_SHIFT); - SPEX(fem.ghz2.tr_iso, SSB_SPROM8_FEM2G, - SSB_SROM8_FEM_TR_ISO, SSB_SROM8_FEM_TR_ISO_SHIFT); - SPEX(fem.ghz2.antswlut, SSB_SPROM8_FEM2G, - SSB_SROM8_FEM_ANTSWLUT, SSB_SROM8_FEM_ANTSWLUT_SHIFT); - - SPEX(fem.ghz5.tssipos, SSB_SPROM8_FEM5G, - SSB_SROM8_FEM_TSSIPOS, SSB_SROM8_FEM_TSSIPOS_SHIFT); - SPEX(fem.ghz5.extpa_gain, SSB_SPROM8_FEM5G, - SSB_SROM8_FEM_EXTPA_GAIN, SSB_SROM8_FEM_EXTPA_GAIN_SHIFT); - SPEX(fem.ghz5.pdet_range, SSB_SPROM8_FEM5G, - SSB_SROM8_FEM_PDET_RANGE, SSB_SROM8_FEM_PDET_RANGE_SHIFT); - SPEX(fem.ghz5.tr_iso, SSB_SPROM8_FEM5G, - SSB_SROM8_FEM_TR_ISO, SSB_SROM8_FEM_TR_ISO_SHIFT); - SPEX(fem.ghz5.antswlut, SSB_SPROM8_FEM5G, - SSB_SROM8_FEM_ANTSWLUT, SSB_SROM8_FEM_ANTSWLUT_SHIFT); - - SPEX(leddc_on_time, SSB_SPROM8_LEDDC, SSB_SPROM8_LEDDC_ON, - SSB_SPROM8_LEDDC_ON_SHIFT); - SPEX(leddc_off_time, SSB_SPROM8_LEDDC, SSB_SPROM8_LEDDC_OFF, - SSB_SPROM8_LEDDC_OFF_SHIFT); - - SPEX(txchain, SSB_SPROM8_TXRXC, SSB_SPROM8_TXRXC_TXCHAIN, - SSB_SPROM8_TXRXC_TXCHAIN_SHIFT); - SPEX(rxchain, SSB_SPROM8_TXRXC, SSB_SPROM8_TXRXC_RXCHAIN, - SSB_SPROM8_TXRXC_RXCHAIN_SHIFT); - SPEX(antswitch, SSB_SPROM8_TXRXC, SSB_SPROM8_TXRXC_SWITCH, - SSB_SPROM8_TXRXC_SWITCH_SHIFT); - - SPEX(opo, SSB_SPROM8_OFDM2GPO, 0x00ff, 0); - - SPEX_ARRAY8(mcs2gpo, SSB_SPROM8_2G_MCSPO, ~0, 0); - SPEX_ARRAY8(mcs5gpo, SSB_SPROM8_5G_MCSPO, ~0, 0); - SPEX_ARRAY8(mcs5glpo, SSB_SPROM8_5GL_MCSPO, ~0, 0); - SPEX_ARRAY8(mcs5ghpo, SSB_SPROM8_5GH_MCSPO, ~0, 0); - - SPEX(rawtempsense, SSB_SPROM8_RAWTS, SSB_SPROM8_RAWTS_RAWTEMP, - SSB_SPROM8_RAWTS_RAWTEMP_SHIFT); - SPEX(measpower, SSB_SPROM8_RAWTS, SSB_SPROM8_RAWTS_MEASPOWER, - SSB_SPROM8_RAWTS_MEASPOWER_SHIFT); - SPEX(tempsense_slope, SSB_SPROM8_OPT_CORRX, - SSB_SPROM8_OPT_CORRX_TEMP_SLOPE, - SSB_SPROM8_OPT_CORRX_TEMP_SLOPE_SHIFT); - SPEX(tempcorrx, SSB_SPROM8_OPT_CORRX, SSB_SPROM8_OPT_CORRX_TEMPCORRX, - SSB_SPROM8_OPT_CORRX_TEMPCORRX_SHIFT); - SPEX(tempsense_option, SSB_SPROM8_OPT_CORRX, - SSB_SPROM8_OPT_CORRX_TEMP_OPTION, - SSB_SPROM8_OPT_CORRX_TEMP_OPTION_SHIFT); - SPEX(freqoffset_corr, SSB_SPROM8_HWIQ_IQSWP, - SSB_SPROM8_HWIQ_IQSWP_FREQ_CORR, - SSB_SPROM8_HWIQ_IQSWP_FREQ_CORR_SHIFT); - SPEX(iqcal_swp_dis, SSB_SPROM8_HWIQ_IQSWP, - SSB_SPROM8_HWIQ_IQSWP_IQCAL_SWP, - SSB_SPROM8_HWIQ_IQSWP_IQCAL_SWP_SHIFT); - SPEX(hw_iqcal_en, SSB_SPROM8_HWIQ_IQSWP, SSB_SPROM8_HWIQ_IQSWP_HW_IQCAL, - SSB_SPROM8_HWIQ_IQSWP_HW_IQCAL_SHIFT); - - SPEX(bw40po, SSB_SPROM8_BW40PO, ~0, 0); - SPEX(cddpo, SSB_SPROM8_CDDPO, ~0, 0); - SPEX(stbcpo, SSB_SPROM8_STBCPO, ~0, 0); - SPEX(bwduppo, SSB_SPROM8_BWDUPPO, ~0, 0); - - SPEX(tempthresh, SSB_SPROM8_THERMAL, SSB_SPROM8_THERMAL_TRESH, - SSB_SPROM8_THERMAL_TRESH_SHIFT); - SPEX(tempoffset, SSB_SPROM8_THERMAL, SSB_SPROM8_THERMAL_OFFSET, - SSB_SPROM8_THERMAL_OFFSET_SHIFT); - SPEX(phycal_tempdelta, SSB_SPROM8_TEMPDELTA, - SSB_SPROM8_TEMPDELTA_PHYCAL, - SSB_SPROM8_TEMPDELTA_PHYCAL_SHIFT); - SPEX(temps_period, SSB_SPROM8_TEMPDELTA, SSB_SPROM8_TEMPDELTA_PERIOD, - SSB_SPROM8_TEMPDELTA_PERIOD_SHIFT); - SPEX(temps_hysteresis, SSB_SPROM8_TEMPDELTA, - SSB_SPROM8_TEMPDELTA_HYSTERESIS, - SSB_SPROM8_TEMPDELTA_HYSTERESIS_SHIFT); - sprom_extract_r458(out, in); - - /* TODO - get remaining rev 8 stuff needed */ -} - -static int sprom_extract(struct ssb_fbs *priv, const u16 *in, u16 size) -{ - struct ssb_sprom *out = &priv->sprom; - - memset(out, 0, sizeof(*out)); - - out->revision = in[size - 1] & 0x00FF; - - switch (out->revision) { - case 1: - case 2: - case 3: - sprom_extract_r123(out, in); - break; - case 4: - case 5: - sprom_extract_r45(out, in); - break; - case 8: - sprom_extract_r8(out, in); - break; - default: - dev_warn(priv->dev, - "Unsupported SPROM revision %d detected." - " Will extract v1\n", - out->revision); - out->revision = 1; - sprom_extract_r123(out, in); - } - - if (out->boardflags_lo == 0xFFFF) - out->boardflags_lo = 0; /* per specs */ - if (out->boardflags_hi == 0xFFFF) - out->boardflags_hi = 0; /* per specs */ - - return 0; -} - -static void ssb_fbs_fixup(struct ssb_fbs *priv, u16 *sprom) -{ - struct device_node *node = priv->dev->of_node; - u32 fixups, off, val; - int i = 0; - - if (!of_get_property(node, "brcm,sprom-fixups", &fixups)) - return; - - fixups /= sizeof(u32); - - dev_info(priv->dev, "patching SPROM with %u fixups...\n", fixups >> 1); - - while (i < fixups) { - if (of_property_read_u32_index(node, "brcm,sprom-fixups", - i++, &off)) { - dev_err(priv->dev, "error reading fixup[%u] offset\n", - i - 1); - return; - } - - if (of_property_read_u32_index(node, "brcm,sprom-fixups", - i++, &val)) { - dev_err(priv->dev, "error reading fixup[%u] value\n", - i - 1); - return; - } - - dev_dbg(priv->dev, "fixup[%d]=0x%04x\n", off, val); - - sprom[off] = val; - } -} - -static bool sprom_override_devid(struct ssb_fbs *priv, struct ssb_sprom *out, - const u16 *in) -{ - SPEX(dev_id, SSB_SPROM1_PID, 0xFFFF, 0); - return !!out->dev_id; -} - -static int ssb_fbs_set(struct ssb_fbs *priv, struct device_node *node) -{ - struct ssb_sprom *sprom = &priv->sprom; - const struct firmware *fw; - const char *sprom_name; - int err; - - if (of_property_read_string(node, "brcm,sprom", &sprom_name)) - sprom_name = NULL; - - if (sprom_name) { - err = request_firmware_direct(&fw, sprom_name, priv->dev); - if (err) - dev_err(priv->dev, "%s load error\n", sprom_name); - } else { - err = -ENOENT; - } - - if (err) { - sprom->revision = 0x02; - sprom->board_rev = 0x0017; - sprom->country_code = 0x00; - sprom->ant_available_bg = 0x03; - sprom->pa0b0 = 0x15ae; - sprom->pa0b1 = 0xfa85; - sprom->pa0b2 = 0xfe8d; - sprom->pa1b0 = 0xffff; - sprom->pa1b1 = 0xffff; - sprom->pa1b2 = 0xffff; - sprom->gpio0 = 0xff; - sprom->gpio1 = 0xff; - sprom->gpio2 = 0xff; - sprom->gpio3 = 0xff; - sprom->maxpwr_bg = 0x4c; - sprom->itssi_bg = 0x00; - sprom->boardflags_lo = 0x2848; - sprom->boardflags_hi = 0x0000; - priv->devid_override = false; - - dev_warn(priv->dev, "using basic SPROM\n"); - } else { - size_t size = min(fw->size, (size_t) SSB_FBS_MAX_SIZE); - u16 tmp_sprom[SSB_FBS_MAX_SIZE >> 1]; - u32 i, j; - - for (i = 0, j = 0; i < size; i += 2, j++) - tmp_sprom[j] = (fw->data[i] << 8) | fw->data[i + 1]; - - release_firmware(fw); - ssb_fbs_fixup(priv, tmp_sprom); - sprom_extract(priv, tmp_sprom, size >> 1); - - priv->devid_override = sprom_override_devid(priv, sprom, - tmp_sprom); - } - - return 0; -} - -static int ssb_fbs_probe(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - struct device_node *node = dev->of_node; - struct ssb_fbs *priv; - unsigned long flags; - u8 mac[ETH_ALEN]; - - priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); - if (!priv) - return -ENOMEM; - - priv->dev = dev; - - ssb_fbs_set(priv, node); - - of_property_read_u32(node, "pci-bus", &priv->pci_bus); - of_property_read_u32(node, "pci-dev", &priv->pci_dev); - - of_get_mac_address(node, mac); - if (is_valid_ether_addr(mac)) { - dev_info(dev, "mtd mac %pM\n", mac); - } else { - eth_random_addr(mac); - dev_info(dev, "random mac %pM\n", mac); - } - - memcpy(priv->sprom.il0mac, mac, ETH_ALEN); - memcpy(priv->sprom.et0mac, mac, ETH_ALEN); - memcpy(priv->sprom.et1mac, mac, ETH_ALEN); - memcpy(priv->sprom.et2mac, mac, ETH_ALEN); - - spin_lock_irqsave(&ssb_fbs_lock, flags); - list_add(&priv->list, &ssb_fbs_list); - spin_unlock_irqrestore(&ssb_fbs_lock, flags); - - dev_info(dev, "registered SPROM for [%x:%x]\n", - priv->pci_bus, priv->pci_dev); - - return 0; -} - -static const struct of_device_id ssb_fbs_of_match[] = { - { .compatible = "brcm,ssb-sprom", }, - { /* sentinel */ } -}; -MODULE_DEVICE_TABLE(of, ssb_fbs_of_match); - -static struct platform_driver ssb_fbs_driver = { - .probe = ssb_fbs_probe, - .driver = { - .name = "ssb-sprom", - .of_match_table = ssb_fbs_of_match, - }, -}; - -int __init ssb_fbs_register(void) -{ - return platform_driver_register(&ssb_fbs_driver); -} diff --git a/target/linux/generic/files-6.12/include/dt-bindings/mtd/partitions/uimage.h b/target/linux/generic/files-6.12/include/dt-bindings/mtd/partitions/uimage.h deleted file mode 100644 index 43d5f7b5da8798..00000000000000 --- a/target/linux/generic/files-6.12/include/dt-bindings/mtd/partitions/uimage.h +++ /dev/null @@ -1,198 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * *** IMPORTANT *** - * This file is not only included from C-code but also from devicetree source - * files. As such this file MUST only contain comments and defines. - * - * Based on image.h from U-Boot which is - * (C) Copyright 2008 Semihalf - * (C) Copyright 2000-2005 Wolfgang Denk, DENX Software Engineering, wd@denx.de. - */ - -#ifndef __UIMAGE_H__ -#define __UIMAGE_H__ - -/* - * Operating System Codes - * - * The following are exposed to uImage header. - * New IDs *MUST* be appended at the end of the list and *NEVER* - * inserted for backward compatibility. - */ -#define IH_OS_INVALID 0 /* Invalid OS */ -#define IH_OS_OPENBSD 1 /* OpenBSD */ -#define IH_OS_NETBSD 2 /* NetBSD */ -#define IH_OS_FREEBSD 3 /* FreeBSD */ -#define IH_OS_4_4BSD 4 /* 4.4BSD */ -#define IH_OS_LINUX 5 /* Linux */ -#define IH_OS_SVR4 6 /* SVR4 */ -#define IH_OS_ESIX 7 /* Esix */ -#define IH_OS_SOLARIS 8 /* Solaris */ -#define IH_OS_IRIX 9 /* Irix */ -#define IH_OS_SCO 10 /* SCO */ -#define IH_OS_DELL 11 /* Dell */ -#define IH_OS_NCR 12 /* NCR */ -#define IH_OS_LYNXOS 13 /* LynxOS */ -#define IH_OS_VXWORKS 14 /* VxWorks */ -#define IH_OS_PSOS 15 /* pSOS */ -#define IH_OS_QNX 16 /* QNX */ -#define IH_OS_U_BOOT 17 /* Firmware */ -#define IH_OS_RTEMS 18 /* RTEMS */ -#define IH_OS_ARTOS 19 /* ARTOS */ -#define IH_OS_UNITY 20 /* Unity OS */ -#define IH_OS_INTEGRITY 21 /* INTEGRITY */ -#define IH_OS_OSE 22 /* OSE */ -#define IH_OS_PLAN9 23 /* Plan 9 */ -#define IH_OS_OPENRTOS 24 /* OpenRTOS */ -#define IH_OS_ARM_TRUSTED_FIRMWARE 25 /* ARM Trusted Firmware */ -#define IH_OS_TEE 26 /* Trusted Execution Environment */ -#define IH_OS_OPENSBI 27 /* RISC-V OpenSBI */ -#define IH_OS_EFI 28 /* EFI Firmware (e.g. GRUB2) */ - -/* - * CPU Architecture Codes (supported by Linux) - * - * The following are exposed to uImage header. - * New IDs *MUST* be appended at the end of the list and *NEVER* - * inserted for backward compatibility. - */ -#define IH_ARCH_INVALID 0 /* Invalid CPU */ -#define IH_ARCH_ALPHA 1 /* Alpha */ -#define IH_ARCH_ARM 2 /* ARM */ -#define IH_ARCH_I386 3 /* Intel x86 */ -#define IH_ARCH_IA64 4 /* IA64 */ -#define IH_ARCH_MIPS 5 /* MIPS */ -#define IH_ARCH_MIPS64 6 /* MIPS 64 Bit */ -#define IH_ARCH_PPC 7 /* PowerPC */ -#define IH_ARCH_S390 8 /* IBM S390 */ -#define IH_ARCH_SH 9 /* SuperH */ -#define IH_ARCH_SPARC 10 /* Sparc */ -#define IH_ARCH_SPARC64 11 /* Sparc 64 Bit */ -#define IH_ARCH_M68K 12 /* M68K */ -#define IH_ARCH_NIOS 13 /* Nios-32 */ -#define IH_ARCH_MICROBLAZE 14 /* MicroBlaze */ -#define IH_ARCH_NIOS2 15 /* Nios-II */ -#define IH_ARCH_BLACKFIN 16 /* Blackfin */ -#define IH_ARCH_AVR32 17 /* AVR32 */ -#define IH_ARCH_ST200 18 /* STMicroelectronics ST200 */ -#define IH_ARCH_SANDBOX 19 /* Sandbox architecture (test only) */ -#define IH_ARCH_NDS32 20 /* ANDES Technology - NDS32 */ -#define IH_ARCH_OPENRISC 21 /* OpenRISC 1000 */ -#define IH_ARCH_ARM64 22 /* ARM64 */ -#define IH_ARCH_ARC 23 /* Synopsys DesignWare ARC */ -#define IH_ARCH_X86_64 24 /* AMD x86_64, Intel and Via */ -#define IH_ARCH_XTENSA 25 /* Xtensa */ -#define IH_ARCH_RISCV 26 /* RISC-V */ - -/* - * Image Types - * - * "Standalone Programs" are directly runnable in the environment - * provided by U-Boot; it is expected that (if they behave - * well) you can continue to work in U-Boot after return from - * the Standalone Program. - * "OS Kernel Images" are usually images of some Embedded OS which - * will take over control completely. Usually these programs - * will install their own set of exception handlers, device - * drivers, set up the MMU, etc. - this means, that you cannot - * expect to re-enter U-Boot except by resetting the CPU. - * "RAMDisk Images" are more or less just data blocks, and their - * parameters (address, size) are passed to an OS kernel that is - * being started. - * "Multi-File Images" contain several images, typically an OS - * (Linux) kernel image and one or more data images like - * RAMDisks. This construct is useful for instance when you want - * to boot over the network using BOOTP etc., where the boot - * server provides just a single image file, but you want to get - * for instance an OS kernel and a RAMDisk image. - * - * "Multi-File Images" start with a list of image sizes, each - * image size (in bytes) specified by an "uint32_t" in network - * byte order. This list is terminated by an "(uint32_t)0". - * Immediately after the terminating 0 follow the images, one by - * one, all aligned on "uint32_t" boundaries (size rounded up to - * a multiple of 4 bytes - except for the last file). - * - * "Firmware Images" are binary images containing firmware (like - * U-Boot or FPGA images) which usually will be programmed to - * flash memory. - * - * "Script files" are command sequences that will be executed by - * U-Boot's command interpreter; this feature is especially - * useful when you configure U-Boot to use a real shell (hush) - * as command interpreter (=> Shell Scripts). - * - * The following are exposed to uImage header. - * New IDs *MUST* be appended at the end of the list and *NEVER* - * inserted for backward compatibility. - */ -#define IH_TYPE_INVALID 0 /* Invalid Image */ -#define IH_TYPE_STANDALONE 1 /* Standalone Program */ -#define IH_TYPE_KERNEL 2 /* OS Kernel Image */ -#define IH_TYPE_RAMDISK 3 /* RAMDisk Image */ -#define IH_TYPE_MULTI 4 /* Multi-File Image */ -#define IH_TYPE_FIRMWARE 5 /* Firmware Image */ -#define IH_TYPE_SCRIPT 6 /* Script file */ -#define IH_TYPE_FILESYSTEM 7 /* Filesystem Image (any type) */ -#define IH_TYPE_FLATDT 8 /* Binary Flat Device Tree Blob */ -#define IH_TYPE_KWBIMAGE 9 /* Kirkwood Boot Image */ -#define IH_TYPE_IMXIMAGE 10 /* Freescale IMXBoot Image */ -#define IH_TYPE_UBLIMAGE 11 /* Davinci UBL Image */ -#define IH_TYPE_OMAPIMAGE 12 /* TI OMAP Config Header Image */ -#define IH_TYPE_AISIMAGE 13 /* TI Davinci AIS Image */ - /* OS Kernel Image, can run from any load address */ -#define IH_TYPE_KERNEL_NOLOAD 14 -#define IH_TYPE_PBLIMAGE 15 /* Freescale PBL Boot Image */ -#define IH_TYPE_MXSIMAGE 16 /* Freescale MXSBoot Image */ -#define IH_TYPE_GPIMAGE 17 /* TI Keystone GPHeader Image */ -#define IH_TYPE_ATMELIMAGE 18 /* ATMEL ROM bootable Image */ -#define IH_TYPE_SOCFPGAIMAGE 19 /* Altera SOCFPGA CV/AV Preloader */ -#define IH_TYPE_X86_SETUP 20 /* x86 setup.bin Image */ -#define IH_TYPE_LPC32XXIMAGE 21 /* x86 setup.bin Image */ -#define IH_TYPE_LOADABLE 22 /* A list of typeless images */ -#define IH_TYPE_RKIMAGE 23 /* Rockchip Boot Image */ -#define IH_TYPE_RKSD 24 /* Rockchip SD card */ -#define IH_TYPE_RKSPI 25 /* Rockchip SPI image */ -#define IH_TYPE_ZYNQIMAGE 26 /* Xilinx Zynq Boot Image */ -#define IH_TYPE_ZYNQMPIMAGE 27 /* Xilinx ZynqMP Boot Image */ -#define IH_TYPE_ZYNQMPBIF 28 /* Xilinx ZynqMP Boot Image (bif) */ -#define IH_TYPE_FPGA 29 /* FPGA Image */ -#define IH_TYPE_VYBRIDIMAGE 30 /* VYBRID .vyb Image */ -#define IH_TYPE_TEE 31 /* Trusted Execution Environment OS Image */ -#define IH_TYPE_FIRMWARE_IVT 32 /* Firmware Image with HABv4 IVT */ -#define IH_TYPE_PMMC 33 /* TI Power Management Micro-Controller Firmware */ -#define IH_TYPE_STM32IMAGE 34 /* STMicroelectronics STM32 Image */ -#define IH_TYPE_SOCFPGAIMAGE_V1 35 /* Altera SOCFPGA A10 Preloader */ -#define IH_TYPE_MTKIMAGE 36 /* MediaTek BootROM loadable Image */ -#define IH_TYPE_IMX8MIMAGE 37 /* Freescale IMX8MBoot Image */ -#define IH_TYPE_IMX8IMAGE 38 /* Freescale IMX8Boot Image */ -#define IH_TYPE_COPRO 39 /* Coprocessor Image for remoteproc*/ - - -/* - * Compression Types - * - * The following are exposed to uImage header. - * New IDs *MUST* be appended at the end of the list and *NEVER* - * inserted for backward compatibility. - */ -#define IH_COMP_NONE 0 /* No Compression Used */ -#define IH_COMP_GZIP 1 /* gzip Compression Used */ -#define IH_COMP_BZIP2 2 /* bzip2 Compression Used */ -#define IH_COMP_LZMA 3 /* lzma Compression Used */ -#define IH_COMP_LZO 4 /* lzo Compression Used */ -#define IH_COMP_LZ4 5 /* lz4 Compression Used */ - - -#define LZ4F_MAGIC 0x184D2204 /* LZ4 Magic Number */ -#define IH_MAGIC 0x27051956 /* Image Magic Number */ -#define IH_NMLEN 32 /* Image Name Length */ - -/* - * Magic values specific to "openwrt,uimage" partitions - */ -#define IH_MAGIC_OKLI 0x4f4b4c49 /* 'OKLI' */ -#define FW_EDIMAX_OFFSET 20 /* Edimax Firmware Offset */ -#define FW_MAGIC_EDIMAX 0x43535953 /* Edimax Firmware Magic Number */ - -#endif /* __UIMAGE_H__ */ diff --git a/target/linux/generic/files-6.12/include/linux/ar8216_platform.h b/target/linux/generic/files-6.12/include/linux/ar8216_platform.h deleted file mode 100644 index 24bc442a26d0ce..00000000000000 --- a/target/linux/generic/files-6.12/include/linux/ar8216_platform.h +++ /dev/null @@ -1,133 +0,0 @@ -/* - * AR8216 switch driver platform data - * - * Copyright (C) 2012 Gabor Juhos - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#ifndef AR8216_PLATFORM_H -#define AR8216_PLATFORM_H - -enum ar8327_pad_mode { - AR8327_PAD_NC = 0, - AR8327_PAD_MAC2MAC_MII, - AR8327_PAD_MAC2MAC_GMII, - AR8327_PAD_MAC_SGMII, - AR8327_PAD_MAC2PHY_MII, - AR8327_PAD_MAC2PHY_GMII, - AR8327_PAD_MAC_RGMII, - AR8327_PAD_PHY_GMII, - AR8327_PAD_PHY_RGMII, - AR8327_PAD_PHY_MII, -}; - -enum ar8327_clk_delay_sel { - AR8327_CLK_DELAY_SEL0 = 0, - AR8327_CLK_DELAY_SEL1, - AR8327_CLK_DELAY_SEL2, - AR8327_CLK_DELAY_SEL3, -}; - -struct ar8327_pad_cfg { - enum ar8327_pad_mode mode; - bool rxclk_sel; - bool txclk_sel; - bool pipe_rxclk_sel; - bool txclk_delay_en; - bool rxclk_delay_en; - bool sgmii_delay_en; - enum ar8327_clk_delay_sel txclk_delay_sel; - enum ar8327_clk_delay_sel rxclk_delay_sel; - bool mac06_exchange_dis; -}; - -enum ar8327_port_speed { - AR8327_PORT_SPEED_10 = 0, - AR8327_PORT_SPEED_100, - AR8327_PORT_SPEED_1000, -}; - -struct ar8327_port_cfg { - int force_link:1; - enum ar8327_port_speed speed; - int txpause:1; - int rxpause:1; - int duplex:1; -}; - -struct ar8327_sgmii_cfg { - u32 sgmii_ctrl; - bool serdes_aen; -}; - -struct ar8327_led_cfg { - u32 led_ctrl0; - u32 led_ctrl1; - u32 led_ctrl2; - u32 led_ctrl3; - bool open_drain; -}; - -enum ar8327_led_num { - AR8327_LED_PHY0_0 = 0, - AR8327_LED_PHY0_1, - AR8327_LED_PHY0_2, - AR8327_LED_PHY1_0, - AR8327_LED_PHY1_1, - AR8327_LED_PHY1_2, - AR8327_LED_PHY2_0, - AR8327_LED_PHY2_1, - AR8327_LED_PHY2_2, - AR8327_LED_PHY3_0, - AR8327_LED_PHY3_1, - AR8327_LED_PHY3_2, - AR8327_LED_PHY4_0, - AR8327_LED_PHY4_1, - AR8327_LED_PHY4_2, -}; - -enum ar8327_led_mode { - AR8327_LED_MODE_HW = 0, - AR8327_LED_MODE_SW, -}; - -struct ar8327_led_info { - const char *name; - const char *default_trigger; - bool active_low; - enum ar8327_led_num led_num; - enum ar8327_led_mode mode; -}; - -#define AR8327_LED_INFO(_led, _mode, _name) { \ - .name = (_name), \ - .led_num = AR8327_LED_ ## _led, \ - .mode = AR8327_LED_MODE_ ## _mode \ -} - -struct ar8327_platform_data { - struct ar8327_pad_cfg *pad0_cfg; - struct ar8327_pad_cfg *pad5_cfg; - struct ar8327_pad_cfg *pad6_cfg; - struct ar8327_sgmii_cfg *sgmii_cfg; - struct ar8327_port_cfg port0_cfg; - struct ar8327_port_cfg port6_cfg; - struct ar8327_led_cfg *led_cfg; - - int (*get_port_link)(unsigned port); - - unsigned num_leds; - const struct ar8327_led_info *leds; -}; - -#endif /* AR8216_PLATFORM_H */ - diff --git a/target/linux/generic/files-6.12/include/linux/ath5k_platform.h b/target/linux/generic/files-6.12/include/linux/ath5k_platform.h deleted file mode 100644 index ec8522452879ac..00000000000000 --- a/target/linux/generic/files-6.12/include/linux/ath5k_platform.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (c) 2008 Atheros Communications Inc. - * Copyright (c) 2009 Gabor Juhos - * Copyright (c) 2009 Imre Kaloz - * Copyright (c) 2010 Daniel Golle - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#ifndef _LINUX_ATH5K_PLATFORM_H -#define _LINUX_ATH5K_PLATFORM_H - -#define ATH5K_PLAT_EEP_MAX_WORDS 2048 - -struct ath5k_platform_data { - u16 *eeprom_data; - u8 *macaddr; -}; - -#endif /* _LINUX_ATH5K_PLATFORM_H */ diff --git a/target/linux/generic/files-6.12/include/linux/ath9k_platform.h b/target/linux/generic/files-6.12/include/linux/ath9k_platform.h deleted file mode 100644 index e210108568a690..00000000000000 --- a/target/linux/generic/files-6.12/include/linux/ath9k_platform.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (c) 2008 Atheros Communications Inc. - * Copyright (c) 2009 Gabor Juhos - * Copyright (c) 2009 Imre Kaloz - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#ifndef _LINUX_ATH9K_PLATFORM_H -#define _LINUX_ATH9K_PLATFORM_H - -#define ATH9K_PLAT_EEP_MAX_WORDS 2048 - -struct ath9k_platform_data { - const char *eeprom_name; - - u16 eeprom_data[ATH9K_PLAT_EEP_MAX_WORDS]; - u8 *macaddr; - - int led_pin; - u32 gpio_mask; - u32 gpio_val; - - u32 bt_active_pin; - u32 bt_priority_pin; - u32 wlan_active_pin; - - bool endian_check; - bool is_clk_25mhz; - bool tx_gain_buffalo; - bool disable_2ghz; - bool disable_5ghz; - bool led_active_high; - - int (*get_mac_revision)(void); - int (*external_reset)(void); - - bool use_eeprom; - - int num_leds; - const struct gpio_led *leds; - - unsigned num_btns; - const struct gpio_keys_button *btns; - unsigned btn_poll_interval; -}; - -#endif /* _LINUX_ATH9K_PLATFORM_H */ diff --git a/target/linux/generic/files-6.12/include/linux/mtd/mtk_bmt.h b/target/linux/generic/files-6.12/include/linux/mtd/mtk_bmt.h deleted file mode 100644 index cbb6d04d895208..00000000000000 --- a/target/linux/generic/files-6.12/include/linux/mtd/mtk_bmt.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef __MTK_BMT_H -#define __MTK_BMT_H - -#ifdef CONFIG_MTD_NAND_MTK_BMT -int mtk_bmt_attach(struct mtd_info *mtd); -void mtk_bmt_detach(struct mtd_info *mtd); -#else -static inline int mtk_bmt_attach(struct mtd_info *mtd) -{ - return 0; -} - -static inline void mtk_bmt_detach(struct mtd_info *mtd) -{ -} -#endif - -#endif diff --git a/target/linux/generic/files-6.12/include/linux/myloader.h b/target/linux/generic/files-6.12/include/linux/myloader.h deleted file mode 100644 index d89e415fba6cae..00000000000000 --- a/target/linux/generic/files-6.12/include/linux/myloader.h +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Compex's MyLoader specific definitions - * - * Copyright (C) 2006-2008 Gabor Juhos - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published - * by the Free Software Foundation. - * - */ - -#ifndef _MYLOADER_H_ -#define _MYLOADER_H_ - -/* Myloader specific magic numbers */ -#define MYLO_MAGIC_SYS_PARAMS 0x20021107 -#define MYLO_MAGIC_PARTITIONS 0x20021103 -#define MYLO_MAGIC_BOARD_PARAMS 0x20021103 - -/* Vendor ID's (seems to be same as the PCI vendor ID's) */ -#define VENID_COMPEX 0x11F6 - -/* Devices based on the ADM5120 */ -#define DEVID_COMPEX_NP27G 0x0078 -#define DEVID_COMPEX_NP28G 0x044C -#define DEVID_COMPEX_NP28GHS 0x044E -#define DEVID_COMPEX_WP54Gv1C 0x0514 -#define DEVID_COMPEX_WP54G 0x0515 -#define DEVID_COMPEX_WP54AG 0x0546 -#define DEVID_COMPEX_WPP54AG 0x0550 -#define DEVID_COMPEX_WPP54G 0x0555 - -/* Devices based on the Atheros AR2317 */ -#define DEVID_COMPEX_NP25G 0x05E6 -#define DEVID_COMPEX_WPE53G 0x05DC - -/* Devices based on the Atheros AR71xx */ -#define DEVID_COMPEX_WP543 0x0640 -#define DEVID_COMPEX_WPE72 0x0672 - -/* Devices based on the IXP422 */ -#define DEVID_COMPEX_WP18 0x047E -#define DEVID_COMPEX_NP18A 0x0489 - -/* Other devices */ -#define DEVID_COMPEX_NP26G8M 0x03E8 -#define DEVID_COMPEX_NP26G16M 0x03E9 - -struct mylo_partition { - uint16_t flags; /* partition flags */ - uint16_t type; /* type of the partition */ - uint32_t addr; /* relative address of the partition from the - flash start */ - uint32_t size; /* size of the partition in bytes */ - uint32_t param; /* if this is the active partition, the - MyLoader load code to this address */ -}; - -#define PARTITION_FLAG_ACTIVE 0x8000 /* this is the active partition, - * MyLoader loads firmware from here */ -#define PARTITION_FLAG_ISRAM 0x2000 /* FIXME: this is a RAM partition? */ -#define PARTIIION_FLAG_RAMLOAD 0x1000 /* FIXME: load this partition into the RAM? */ -#define PARTITION_FLAG_PRELOAD 0x0800 /* the partition data preloaded to RAM - * before decompression */ -#define PARTITION_FLAG_LZMA 0x0100 /* partition data compressed by LZMA */ -#define PARTITION_FLAG_HAVEHDR 0x0002 /* the partition data have a header */ - -#define PARTITION_TYPE_FREE 0 -#define PARTITION_TYPE_USED 1 - -#define MYLO_MAX_PARTITIONS 8 /* maximum number of partitions in the - partition table */ - -struct mylo_partition_table { - uint32_t magic; /* must be MYLO_MAGIC_PARTITIONS */ - uint32_t res0; /* unknown/unused */ - uint32_t res1; /* unknown/unused */ - uint32_t res2; /* unknown/unused */ - struct mylo_partition partitions[MYLO_MAX_PARTITIONS]; -}; - -struct mylo_partition_header { - uint32_t len; /* length of the partition data */ - uint32_t crc; /* CRC value of the partition data */ -}; - -struct mylo_system_params { - uint32_t magic; /* must be MYLO_MAGIC_SYS_PARAMS */ - uint32_t res0; - uint32_t res1; - uint32_t mylo_ver; - uint16_t vid; /* Vendor ID */ - uint16_t did; /* Device ID */ - uint16_t svid; /* Sub Vendor ID */ - uint16_t sdid; /* Sub Device ID */ - uint32_t rev; /* device revision */ - uint32_t fwhi; - uint32_t fwlo; - uint32_t tftp_addr; - uint32_t prog_start; - uint32_t flash_size; /* size of boot FLASH in bytes */ - uint32_t dram_size; /* size of onboard RAM in bytes */ -}; - -struct mylo_eth_addr { - uint8_t mac[6]; - uint8_t csum[2]; -}; - -#define MYLO_ETHADDR_COUNT 8 /* maximum number of ethernet address - in the board parameters */ - -struct mylo_board_params { - uint32_t magic; /* must be MYLO_MAGIC_BOARD_PARAMS */ - uint32_t res0; - uint32_t res1; - uint32_t res2; - struct mylo_eth_addr addr[MYLO_ETHADDR_COUNT]; -}; - -#endif /* _MYLOADER_H_*/ diff --git a/target/linux/generic/files-6.12/include/linux/platform_data/adm6996-gpio.h b/target/linux/generic/files-6.12/include/linux/platform_data/adm6996-gpio.h deleted file mode 100644 index d5af9bbf6e5588..00000000000000 --- a/target/linux/generic/files-6.12/include/linux/platform_data/adm6996-gpio.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * ADM6996 GPIO platform data - * - * Copyright (C) 2013 Hauke Mehrtens - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License v2 as published by the - * Free Software Foundation - */ - -#ifndef __PLATFORM_ADM6996_GPIO_H -#define __PLATFORM_ADM6996_GPIO_H - -#include - -enum adm6996_model { - ADM6996FC = 1, - ADM6996M = 2, - ADM6996L = 3, -}; - -struct adm6996_gpio_platform_data { - u8 eecs; - u8 eesk; - u8 eedi; - enum adm6996_model model; -}; - -#endif diff --git a/target/linux/generic/files-6.12/include/linux/routerboot.h b/target/linux/generic/files-6.12/include/linux/routerboot.h deleted file mode 100644 index 3cda858cf9c2ef..00000000000000 --- a/target/linux/generic/files-6.12/include/linux/routerboot.h +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Mikrotik's RouterBOOT definitions - * - * Copyright (C) 2007-2008 Gabor Juhos - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published - * by the Free Software Foundation. - * - */ - -#ifndef _ROUTERBOOT_H -#define _ROUTERBOOT_H - -#define RB_MAC_SIZE 6 - -/* - * Magic numbers - */ -#define RB_MAGIC_HARD 0x64726148 /* "Hard" */ -#define RB_MAGIC_SOFT 0x74666F53 /* "Soft" */ -#define RB_MAGIC_DAWN 0x6E776144 /* "Dawn" */ - -#define RB_ID_TERMINATOR 0 - -/* - * ID values for Hardware settings - */ -#define RB_ID_HARD_01 1 -#define RB_ID_HARD_02 2 -#define RB_ID_FLASH_INFO 3 -#define RB_ID_MAC_ADDRESS_PACK 4 -#define RB_ID_BOARD_NAME 5 -#define RB_ID_BIOS_VERSION 6 -#define RB_ID_HARD_07 7 -#define RB_ID_SDRAM_TIMINGS 8 -#define RB_ID_DEVICE_TIMINGS 9 -#define RB_ID_SOFTWARE_ID 10 -#define RB_ID_SERIAL_NUMBER 11 -#define RB_ID_HARD_12 12 -#define RB_ID_MEMORY_SIZE 13 -#define RB_ID_MAC_ADDRESS_COUNT 14 -#define RB_ID_HW_OPTIONS 21 -#define RB_ID_WLAN_DATA 22 - -/* - * ID values for Software settings - */ -#define RB_ID_UART_SPEED 1 -#define RB_ID_BOOT_DELAY 2 -#define RB_ID_BOOT_DEVICE 3 -#define RB_ID_BOOT_KEY 4 -#define RB_ID_CPU_MODE 5 -#define RB_ID_FW_VERSION 6 -#define RB_ID_SOFT_07 7 -#define RB_ID_SOFT_08 8 -#define RB_ID_BOOT_PROTOCOL 9 -#define RB_ID_SOFT_10 10 -#define RB_ID_SOFT_11 11 - -/* - * UART_SPEED values - */ -#define RB_UART_SPEED_115200 0 -#define RB_UART_SPEED_57600 1 -#define RB_UART_SPEED_38400 2 -#define RB_UART_SPEED_19200 3 -#define RB_UART_SPEED_9600 4 -#define RB_UART_SPEED_4800 5 -#define RB_UART_SPEED_2400 6 -#define RB_UART_SPEED_1200 7 - -/* - * BOOT_DELAY values - */ -#define RB_BOOT_DELAY_0SEC 0 -#define RB_BOOT_DELAY_1SEC 1 -#define RB_BOOT_DELAY_2SEC 2 - -/* - * BOOT_DEVICE values - */ -#define RB_BOOT_DEVICE_ETHER 0 -#define RB_BOOT_DEVICE_NANDETH 1 -#define RB_BOOT_DEVICE_ETHONCE 2 -#define RB_BOOT_DEVICE_NANDONLY 3 - -/* - * BOOT_KEY values - */ -#define RB_BOOT_KEY_ANY 0 -#define RB_BOOT_KEY_DEL 1 - -/* - * CPU_MODE values - */ -#define RB_CPU_MODE_POWERSAVE 0 -#define RB_CPU_MODE_REGULAR 1 - -/* - * BOOT_PROTOCOL values - */ -#define RB_BOOT_PROTOCOL_BOOTP 0 -#define RB_BOOT_PROTOCOL_DHCP 1 - -#endif /* _ROUTERBOOT_H */ diff --git a/target/linux/generic/files-6.12/include/linux/rt2x00_platform.h b/target/linux/generic/files-6.12/include/linux/rt2x00_platform.h deleted file mode 100644 index e10377e21b092e..00000000000000 --- a/target/linux/generic/files-6.12/include/linux/rt2x00_platform.h +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Platform data definition for the rt2x00 driver - * - * Copyright (C) 2011 Gabor Juhos - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published - * by the Free Software Foundation. - * - */ - -#ifndef _RT2X00_PLATFORM_H -#define _RT2X00_PLATFORM_H - -struct rt2x00_platform_data { - char *eeprom_file_name; - const u8 *mac_address; - - int disable_2ghz; - int disable_5ghz; -}; - -#endif /* _RT2X00_PLATFORM_H */ diff --git a/target/linux/generic/files-6.12/include/linux/rtl8366.h b/target/linux/generic/files-6.12/include/linux/rtl8366.h deleted file mode 100644 index e3ce8f5361eb57..00000000000000 --- a/target/linux/generic/files-6.12/include/linux/rtl8366.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Platform data definition for the Realtek RTL8366RB/S ethernet switch driver - * - * Copyright (C) 2009-2010 Gabor Juhos - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published - * by the Free Software Foundation. - */ - -#ifndef _RTL8366_H -#define _RTL8366_H - -#define RTL8366_DRIVER_NAME "rtl8366" -#define RTL8366S_DRIVER_NAME "rtl8366s" -#define RTL8366RB_DRIVER_NAME "rtl8366rb" - -struct rtl8366_smi; - -enum rtl8366_type { - RTL8366_TYPE_UNKNOWN, - RTL8366_TYPE_S, - RTL8366_TYPE_RB, -}; - -struct rtl8366_initval { - unsigned reg; - u16 val; -}; - -struct rtl8366_platform_data { - unsigned gpio_sda; - unsigned gpio_sck; - void (*hw_reset)(struct rtl8366_smi *smi, bool active); - - unsigned num_initvals; - struct rtl8366_initval *initvals; -}; - -enum rtl8366_type rtl8366_smi_detect(struct rtl8366_platform_data *pdata); - -#endif /* _RTL8366_H */ diff --git a/target/linux/generic/files-6.12/include/linux/rtl8367.h b/target/linux/generic/files-6.12/include/linux/rtl8367.h deleted file mode 100644 index 14150393e28070..00000000000000 --- a/target/linux/generic/files-6.12/include/linux/rtl8367.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Platform data definition for the Realtek RTL8367 ethernet switch driver - * - * Copyright (C) 2011 Gabor Juhos - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published - * by the Free Software Foundation. - */ - -#ifndef _RTL8367_H -#define _RTL8367_H - -#define RTL8367_DRIVER_NAME "rtl8367" -#define RTL8367B_DRIVER_NAME "rtl8367b" - -enum rtl8367_port_speed { - RTL8367_PORT_SPEED_10 = 0, - RTL8367_PORT_SPEED_100, - RTL8367_PORT_SPEED_1000, -}; - -struct rtl8367_port_ability { - int force_mode; - int nway; - int txpause; - int rxpause; - int link; - int duplex; - enum rtl8367_port_speed speed; -}; - -enum rtl8367_extif_mode { - RTL8367_EXTIF_MODE_DISABLED = 0, - RTL8367_EXTIF_MODE_RGMII, - RTL8367_EXTIF_MODE_MII_MAC, - RTL8367_EXTIF_MODE_MII_PHY, - RTL8367_EXTIF_MODE_TMII_MAC, - RTL8367_EXTIF_MODE_TMII_PHY, - RTL8367_EXTIF_MODE_GMII, - RTL8367_EXTIF_MODE_RGMII_33V, - RTL8367B_EXTIF_MODE_RMII_MAC = 7, - RTL8367B_EXTIF_MODE_RMII_PHY, - RTL8367B_EXTIF_MODE_RGMII_33V, -}; - -struct rtl8367_extif_config { - unsigned int txdelay; - unsigned int rxdelay; - enum rtl8367_extif_mode mode; - struct rtl8367_port_ability ability; -}; - -struct rtl8367_platform_data { - unsigned gpio_sda; - unsigned gpio_sck; - void (*hw_reset)(bool active); - - struct rtl8367_extif_config *extif0_cfg; - struct rtl8367_extif_config *extif1_cfg; -}; - -#endif /* _RTL8367_H */ diff --git a/target/linux/generic/files-6.12/include/linux/switch.h b/target/linux/generic/files-6.12/include/linux/switch.h deleted file mode 100644 index 4e6238470d3062..00000000000000 --- a/target/linux/generic/files-6.12/include/linux/switch.h +++ /dev/null @@ -1,179 +0,0 @@ -/* - * switch.h: Switch configuration API - * - * Copyright (C) 2008 Felix Fietkau - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ -#ifndef _LINUX_SWITCH_H -#define _LINUX_SWITCH_H - -#include -#include - -struct switch_dev; -struct switch_op; -struct switch_val; -struct switch_attr; -struct switch_attrlist; -struct switch_led_trigger; - -int register_switch(struct switch_dev *dev, struct net_device *netdev); -void unregister_switch(struct switch_dev *dev); - -/** - * struct switch_attrlist - attribute list - * - * @n_attr: number of attributes - * @attr: pointer to the attributes array - */ -struct switch_attrlist { - int n_attr; - const struct switch_attr *attr; -}; - -enum switch_port_speed { - SWITCH_PORT_SPEED_UNKNOWN = 0, - SWITCH_PORT_SPEED_10 = 10, - SWITCH_PORT_SPEED_100 = 100, - SWITCH_PORT_SPEED_1000 = 1000, -}; - -struct switch_port_link { - bool link; - bool duplex; - bool aneg; - bool tx_flow; - bool rx_flow; - enum switch_port_speed speed; - /* in ethtool adv_t format */ - u32 eee; -}; - -struct switch_port_stats { - unsigned long long tx_bytes; - unsigned long long rx_bytes; -}; - -/** - * struct switch_dev_ops - switch driver operations - * - * @attr_global: global switch attribute list - * @attr_port: port attribute list - * @attr_vlan: vlan attribute list - * - * Callbacks: - * - * @get_vlan_ports: read the port list of a VLAN - * @set_vlan_ports: set the port list of a VLAN - * - * @get_port_pvid: get the primary VLAN ID of a port - * @set_port_pvid: set the primary VLAN ID of a port - * - * @apply_config: apply all changed settings to the switch - * @reset_switch: resetting the switch - */ -struct switch_dev_ops { - struct switch_attrlist attr_global, attr_port, attr_vlan; - - int (*get_vlan_ports)(struct switch_dev *dev, struct switch_val *val); - int (*set_vlan_ports)(struct switch_dev *dev, struct switch_val *val); - - int (*get_port_pvid)(struct switch_dev *dev, int port, int *val); - int (*set_port_pvid)(struct switch_dev *dev, int port, int val); - - int (*apply_config)(struct switch_dev *dev); - int (*reset_switch)(struct switch_dev *dev); - - int (*get_port_link)(struct switch_dev *dev, int port, - struct switch_port_link *link); - int (*set_port_link)(struct switch_dev *dev, int port, - struct switch_port_link *link); - int (*get_port_stats)(struct switch_dev *dev, int port, - struct switch_port_stats *stats); - - int (*phy_read16)(struct switch_dev *dev, int addr, u8 reg, u16 *value); - int (*phy_write16)(struct switch_dev *dev, int addr, u8 reg, u16 value); -}; - -struct switch_dev { - struct device_node *of_node; - const struct switch_dev_ops *ops; - /* will be automatically filled */ - char devname[IFNAMSIZ]; - - const char *name; - /* NB: either alias or netdev must be set */ - const char *alias; - struct net_device *netdev; - - unsigned int ports; - unsigned int vlans; - unsigned int cpu_port; - - /* the following fields are internal for swconfig */ - unsigned int id; - struct list_head dev_list; - unsigned long def_global, def_port, def_vlan; - - struct mutex sw_mutex; - struct switch_port *portbuf; - struct switch_portmap *portmap; - struct switch_port_link linkbuf; - - char buf[128]; - -#ifdef CONFIG_SWCONFIG_LEDS - struct switch_led_trigger *led_trigger; -#endif -}; - -struct switch_port { - u32 id; - u32 flags; -}; - -struct switch_portmap { - u32 virt; - const char *s; -}; - -struct switch_val { - const struct switch_attr *attr; - unsigned int port_vlan; - unsigned int len; - union { - const char *s; - u32 i; - struct switch_port *ports; - struct switch_port_link *link; - } value; -}; - -struct switch_attr { - int disabled; - int type; - const char *name; - const char *description; - - int (*set)(struct switch_dev *dev, const struct switch_attr *attr, struct switch_val *val); - int (*get)(struct switch_dev *dev, const struct switch_attr *attr, struct switch_val *val); - - /* for driver internal use */ - int id; - int ofs; - int max; -}; - -int switch_generic_set_link(struct switch_dev *dev, int port, - struct switch_port_link *link); - -#endif /* _LINUX_SWITCH_H */ diff --git a/target/linux/generic/files-6.12/include/uapi/linux/switch.h b/target/linux/generic/files-6.12/include/uapi/linux/switch.h deleted file mode 100644 index ea449653fafa57..00000000000000 --- a/target/linux/generic/files-6.12/include/uapi/linux/switch.h +++ /dev/null @@ -1,119 +0,0 @@ -/* - * switch.h: Switch configuration API - * - * Copyright (C) 2008 Felix Fietkau - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#ifndef _UAPI_LINUX_SWITCH_H -#define _UAPI_LINUX_SWITCH_H - -#include -#include -#include -#include -#ifndef __KERNEL__ -#include -#include -#include -#endif - -/* main attributes */ -enum { - SWITCH_ATTR_UNSPEC, - /* global */ - SWITCH_ATTR_TYPE, - /* device */ - SWITCH_ATTR_ID, - SWITCH_ATTR_DEV_NAME, - SWITCH_ATTR_ALIAS, - SWITCH_ATTR_NAME, - SWITCH_ATTR_VLANS, - SWITCH_ATTR_PORTS, - SWITCH_ATTR_PORTMAP, - SWITCH_ATTR_CPU_PORT, - /* attributes */ - SWITCH_ATTR_OP_ID, - SWITCH_ATTR_OP_TYPE, - SWITCH_ATTR_OP_NAME, - SWITCH_ATTR_OP_PORT, - SWITCH_ATTR_OP_VLAN, - SWITCH_ATTR_OP_VALUE_INT, - SWITCH_ATTR_OP_VALUE_STR, - SWITCH_ATTR_OP_VALUE_PORTS, - SWITCH_ATTR_OP_VALUE_LINK, - SWITCH_ATTR_OP_DESCRIPTION, - /* port lists */ - SWITCH_ATTR_PORT, - SWITCH_ATTR_MAX -}; - -enum { - /* port map */ - SWITCH_PORTMAP_PORTS, - SWITCH_PORTMAP_SEGMENT, - SWITCH_PORTMAP_VIRT, - SWITCH_PORTMAP_MAX -}; - -/* commands */ -enum { - SWITCH_CMD_UNSPEC, - SWITCH_CMD_GET_SWITCH, - SWITCH_CMD_NEW_ATTR, - SWITCH_CMD_LIST_GLOBAL, - SWITCH_CMD_GET_GLOBAL, - SWITCH_CMD_SET_GLOBAL, - SWITCH_CMD_LIST_PORT, - SWITCH_CMD_GET_PORT, - SWITCH_CMD_SET_PORT, - SWITCH_CMD_LIST_VLAN, - SWITCH_CMD_GET_VLAN, - SWITCH_CMD_SET_VLAN -}; - -/* data types */ -enum switch_val_type { - SWITCH_TYPE_UNSPEC, - SWITCH_TYPE_INT, - SWITCH_TYPE_STRING, - SWITCH_TYPE_PORTS, - SWITCH_TYPE_LINK, - SWITCH_TYPE_NOVAL, -}; - -/* port nested attributes */ -enum { - SWITCH_PORT_UNSPEC, - SWITCH_PORT_ID, - SWITCH_PORT_FLAG_TAGGED, - SWITCH_PORT_ATTR_MAX -}; - -/* link nested attributes */ -enum { - SWITCH_LINK_UNSPEC, - SWITCH_LINK_FLAG_LINK, - SWITCH_LINK_FLAG_DUPLEX, - SWITCH_LINK_FLAG_ANEG, - SWITCH_LINK_FLAG_TX_FLOW, - SWITCH_LINK_FLAG_RX_FLOW, - SWITCH_LINK_SPEED, - SWITCH_LINK_FLAG_EEE_100BASET, - SWITCH_LINK_FLAG_EEE_1000BASET, - SWITCH_LINK_ATTR_MAX, -}; - -#define SWITCH_ATTR_DEFAULTS_OFFSET 0x1000 - - -#endif /* _UAPI_LINUX_SWITCH_H */