From bc3b87b33365f93c5c11ce92c125339892099644 Mon Sep 17 00:00:00 2001 From: Florian Boor Date: Sun, 3 Jun 2018 00:34:15 +0200 Subject: [PATCH] linux-karo: Add initial version of linux-karo 4.9.11 based on NXP kernel tree --- recipes-kernel/linux/linux-imx.inc | 22 + .../0001-DTS-Add-Stratec-TX6-devicetree.patch | 160 + .../add-support-for-edt-m12-touch.patch | 182 + .../linux-karo-4.9.11/edt-ft5x06-fixes.patch | 95 + .../edt-ft5x06-make-distinction-between.patch | 296 + .../ethernet-update-driver.patch | 17985 ++++++++++++++++ ...pu-viv_gcc6_indent_warning_error_fix.patch | 30 + .../linux-karo-4.9.11/reset-phy-minimal.patch | 30 + ..._the_enet_out_clock_is_being_enabled.patch | 203 + .../set-enet_ref_clk-to-50-mhz.patch | 25 + .../linux/linux-karo-4.9.11/tx6/defconfig | 461 + .../linux-karo-4.9.11/tx6/imx6qdl-tx6-gpio.h | 338 + .../linux-karo-4.9.11/tx6/imx6qdl-tx6.dtsi | 647 + .../imx6dl-tx6-emmc-aclavis-lvds.dts | 128 + .../imx6dl-tx6-nand-aclavis-lvds.dts | 128 + .../imx6q-tx6-emmc-aclavis-lvds.dts | 128 + .../imx6q-tx6-nand-aclavis-lvds.dts | 128 + .../imx6qp-tx6-emmc-aclavis-lvds.dts | 129 + .../imx6s-tx6-emmc-aclavis-lvds.dts | 132 + .../imx6s-tx6-nand-aclavis-lvds.dts | 132 + .../aclavis-lvds/txbase-aclavis-lvds.dtsi | 247 + .../aclavis/imx6dl-tx6-emmc-aclavis.dts | 107 + .../aclavis/imx6dl-tx6-nand-aclavis.dts | 107 + .../txbase/aclavis/imx6q-tx6-emmc-aclavis.dts | 107 + .../txbase/aclavis/imx6q-tx6-nand-aclavis.dts | 107 + .../aclavis/imx6qp-tx6-emmc-aclavis.dts | 108 + .../txbase/aclavis/imx6s-tx6-emmc-aclavis.dts | 111 + .../txbase/aclavis/imx6s-tx6-nand-aclavis.dts | 111 + .../txbase/aclavis/txbase-aclavis.dtsi | 332 + .../evalkit/imx6dl-tx6-emmc-evalkit.dts | 107 + .../evalkit/imx6dl-tx6-nand-evalkit.dts | 107 + .../txbase/evalkit/imx6q-tx6-emmc-evalkit.dts | 107 + .../txbase/evalkit/imx6q-tx6-nand-evalkit.dts | 107 + .../evalkit/imx6qp-tx6-emmc-evalkit.dts | 108 + .../txbase/evalkit/imx6s-tx6-emmc-evalkit.dts | 111 + .../txbase/evalkit/imx6s-tx6-nand-evalkit.dts | 111 + .../txbase/evalkit/txbase-evalkit.dtsi | 197 + .../mb7-lvds/imx6dl-tx6-emmc-mb7-lvds.dts | 128 + .../mb7-lvds/imx6dl-tx6-nand-mb7-lvds.dts | 128 + .../mb7-lvds/imx6q-tx6-emmc-mb7-lvds.dts | 128 + .../mb7-lvds/imx6q-tx6-nand-mb7-lvds.dts | 128 + .../mb7-lvds/imx6qp-tx6-emmc-mb7-lvds.dts | 129 + .../mb7-lvds/imx6s-tx6-emmc-mb7-lvds.dts | 132 + .../mb7-lvds/imx6s-tx6-nand-mb7-lvds.dts | 132 + .../txbase/mb7-lvds/txbase-mb7-lvds.dtsi | 295 + .../txbase/mb7/imx6dl-tx6-emmc-mb7.dts | 107 + .../txbase/mb7/imx6dl-tx6-nand-mb7.dts | 107 + .../txbase/mb7/imx6q-tx6-emmc-mb7.dts | 107 + .../txbase/mb7/imx6q-tx6-nand-mb7.dts | 107 + .../txbase/mb7/imx6qp-tx6-emmc-mb7.dts | 108 + .../txbase/mb7/imx6s-tx6-emmc-mb7.dts | 111 + .../txbase/mb7/imx6s-tx6-nand-mb7.dts | 111 + .../txbase/mb7/txbase-mb7.dtsi | 382 + .../txbase/myboard/imx6s-tx6-emmc-myboard.dts | 111 + .../txbase/myboard/txbase-myboard.dtsi | 383 + recipes-kernel/linux/linux-karo_4.9.11.bb | 63 + 56 files changed, 26568 insertions(+) create mode 100644 recipes-kernel/linux/linux-imx.inc create mode 100644 recipes-kernel/linux/linux-karo-4.9.11/0001-DTS-Add-Stratec-TX6-devicetree.patch create mode 100644 recipes-kernel/linux/linux-karo-4.9.11/add-support-for-edt-m12-touch.patch create mode 100644 recipes-kernel/linux/linux-karo-4.9.11/edt-ft5x06-fixes.patch create mode 100644 recipes-kernel/linux/linux-karo-4.9.11/edt-ft5x06-make-distinction-between.patch create mode 100644 recipes-kernel/linux/linux-karo-4.9.11/ethernet-update-driver.patch create mode 100755 recipes-kernel/linux/linux-karo-4.9.11/gpu-viv_gcc6_indent_warning_error_fix.patch create mode 100644 recipes-kernel/linux/linux-karo-4.9.11/reset-phy-minimal.patch create mode 100644 recipes-kernel/linux/linux-karo-4.9.11/reset_ethernet_phy_whenever_the_enet_out_clock_is_being_enabled.patch create mode 100755 recipes-kernel/linux/linux-karo-4.9.11/set-enet_ref_clk-to-50-mhz.patch create mode 100644 recipes-kernel/linux/linux-karo-4.9.11/tx6/defconfig create mode 100755 recipes-kernel/linux/linux-karo-4.9.11/tx6/imx6qdl-tx6-gpio.h create mode 100755 recipes-kernel/linux/linux-karo-4.9.11/tx6/imx6qdl-tx6.dtsi create mode 100755 recipes-kernel/linux/linux-karo-4.9.11/txbase/aclavis-lvds/imx6dl-tx6-emmc-aclavis-lvds.dts create mode 100755 recipes-kernel/linux/linux-karo-4.9.11/txbase/aclavis-lvds/imx6dl-tx6-nand-aclavis-lvds.dts create mode 100755 recipes-kernel/linux/linux-karo-4.9.11/txbase/aclavis-lvds/imx6q-tx6-emmc-aclavis-lvds.dts create mode 100755 recipes-kernel/linux/linux-karo-4.9.11/txbase/aclavis-lvds/imx6q-tx6-nand-aclavis-lvds.dts create mode 100755 recipes-kernel/linux/linux-karo-4.9.11/txbase/aclavis-lvds/imx6qp-tx6-emmc-aclavis-lvds.dts create mode 100755 recipes-kernel/linux/linux-karo-4.9.11/txbase/aclavis-lvds/imx6s-tx6-emmc-aclavis-lvds.dts create mode 100755 recipes-kernel/linux/linux-karo-4.9.11/txbase/aclavis-lvds/imx6s-tx6-nand-aclavis-lvds.dts create mode 100755 recipes-kernel/linux/linux-karo-4.9.11/txbase/aclavis-lvds/txbase-aclavis-lvds.dtsi create mode 100755 recipes-kernel/linux/linux-karo-4.9.11/txbase/aclavis/imx6dl-tx6-emmc-aclavis.dts create mode 100755 recipes-kernel/linux/linux-karo-4.9.11/txbase/aclavis/imx6dl-tx6-nand-aclavis.dts create mode 100755 recipes-kernel/linux/linux-karo-4.9.11/txbase/aclavis/imx6q-tx6-emmc-aclavis.dts create mode 100755 recipes-kernel/linux/linux-karo-4.9.11/txbase/aclavis/imx6q-tx6-nand-aclavis.dts create mode 100755 recipes-kernel/linux/linux-karo-4.9.11/txbase/aclavis/imx6qp-tx6-emmc-aclavis.dts create mode 100755 recipes-kernel/linux/linux-karo-4.9.11/txbase/aclavis/imx6s-tx6-emmc-aclavis.dts create mode 100755 recipes-kernel/linux/linux-karo-4.9.11/txbase/aclavis/imx6s-tx6-nand-aclavis.dts create mode 100755 recipes-kernel/linux/linux-karo-4.9.11/txbase/aclavis/txbase-aclavis.dtsi create mode 100755 recipes-kernel/linux/linux-karo-4.9.11/txbase/evalkit/imx6dl-tx6-emmc-evalkit.dts create mode 100755 recipes-kernel/linux/linux-karo-4.9.11/txbase/evalkit/imx6dl-tx6-nand-evalkit.dts create mode 100755 recipes-kernel/linux/linux-karo-4.9.11/txbase/evalkit/imx6q-tx6-emmc-evalkit.dts create mode 100755 recipes-kernel/linux/linux-karo-4.9.11/txbase/evalkit/imx6q-tx6-nand-evalkit.dts create mode 100755 recipes-kernel/linux/linux-karo-4.9.11/txbase/evalkit/imx6qp-tx6-emmc-evalkit.dts create mode 100755 recipes-kernel/linux/linux-karo-4.9.11/txbase/evalkit/imx6s-tx6-emmc-evalkit.dts create mode 100755 recipes-kernel/linux/linux-karo-4.9.11/txbase/evalkit/imx6s-tx6-nand-evalkit.dts create mode 100755 recipes-kernel/linux/linux-karo-4.9.11/txbase/evalkit/txbase-evalkit.dtsi create mode 100755 recipes-kernel/linux/linux-karo-4.9.11/txbase/mb7-lvds/imx6dl-tx6-emmc-mb7-lvds.dts create mode 100755 recipes-kernel/linux/linux-karo-4.9.11/txbase/mb7-lvds/imx6dl-tx6-nand-mb7-lvds.dts create mode 100755 recipes-kernel/linux/linux-karo-4.9.11/txbase/mb7-lvds/imx6q-tx6-emmc-mb7-lvds.dts create mode 100755 recipes-kernel/linux/linux-karo-4.9.11/txbase/mb7-lvds/imx6q-tx6-nand-mb7-lvds.dts create mode 100755 recipes-kernel/linux/linux-karo-4.9.11/txbase/mb7-lvds/imx6qp-tx6-emmc-mb7-lvds.dts create mode 100755 recipes-kernel/linux/linux-karo-4.9.11/txbase/mb7-lvds/imx6s-tx6-emmc-mb7-lvds.dts create mode 100755 recipes-kernel/linux/linux-karo-4.9.11/txbase/mb7-lvds/imx6s-tx6-nand-mb7-lvds.dts create mode 100755 recipes-kernel/linux/linux-karo-4.9.11/txbase/mb7-lvds/txbase-mb7-lvds.dtsi create mode 100755 recipes-kernel/linux/linux-karo-4.9.11/txbase/mb7/imx6dl-tx6-emmc-mb7.dts create mode 100755 recipes-kernel/linux/linux-karo-4.9.11/txbase/mb7/imx6dl-tx6-nand-mb7.dts create mode 100755 recipes-kernel/linux/linux-karo-4.9.11/txbase/mb7/imx6q-tx6-emmc-mb7.dts create mode 100755 recipes-kernel/linux/linux-karo-4.9.11/txbase/mb7/imx6q-tx6-nand-mb7.dts create mode 100755 recipes-kernel/linux/linux-karo-4.9.11/txbase/mb7/imx6qp-tx6-emmc-mb7.dts create mode 100755 recipes-kernel/linux/linux-karo-4.9.11/txbase/mb7/imx6s-tx6-emmc-mb7.dts create mode 100755 recipes-kernel/linux/linux-karo-4.9.11/txbase/mb7/imx6s-tx6-nand-mb7.dts create mode 100755 recipes-kernel/linux/linux-karo-4.9.11/txbase/mb7/txbase-mb7.dtsi create mode 100755 recipes-kernel/linux/linux-karo-4.9.11/txbase/myboard/imx6s-tx6-emmc-myboard.dts create mode 100755 recipes-kernel/linux/linux-karo-4.9.11/txbase/myboard/txbase-myboard.dtsi create mode 100644 recipes-kernel/linux/linux-karo_4.9.11.bb diff --git a/recipes-kernel/linux/linux-imx.inc b/recipes-kernel/linux/linux-imx.inc new file mode 100644 index 0000000..9a8a035 --- /dev/null +++ b/recipes-kernel/linux/linux-imx.inc @@ -0,0 +1,22 @@ +# Copyright (C) 2012, 2015 O.S. Systems Software LTDA. +# Released under the MIT license (see COPYING.MIT for the terms) + +LICENSE = "GPLv2" +LIC_FILES_CHKSUM = "file://COPYING;md5=d7810fab7487fb0aad327b76f1be7cd7" + +inherit kernel fsl-kernel-localversion fsl-vivante-kernel-driver-handler + +# Put a local version until we have a true SRCREV to point to +LOCALVERSION ?= "" +SCMVERSION ?= "y" +SRCBRANCH ?= "" + +SRC_URI = "git://source.codeaurora.org/external/imx/linux-imx;protocol=https;branch=${SRCBRANCH} \ + file://defconfig \ +" + +S = "${WORKDIR}/git" + +# We need to pass it as param since kernel might support more then one +# machine, with different entry points +KERNEL_EXTRA_ARGS += "LOADADDR=${UBOOT_ENTRYPOINT}" diff --git a/recipes-kernel/linux/linux-karo-4.9.11/0001-DTS-Add-Stratec-TX6-devicetree.patch b/recipes-kernel/linux/linux-karo-4.9.11/0001-DTS-Add-Stratec-TX6-devicetree.patch new file mode 100644 index 0000000..f30ba1d --- /dev/null +++ b/recipes-kernel/linux/linux-karo-4.9.11/0001-DTS-Add-Stratec-TX6-devicetree.patch @@ -0,0 +1,160 @@ +From 52902ee8a80e2aec3135e47a9189811f5d209c3c Mon Sep 17 00:00:00 2001 +From: Florian Boor +Date: Tue, 6 Mar 2018 13:59:22 +0100 +Subject: [PATCH] DTS: Add Stratec TX6 devicetree + +--- + arch/arm/boot/dts/Makefile | 1 + + arch/arm/boot/dts/imx6dl-tx6-emmc-mb7-stratec.dts | 128 ++++++++++++++++++++++ + 2 files changed, 129 insertions(+) + create mode 100644 arch/arm/boot/dts/imx6dl-tx6-emmc-mb7-stratec.dts + +diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile +index f151ec7..e03cd14 100644 +--- a/arch/arm/boot/dts/Makefile ++++ b/arch/arm/boot/dts/Makefile +@@ -400,6 +400,7 @@ dtb-$(CONFIG_SOC_IMX6Q) += \ + imx6dl-tx6u-8033-mb7.dtb \ + imx6dl-tx6u-811x.dtb \ + imx6dl-tx6u-81xx-mb7.dtb \ ++ imx6dl-tx6-emmc-mb7-stratec.dtb \ + imx6dl-udoo.dtb \ + imx6dl-wandboard.dtb \ + imx6dl-wandboard-revb1.dtb \ +diff --git a/arch/arm/boot/dts/imx6dl-tx6-emmc-mb7-stratec.dts b/arch/arm/boot/dts/imx6dl-tx6-emmc-mb7-stratec.dts +new file mode 100644 +index 0000000..0270e6c +--- /dev/null ++++ b/arch/arm/boot/dts/imx6dl-tx6-emmc-mb7-stratec.dts +@@ -0,0 +1,128 @@ ++/* ++ * Copyright 2016 Lothar Waßmann ++ * Copyright 2016 Oliver Wendt ++ * Copyright 2016 Michael Vyskocil ++ * ++ * This file is dual-licensed: you can use it either under the terms ++ * of the GPL or the X11 license, at your option. Note that this dual ++ * licensing only applies to this file, and not this project as a ++ * whole. ++ * ++ * a) This file 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 file 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. ++ * ++ * Or, alternatively, ++ * ++ * b) Permission is hereby granted, free of charge, to any person ++ * obtaining a copy of this software and associated documentation ++ * files (the "Software"), to deal in the Software without ++ * restriction, including without limitation the rights to use, ++ * copy, modify, merge, publish, distribute, sublicense, and/or ++ * sell copies of the Software, and to permit persons to whom the ++ * Software is furnished to do so, subject to the following ++ * conditions: ++ * ++ * The above copyright notice and this permission notice shall be ++ * included in all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, ++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES ++ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND ++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT ++ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, ++ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING ++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ * OTHER DEALINGS IN THE SOFTWARE. ++ */ ++ ++/* ++ * Please be reminded that - in general - DTSI file(s) are include files that ++ * are for more than one purpose (usually bound to a SoC) and as such shouldn't ++ * be edited. For end-user products it should be the DTS file(s) that choose ++ * which devices and pins are active and setup. ++ * ++ * The setup of DT files for Ka-Ro TX COM Modules under Yocto follow a ++ * different, non-standard, implementation to the mainline Linux kernel. ++ */ ++ ++/* ++ * Please see the imx6*-tx6-gpio.h && imx6*-tx6.dtsi in "linux-karo-x.y.ab/tx6" ++ * for the definitions like TX_NAND or TX_EMMC, etc. ++ */ ++ ++/dts-v1/; ++ ++#include "imx6dl.dtsi" ++#include "imx6qdl-tx6.dtsi" ++#include "txbase-mb7.dtsi" ++ ++/ { ++ model = "Ka-Ro electronics TX6U Module (eMMC & RGB)"; ++ compatible = "karo,imx6dl-tx6dl", "fsl,imx6dl"; ++}; ++ ++/* ++ * Every VOU is multi parted: backlight, device, framebuffer, pwm ++ * Thus all parts have to be enabled before a display can be used on the ++ * specific port. ++ */ ++ ++&backlight0 { ++ status = "okay"; ++}; ++ ++/* ++ * NVM setup ++ */ ++ ++TX_EMMC { ++ status = "okay"; ++}; ++ ++/* ++ * Remaining device references in alphabetical order ++ */ ++ ++TX_LCD { ++ status = "okay"; ++ /* ++ * Users should add their custom timing here, therewith ++ * therewith overwriting the default/pre-defined timings. For more see: ++ * ++ * txbase/{BASEBOARD}-{DISPLAY-IF}/txbase-{BASEBOARD}-{DISPLAY-IF}.dtsi ++ * ++ * e.g.: ++ * txbase/mb7-lvds/txbase-aclavis.dtsi ++ */ ++}; ++ ++TX_LCD_FB { ++ status = "okay"; ++}; ++ ++TX_I2C { ++ status = "okay"; ++ ++ rtc@6f { ++ compatible = "microchip,mcp7940x"; ++ reg = <0x6f>; ++ }; ++ ++ polytouch: edt-ft5x06@38 { ++ compatible = "edt,edt-ft5x06"; ++ reg = <0x38>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pinctrl_edt_ft5x06>; ++ interrupts-extended = ; ++ reset-gpios = ; ++ wake-gpios = ; ++ linux,wakeup; ++ }; ++}; ++ +-- +2.1.4 + diff --git a/recipes-kernel/linux/linux-karo-4.9.11/add-support-for-edt-m12-touch.patch b/recipes-kernel/linux/linux-karo-4.9.11/add-support-for-edt-m12-touch.patch new file mode 100644 index 0000000..791eb55 --- /dev/null +++ b/recipes-kernel/linux/linux-karo-4.9.11/add-support-for-edt-m12-touch.patch @@ -0,0 +1,182 @@ +From patchwork Thu Oct 5 15:35:08 2017 +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +Subject: [3/3] input: edt-ft5x06: implement support for the EDT-M12 series. +From: Simon Budig +X-Patchwork-Id: 9987471 +Message-Id: <20171005153508.32127-3-simon.budig@kernelconcepts.de> +To: linux-input@vger.kernel.org +Cc: dmitry.torokhov@gmail.com, Simon Budig +Date: Thu, 5 Oct 2017 17:35:08 +0200 + +From: Simon Budig + +This adds support for the EDT M12 series of touchscreens. + +Signed-off-by: Simon Budig +--- + drivers/input/touchscreen/edt-ft5x06.c | 48 +++++++++++++++++++++++++++------- + 1 file changed, 38 insertions(+), 10 deletions(-) + +diff --git a/drivers/input/touchscreen/edt-ft5x06.c b/drivers/input/touchscreen/edt-ft5x06.c +index d128445..8f5c2c0 100644 +--- a/drivers/input/touchscreen/edt-ft5x06.c ++++ b/drivers/input/touchscreen/edt-ft5x06.c +@@ -72,6 +72,7 @@ + enum edt_ver { + EDT_M06, + EDT_M09, ++ EDT_M12, + GENERIC_FT, + }; + +@@ -188,6 +189,7 @@ static irqreturn_t edt_ft5x06_ts_isr(int irq, void *dev_id) + break; + + case EDT_M09: ++ case EDT_M12: + case GENERIC_FT: + cmd = 0x0; + offset = 3; +@@ -211,7 +213,7 @@ static irqreturn_t edt_ft5x06_ts_isr(int irq, void *dev_id) + goto out; + } + +- /* M09 does not send header or CRC */ ++ /* M09/M12 does not send header or CRC */ + if (tsdata->version == EDT_M06) { + if (rdbuf[0] != 0xaa || rdbuf[1] != 0xaa || + rdbuf[2] != datalen) { +@@ -274,6 +276,7 @@ static int edt_ft5x06_register_write(struct edt_ft5x06_ts_data *tsdata, + return edt_ft5x06_ts_readwrite(tsdata->client, 4, + wrbuf, 0, NULL); + case EDT_M09: ++ case EDT_M12: + case GENERIC_FT: + wrbuf[0] = addr; + wrbuf[1] = value; +@@ -313,6 +316,7 @@ static int edt_ft5x06_register_read(struct edt_ft5x06_ts_data *tsdata, + break; + + case EDT_M09: ++ case EDT_M12: + case GENERIC_FT: + wrbuf[0] = addr; + error = edt_ft5x06_ts_readwrite(tsdata->client, 1, +@@ -377,6 +381,7 @@ static ssize_t edt_ft5x06_setting_show(struct device *dev, + break; + + case EDT_M09: ++ case EDT_M12: + case GENERIC_FT: + addr = attr->addr_m09; + break; +@@ -447,6 +452,7 @@ static ssize_t edt_ft5x06_setting_store(struct device *dev, + break; + + case EDT_M09: ++ case EDT_M12: + case GENERIC_FT: + addr = attr->addr_m09; + break; +@@ -472,14 +478,18 @@ static ssize_t edt_ft5x06_setting_store(struct device *dev, + return error ?: count; + } + ++/* m06, m09: range 0-31, m12: range 0-5 */ + static EDT_ATTR(gain, S_IWUSR | S_IRUGO, WORK_REGISTER_GAIN, + M09_REGISTER_GAIN, 0, 31); ++/* m06, m09: range 0-31, m12: range 0-16 */ + static EDT_ATTR(offset, S_IWUSR | S_IRUGO, WORK_REGISTER_OFFSET, + M09_REGISTER_OFFSET, 0, 31); ++/* m06: range 20 to 80, m09: range 0 to 30, m12: range 1 to 255... */ + static EDT_ATTR(threshold, S_IWUSR | S_IRUGO, WORK_REGISTER_THRESHOLD, +- M09_REGISTER_THRESHOLD, 0, 80); ++ M09_REGISTER_THRESHOLD, 0, 255); ++/* m06: range 3 to 14, m12: (0x64: 100Hz) */ + static EDT_ATTR(report_rate, S_IWUSR | S_IRUGO, WORK_REGISTER_REPORT_RATE, +- NO_REGISTER, 3, 14); ++ NO_REGISTER, 0, 255); + + static struct attribute *edt_ft5x06_attrs[] = { + &edt_ft5x06_attr_gain.dattr.attr, +@@ -551,7 +561,7 @@ static int edt_ft5x06_factory_mode(struct edt_ft5x06_ts_data *tsdata) + return error; + + m09_out: +- dev_err(&client->dev, "No factory mode support for M09/GENERIC_FT\n"); ++ dev_err(&client->dev, "No factory mode support for M09/M12/GENERIC_FT\n"); + return -EINVAL; + + } +@@ -776,13 +786,14 @@ static int edt_ft5x06_ts_identify(struct i2c_client *client, + * to have garbage in there + */ + memset(rdbuf, 0, sizeof(rdbuf)); +- error = edt_ft5x06_ts_readwrite(client, 1, "\xbb", ++ error = edt_ft5x06_ts_readwrite(client, 1, "\xBB", + EDT_NAME_LEN - 1, rdbuf); + if (error) + return error; + +- /* if we find something consistent, stay with that assumption +- * at least M09 won't send 3 bytes here ++ /* probe content for something consistent. ++ * M06 starts with a response byte, M12 gives the data directly. ++ * M09/Generic does not provide model number information. + */ + if (!(strncasecmp(rdbuf + 1, "EP0", 3))) { + tsdata->version = EDT_M06; +@@ -798,8 +809,22 @@ static int edt_ft5x06_ts_identify(struct i2c_client *client, + *p++ = '\0'; + strlcpy(model_name, rdbuf + 1, EDT_NAME_LEN); + strlcpy(fw_version, p ? p : "", EDT_NAME_LEN); ++ } else if (!(strncasecmp(rdbuf, "EP0", 3))) { ++ tsdata->version = EDT_M12; ++ ++ /* remove last '$' end marker */ ++ rdbuf[EDT_NAME_LEN - 2] = '\0'; ++ if (rdbuf[EDT_NAME_LEN - 3] == '$') ++ rdbuf[EDT_NAME_LEN - 3] = '\0'; ++ ++ /* look for Model/Version separator */ ++ p = strchr(rdbuf, '*'); ++ if (p) ++ *p++ = '\0'; ++ strlcpy(model_name, rdbuf, EDT_NAME_LEN); ++ strlcpy(fw_version, p ? p : "", EDT_NAME_LEN); + } else { +- /* If it is not an EDT M06 touchscreen, then the model ++ /* if it is not an EDT M06/M12 touchscreen then the model + * detection is a bit hairy. The different ft5x06 + * firmares around don't reliably implement the + * identification registers. Well. we'll take a shot. +@@ -894,7 +919,8 @@ edt_ft5x06_ts_get_parameters(struct edt_ft5x06_ts_data *tsdata) + tsdata->report_rate = edt_ft5x06_register_read(tsdata, + reg_addr->reg_report_rate); + if (tsdata->version == EDT_M06 || +- tsdata->version == EDT_M09) { ++ tsdata->version == EDT_M09 || ++ tsdata->version == EDT_M12) { + tsdata->num_x = edt_ft5x06_register_read(tsdata, + reg_addr->reg_num_x); + tsdata->num_y = edt_ft5x06_register_read(tsdata, +@@ -921,6 +947,7 @@ edt_ft5x06_ts_set_regs(struct edt_ft5x06_ts_data *tsdata) + break; + + case EDT_M09: ++ case EDT_M12: + reg_addr->reg_threshold = M09_REGISTER_THRESHOLD; + reg_addr->reg_report_rate = NO_REGISTER; + reg_addr->reg_gain = M09_REGISTER_GAIN; +@@ -1029,7 +1056,8 @@ static int edt_ft5x06_ts_probe(struct i2c_client *client, + input->dev.parent = &client->dev; + + if (tsdata->version == EDT_M06 || +- tsdata->version == EDT_M09) { ++ tsdata->version == EDT_M09 || ++ tsdata->version == EDT_M12) { + input_set_abs_params(input, ABS_MT_POSITION_X, + 0, tsdata->num_x * 64 - 1, 0, 0); + input_set_abs_params(input, ABS_MT_POSITION_Y, diff --git a/recipes-kernel/linux/linux-karo-4.9.11/edt-ft5x06-fixes.patch b/recipes-kernel/linux/linux-karo-4.9.11/edt-ft5x06-fixes.patch new file mode 100644 index 0000000..3e9cb95 --- /dev/null +++ b/recipes-kernel/linux/linux-karo-4.9.11/edt-ft5x06-fixes.patch @@ -0,0 +1,95 @@ +From aa3d4409b664813ceb86a24bd09458cdd29cbb8a Mon Sep 17 00:00:00 2001 +From: Martin Kepplinger +Date: Mon, 22 May 2017 17:19:45 -0700 +Subject: [PATCH] Input: edt-ft5x06 - increase allowed data range for threshold + parameter + +The datasheet and application note does not mention an allowed range for +the M09_REGISTER_THRESHOLD parameter. One of our customers needs to set +lower values than 20 and they seem to work just fine on EDT EP0xx0M09 with +T5x06 touch. + +So, lacking a known lower limit, we increase the range for thresholds, +and set the lower limit to 0. The documentation is updated accordingly. + +Signed-off-by: Schoefegger Stefan +Signed-off-by: Manfred Schlaegl +Signed-off-by: Martin Kepplinger +Acked-by: Rob Herring +Signed-off-by: Dmitry Torokhov +--- + Documentation/devicetree/bindings/input/touchscreen/edt-ft5x06.txt | 2 +- + drivers/input/touchscreen/edt-ft5x06.c | 2 +- + 3 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/Documentation/devicetree/bindings/input/touchscreen/edt-ft5x06.txt b/Documentation/devicetree/bindings/input/touchscreen/edt-ft5x06.txt +index 6db22103e2dd5..025cf8c9324ac 100644 +--- a/Documentation/devicetree/bindings/input/touchscreen/edt-ft5x06.txt ++++ b/Documentation/devicetree/bindings/input/touchscreen/edt-ft5x06.txt +@@ -36,7 +36,7 @@ Optional properties: + control gpios + + - threshold: allows setting the "click"-threshold in the range +- from 20 to 80. ++ from 0 to 80. + + - gain: allows setting the sensitivity in the range from 0 to + 31. Note that lower values indicate higher +diff --git a/drivers/input/touchscreen/edt-ft5x06.c b/drivers/input/touchscreen/edt-ft5x06.c +index 8cf8d8d5d4ef4..f872817e81e46 100644 +--- a/drivers/input/touchscreen/edt-ft5x06.c ++++ b/drivers/input/touchscreen/edt-ft5x06.c +@@ -471,7 +471,7 @@ static EDT_ATTR(gain, S_IWUSR | S_IRUGO, WORK_REGISTER_GAIN, + static EDT_ATTR(offset, S_IWUSR | S_IRUGO, WORK_REGISTER_OFFSET, + M09_REGISTER_OFFSET, 0, 31); + static EDT_ATTR(threshold, S_IWUSR | S_IRUGO, WORK_REGISTER_THRESHOLD, +- M09_REGISTER_THRESHOLD, 20, 80); ++ M09_REGISTER_THRESHOLD, 0, 80); + static EDT_ATTR(report_rate, S_IWUSR | S_IRUGO, WORK_REGISTER_REPORT_RATE, + NO_REGISTER, 3, 14); + +From 47014752829ed1b52fa6f876b381774ae530503c Mon Sep 17 00:00:00 2001 +From: Luca Ceresoli +Date: Thu, 7 Sep 2017 14:28:28 -0700 +Subject: [PATCH] Input: edt-ft5x06 - fix access to non-existing register + +reg_addr->reg_report_rate is supposed to exist in M06, not M09. + +The driver is written to skip avoids access to non-existing registers +when the register address is NO_REGISTER (0xff). But +reg_addr->reg_report_rate is initialized to 0x00 by devm_kzalloc() (in +edt_ft5x06_ts_probe()) and not changed thereafter. So the checks do +not work and an access to register 0x00 is done. + +Fix by setting reg_addr->reg_report_rate to NO_REGISTER. + +Also fix the only place where reg_report_rate is checked against zero +instead of NO_REGISTER. + +Signed-off-by: Luca Ceresoli +Signed-off-by: Dmitry Torokhov +--- + drivers/input/touchscreen/edt-ft5x06.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/input/touchscreen/edt-ft5x06.c b/drivers/input/touchscreen/edt-ft5x06.c +index f872817e81e46..5bf63f76dddac 100644 +--- a/drivers/input/touchscreen/edt-ft5x06.c ++++ b/drivers/input/touchscreen/edt-ft5x06.c +@@ -593,7 +593,7 @@ static int edt_ft5x06_work_mode(struct edt_ft5x06_ts_data *tsdata) + tsdata->gain); + edt_ft5x06_register_write(tsdata, reg_addr->reg_offset, + tsdata->offset); +- if (reg_addr->reg_report_rate) ++ if (reg_addr->reg_report_rate != NO_REGISTER) + edt_ft5x06_register_write(tsdata, reg_addr->reg_report_rate, + tsdata->report_rate); + +@@ -874,6 +874,7 @@ edt_ft5x06_ts_set_regs(struct edt_ft5x06_ts_data *tsdata) + + case M09: + reg_addr->reg_threshold = M09_REGISTER_THRESHOLD; ++ reg_addr->reg_report_rate = NO_REGISTER; + reg_addr->reg_gain = M09_REGISTER_GAIN; + reg_addr->reg_offset = M09_REGISTER_OFFSET; + reg_addr->reg_num_x = M09_REGISTER_NUM_X; diff --git a/recipes-kernel/linux/linux-karo-4.9.11/edt-ft5x06-make-distinction-between.patch b/recipes-kernel/linux/linux-karo-4.9.11/edt-ft5x06-make-distinction-between.patch new file mode 100644 index 0000000..2cc16b8 --- /dev/null +++ b/recipes-kernel/linux/linux-karo-4.9.11/edt-ft5x06-make-distinction-between.patch @@ -0,0 +1,296 @@ +From 169110c3645621497ca0b1d0d7bc80dcea8ff9d4 Mon Sep 17 00:00:00 2001 +From: Simon Budig +Date: Mon, 9 Oct 2017 20:58:11 -0700 +Subject: [PATCH] Input: edt-ft5x06 - make distinction between m06/m09/generic + more clear + +Since the driver also is useful for some non-EDT touchscreens based on +the focaltec chips introduce the concept of a "generic" focaltec based +touch. + +Use a better heuristics for model detection and be more specific in the +source. + +Signed-off-by: Simon Budig +Signed-off-by: Dmitry Torokhov +--- + drivers/input/touchscreen/edt-ft5x06.c | 122 +++++++++++++++++++++++++-------- + 1 file changed, 93 insertions(+), 29 deletions(-) + +diff --git a/drivers/input/touchscreen/edt-ft5x06.c b/drivers/input/touchscreen/edt-ft5x06.c +index f879d14f7ffcc..56bfd0c14c91a 100644 +--- a/drivers/input/touchscreen/edt-ft5x06.c ++++ b/drivers/input/touchscreen/edt-ft5x06.c +@@ -70,8 +70,9 @@ + #define EDT_RAW_DATA_DELAY 1000 /* usec */ + + enum edt_ver { +- M06, +- M09, ++ EDT_M06, ++ EDT_M09, ++ GENERIC_FT, + }; + + struct edt_reg_addr { +@@ -179,14 +180,15 @@ static irqreturn_t edt_ft5x06_ts_isr(int irq, void *dev_id) + int error; + + switch (tsdata->version) { +- case M06: ++ case EDT_M06: + cmd = 0xf9; /* tell the controller to send touch data */ + offset = 5; /* where the actual touch data starts */ + tplen = 4; /* data comes in so called frames */ + crclen = 1; /* length of the crc data */ + break; + +- case M09: ++ case EDT_M09: ++ case GENERIC_FT: + cmd = 0x0; + offset = 3; + tplen = 6; +@@ -210,7 +212,7 @@ static irqreturn_t edt_ft5x06_ts_isr(int irq, void *dev_id) + } + + /* M09 does not send header or CRC */ +- if (tsdata->version == M06) { ++ if (tsdata->version == EDT_M06) { + if (rdbuf[0] != 0xaa || rdbuf[1] != 0xaa || + rdbuf[2] != datalen) { + dev_err_ratelimited(dev, +@@ -233,7 +235,7 @@ static irqreturn_t edt_ft5x06_ts_isr(int irq, void *dev_id) + continue; + + /* M06 sometimes sends bogus coordinates in TOUCH_DOWN */ +- if (tsdata->version == M06 && type == TOUCH_EVENT_DOWN) ++ if (tsdata->version == EDT_M06 && type == TOUCH_EVENT_DOWN) + continue; + + x = ((buf[0] << 8) | buf[1]) & 0x0fff; +@@ -264,14 +266,15 @@ static int edt_ft5x06_register_write(struct edt_ft5x06_ts_data *tsdata, + u8 wrbuf[4]; + + switch (tsdata->version) { +- case M06: ++ case EDT_M06: + wrbuf[0] = tsdata->factory_mode ? 0xf3 : 0xfc; + wrbuf[1] = tsdata->factory_mode ? addr & 0x7f : addr & 0x3f; + wrbuf[2] = value; + wrbuf[3] = wrbuf[0] ^ wrbuf[1] ^ wrbuf[2]; + return edt_ft5x06_ts_readwrite(tsdata->client, 4, + wrbuf, 0, NULL); +- case M09: ++ case EDT_M09: ++ case GENERIC_FT: + wrbuf[0] = addr; + wrbuf[1] = value; + +@@ -290,7 +293,7 @@ static int edt_ft5x06_register_read(struct edt_ft5x06_ts_data *tsdata, + int error; + + switch (tsdata->version) { +- case M06: ++ case EDT_M06: + wrbuf[0] = tsdata->factory_mode ? 0xf3 : 0xfc; + wrbuf[1] = tsdata->factory_mode ? addr & 0x7f : addr & 0x3f; + wrbuf[1] |= tsdata->factory_mode ? 0x80 : 0x40; +@@ -309,7 +312,8 @@ static int edt_ft5x06_register_read(struct edt_ft5x06_ts_data *tsdata, + } + break; + +- case M09: ++ case EDT_M09: ++ case GENERIC_FT: + wrbuf[0] = addr; + error = edt_ft5x06_ts_readwrite(tsdata->client, 1, + wrbuf, 1, rdbuf); +@@ -368,11 +372,12 @@ static ssize_t edt_ft5x06_setting_show(struct device *dev, + } + + switch (tsdata->version) { +- case M06: ++ case EDT_M06: + addr = attr->addr_m06; + break; + +- case M09: ++ case EDT_M09: ++ case GENERIC_FT: + addr = attr->addr_m09; + break; + +@@ -437,11 +442,12 @@ static ssize_t edt_ft5x06_setting_store(struct device *dev, + } + + switch (tsdata->version) { +- case M06: ++ case EDT_M06: + addr = attr->addr_m06; + break; + +- case M09: ++ case EDT_M09: ++ case GENERIC_FT: + addr = attr->addr_m09; + break; + +@@ -508,7 +514,7 @@ static int edt_ft5x06_factory_mode(struct edt_ft5x06_ts_data *tsdata) + } + + /* mode register is 0x3c when in the work mode */ +- if (tsdata->version == M09) ++ if (tsdata->version != EDT_M06) + goto m09_out; + + error = edt_ft5x06_register_write(tsdata, WORK_REGISTER_OPMODE, 0x03); +@@ -545,7 +551,7 @@ static int edt_ft5x06_factory_mode(struct edt_ft5x06_ts_data *tsdata) + return error; + + m09_out: +- dev_err(&client->dev, "No factory mode support for M09\n"); ++ dev_err(&client->dev, "No factory mode support for M09/GENERIC_FT\n"); + return -EINVAL; + + } +@@ -779,7 +785,7 @@ static int edt_ft5x06_ts_identify(struct i2c_client *client, + * at least M09 won't send 3 bytes here + */ + if (!(strncasecmp(rdbuf + 1, "EP0", 3))) { +- tsdata->version = M06; ++ tsdata->version = EDT_M06; + + /* remove last '$' end marker */ + rdbuf[EDT_NAME_LEN - 1] = '\0'; +@@ -793,8 +799,16 @@ static int edt_ft5x06_ts_identify(struct i2c_client *client, + strlcpy(model_name, rdbuf + 1, EDT_NAME_LEN); + strlcpy(fw_version, p ? p : "", EDT_NAME_LEN); + } else { +- /* since there are only two versions around (M06, M09) */ +- tsdata->version = M09; ++ /* If it is not an EDT M06 touchscreen, then the model ++ * detection is a bit hairy. The different ft5x06 ++ * firmares around don't reliably implement the ++ * identification registers. Well, we'll take a shot. ++ * ++ * The main difference between generic focaltec based ++ * touches and EDT M09 is that we know how to retrieve ++ * the max coordinates for the latter. ++ */ ++ tsdata->version = GENERIC_FT; + + error = edt_ft5x06_ts_readwrite(client, 1, "\xA6", + 2, rdbuf); +@@ -808,8 +822,34 @@ static int edt_ft5x06_ts_identify(struct i2c_client *client, + if (error) + return error; + +- snprintf(model_name, EDT_NAME_LEN, "EP0%i%i0M09", +- rdbuf[0] >> 4, rdbuf[0] & 0x0F); ++ /* This "model identification" is not exact. Unfortunately ++ * not all firmwares for the ft5x06 put useful values in ++ * the identification registers. ++ */ ++ switch (rdbuf[0]) { ++ case 0x35: /* EDT EP0350M09 */ ++ case 0x43: /* EDT EP0430M09 */ ++ case 0x50: /* EDT EP0500M09 */ ++ case 0x57: /* EDT EP0570M09 */ ++ case 0x70: /* EDT EP0700M09 */ ++ tsdata->version = EDT_M09; ++ snprintf(model_name, EDT_NAME_LEN, "EP0%i%i0M09", ++ rdbuf[0] >> 4, rdbuf[0] & 0x0F); ++ break; ++ case 0xa1: /* EDT EP1010ML00 */ ++ tsdata->version = EDT_M09; ++ snprintf(model_name, EDT_NAME_LEN, "EP%i%i0ML00", ++ rdbuf[0] >> 4, rdbuf[0] & 0x0F); ++ break; ++ case 0x5a: /* Solomon Goldentek Display */ ++ snprintf(model_name, EDT_NAME_LEN, "GKTW50SCED1R0"); ++ break; ++ default: ++ snprintf(model_name, EDT_NAME_LEN, ++ "generic ft5x06 (%02x)", ++ rdbuf[0]); ++ break; ++ } + } + + return 0; +@@ -853,8 +893,16 @@ edt_ft5x06_ts_get_parameters(struct edt_ft5x06_ts_data *tsdata) + if (reg_addr->reg_report_rate != NO_REGISTER) + tsdata->report_rate = edt_ft5x06_register_read(tsdata, + reg_addr->reg_report_rate); +- tsdata->num_x = edt_ft5x06_register_read(tsdata, reg_addr->reg_num_x); +- tsdata->num_y = edt_ft5x06_register_read(tsdata, reg_addr->reg_num_y); ++ if (tsdata->version == EDT_M06 || ++ tsdata->version == EDT_M09) { ++ tsdata->num_x = edt_ft5x06_register_read(tsdata, ++ reg_addr->reg_num_x); ++ tsdata->num_y = edt_ft5x06_register_read(tsdata, ++ reg_addr->reg_num_y); ++ } else { ++ tsdata->num_x = -1; ++ tsdata->num_y = -1; ++ } + } + + static void +@@ -863,7 +911,7 @@ edt_ft5x06_ts_set_regs(struct edt_ft5x06_ts_data *tsdata) + struct edt_reg_addr *reg_addr = &tsdata->reg_addr; + + switch (tsdata->version) { +- case M06: ++ case EDT_M06: + reg_addr->reg_threshold = WORK_REGISTER_THRESHOLD; + reg_addr->reg_report_rate = WORK_REGISTER_REPORT_RATE; + reg_addr->reg_gain = WORK_REGISTER_GAIN; +@@ -872,7 +920,7 @@ edt_ft5x06_ts_set_regs(struct edt_ft5x06_ts_data *tsdata) + reg_addr->reg_num_y = WORK_REGISTER_NUM_Y; + break; + +- case M09: ++ case EDT_M09: + reg_addr->reg_threshold = M09_REGISTER_THRESHOLD; + reg_addr->reg_report_rate = NO_REGISTER; + reg_addr->reg_gain = M09_REGISTER_GAIN; +@@ -880,6 +928,13 @@ edt_ft5x06_ts_set_regs(struct edt_ft5x06_ts_data *tsdata) + reg_addr->reg_num_x = M09_REGISTER_NUM_X; + reg_addr->reg_num_y = M09_REGISTER_NUM_Y; + break; ++ ++ case GENERIC_FT: ++ /* this is a guesswork */ ++ reg_addr->reg_threshold = M09_REGISTER_THRESHOLD; ++ reg_addr->reg_gain = M09_REGISTER_GAIN; ++ reg_addr->reg_offset = M09_REGISTER_OFFSET; ++ break; + } + } + +@@ -969,10 +1024,19 @@ static int edt_ft5x06_ts_probe(struct i2c_client *client, + input->id.bustype = BUS_I2C; + input->dev.parent = &client->dev; + +- input_set_abs_params(input, ABS_MT_POSITION_X, +- 0, tsdata->num_x * 64 - 1, 0, 0); +- input_set_abs_params(input, ABS_MT_POSITION_Y, +- 0, tsdata->num_y * 64 - 1, 0, 0); ++ if (tsdata->version == EDT_M06 || ++ tsdata->version == EDT_M09) { ++ input_set_abs_params(input, ABS_MT_POSITION_X, ++ 0, tsdata->num_x * 64 - 1, 0, 0); ++ input_set_abs_params(input, ABS_MT_POSITION_Y, ++ 0, tsdata->num_y * 64 - 1, 0, 0); ++ } else { ++ /* Unknown maximum values. Specify via devicetree */ ++ input_set_abs_params(input, ABS_MT_POSITION_X, ++ 0, 65535, 0, 0); ++ input_set_abs_params(input, ABS_MT_POSITION_Y, ++ 0, 65535, 0, 0); ++ } + + touchscreen_parse_properties(input, true, &tsdata->prop); + diff --git a/recipes-kernel/linux/linux-karo-4.9.11/ethernet-update-driver.patch b/recipes-kernel/linux/linux-karo-4.9.11/ethernet-update-driver.patch new file mode 100644 index 0000000..854443c --- /dev/null +++ b/recipes-kernel/linux/linux-karo-4.9.11/ethernet-update-driver.patch @@ -0,0 +1,17985 @@ +diff --git a/drivers/net/ethernet/freescale/Kconfig b/drivers/net/ethernet/freescale/Kconfig +index 2204c57..25e3425 100644 +--- a/drivers/net/ethernet/freescale/Kconfig ++++ b/drivers/net/ethernet/freescale/Kconfig +@@ -7,10 +7,11 @@ config NET_VENDOR_FREESCALE + default y + depends on FSL_SOC || QUICC_ENGINE || CPM1 || CPM2 || PPC_MPC512x || \ + M523x || M527x || M5272 || M528x || M520x || M532x || \ +- ARCH_MXC || ARCH_MXS || (PPC_MPC52xx && PPC_BESTCOMM) || \ +- ARCH_LAYERSCAPE ++ ARCH_MXC || ARCH_MXS || (PPC_MPC52xx && PPC_BESTCOMM) + ---help--- +- If you have a network (Ethernet) card belonging to this class, say Y. ++ If you have a network (Ethernet) card belonging to this class, say Y ++ and read the Ethernet-HOWTO, available from ++ . + + Note that the answer to this question doesn't directly affect the + kernel: saying N will just cause the configurator to skip all +@@ -22,8 +23,8 @@ if NET_VENDOR_FREESCALE + config FEC + tristate "FEC ethernet controller (of ColdFire and some i.MX CPUs)" + depends on (M523x || M527x || M5272 || M528x || M520x || M532x || \ +- ARM || ARM64) +- default y ++ ARCH_MXC || SOC_IMX28) ++ default ARCH_MXC || SOC_IMX28 if ARM + select PHYLIB + select PTP_1588_CLOCK + ---help--- +@@ -54,7 +55,6 @@ config FEC_MPC52xx_MDIO + If compiled as module, it will be called fec_mpc52xx_phy. + + source "drivers/net/ethernet/freescale/fs_enet/Kconfig" +-source "drivers/net/ethernet/freescale/fman/Kconfig" + + config FSL_PQ_MDIO + tristate "Freescale PQ MDIO" +@@ -85,12 +85,12 @@ config UGETH_TX_ON_DEMAND + + config GIANFAR + tristate "Gianfar Ethernet" ++ depends on FSL_SOC + select FSL_PQ_MDIO + select PHYLIB + select CRC32 + ---help--- + This driver supports the Gigabit TSEC on the MPC83xx, MPC85xx, +- and MPC86xx family of chips, the eTSEC on LS1021A and the FEC +- on the 8540. ++ and MPC86xx family of chips, and the FEC on the 8540. + + endif # NET_VENDOR_FREESCALE +diff --git a/drivers/net/ethernet/freescale/Makefile b/drivers/net/ethernet/freescale/Makefile +index 7f022dd..71debd1 100644 +--- a/drivers/net/ethernet/freescale/Makefile ++++ b/drivers/net/ethernet/freescale/Makefile +@@ -3,10 +3,7 @@ + # + + obj-$(CONFIG_FEC) += fec.o +-fec-objs :=fec_main.o fec_fixup.o fec_ptp.o +-CFLAGS_fec_main.o := -D__CHECK_ENDIAN__ +-CFLAGS_fec_ptp.o := -D__CHECK_ENDIAN__ +- ++fec-objs :=fec_main.o fec_ptp.o + obj-$(CONFIG_FEC_MPC52xx) += fec_mpc52xx.o + ifeq ($(CONFIG_FEC_MPC52xx_MDIO),y) + obj-$(CONFIG_FEC_MPC52xx) += fec_mpc52xx_phy.o +@@ -20,5 +17,3 @@ gianfar_driver-objs := gianfar.o \ + gianfar_ethtool.o + obj-$(CONFIG_UCC_GETH) += ucc_geth_driver.o + ucc_geth_driver-objs := ucc_geth.o ucc_geth_ethtool.o +- +-obj-$(CONFIG_FSL_FMAN) += fman/ +diff --git a/drivers/net/ethernet/freescale/fec.h b/drivers/net/ethernet/freescale/fec.h +index 1d7b3cc..ecdc711 100644 +--- a/drivers/net/ethernet/freescale/fec.h ++++ b/drivers/net/ethernet/freescale/fec.h +@@ -20,8 +20,8 @@ + #include + + #if defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x) || \ +- defined(CONFIG_M520x) || defined(CONFIG_M532x) || defined(CONFIG_ARM) || \ +- defined(CONFIG_ARM64) ++ defined(CONFIG_M520x) || defined(CONFIG_M532x) || \ ++ defined(CONFIG_ARCH_MXC) || defined(CONFIG_SOC_IMX28) + /* + * Just figures, Motorola would have to change the offsets for + * registers in the same peripheral device on different models +@@ -192,45 +192,28 @@ + + /* + * Define the buffer descriptor structure. +- * +- * Evidently, ARM SoCs have the FEC block generated in a +- * little endian mode so adjust endianness accordingly. + */ +-#if defined(CONFIG_ARM) || defined(CONFIG_ARM64) +-#define fec32_to_cpu le32_to_cpu +-#define fec16_to_cpu le16_to_cpu +-#define cpu_to_fec32 cpu_to_le32 +-#define cpu_to_fec16 cpu_to_le16 +-#define __fec32 __le32 +-#define __fec16 __le16 +- ++#if defined(CONFIG_ARCH_MXC) || defined(CONFIG_SOC_IMX28) + struct bufdesc { +- __fec16 cbd_datlen; /* Data length */ +- __fec16 cbd_sc; /* Control and status info */ +- __fec32 cbd_bufaddr; /* Buffer address */ ++ unsigned short cbd_datlen; /* Data length */ ++ unsigned short cbd_sc; /* Control and status info */ ++ unsigned long cbd_bufaddr; /* Buffer address */ + }; + #else +-#define fec32_to_cpu be32_to_cpu +-#define fec16_to_cpu be16_to_cpu +-#define cpu_to_fec32 cpu_to_be32 +-#define cpu_to_fec16 cpu_to_be16 +-#define __fec32 __be32 +-#define __fec16 __be16 +- + struct bufdesc { +- __fec16 cbd_sc; /* Control and status info */ +- __fec16 cbd_datlen; /* Data length */ +- __fec32 cbd_bufaddr; /* Buffer address */ ++ unsigned short cbd_sc; /* Control and status info */ ++ unsigned short cbd_datlen; /* Data length */ ++ unsigned long cbd_bufaddr; /* Buffer address */ + }; + #endif + + struct bufdesc_ex { + struct bufdesc desc; +- __fec32 cbd_esc; +- __fec32 cbd_prot; +- __fec32 cbd_bdu; +- __fec32 ts; +- __fec16 res0[4]; ++ unsigned long cbd_esc; ++ unsigned long cbd_prot; ++ unsigned long cbd_bdu; ++ unsigned long ts; ++ unsigned short res0[4]; + }; + + /* +@@ -294,7 +277,7 @@ struct bufdesc_ex { + + + /* This device has up to three irqs on some platforms */ +-#define FEC_IRQ_NUM 4 ++#define FEC_IRQ_NUM 3 + + /* Maximum number of queues supported + * ENET with AVB IP can support up to 3 independent tx queues and rx queues. +@@ -312,6 +295,12 @@ struct bufdesc_ex { + #define FEC_R_BUFF_SIZE(X) (((X) == 1) ? FEC_R_BUFF_SIZE_1 : \ + (((X) == 2) ? \ + FEC_R_BUFF_SIZE_2 : FEC_R_BUFF_SIZE_0)) ++#define FEC_R_DES_ACTIVE(X) (((X) == 1) ? FEC_R_DES_ACTIVE_1 : \ ++ (((X) == 2) ? \ ++ FEC_R_DES_ACTIVE_2 : FEC_R_DES_ACTIVE_0)) ++#define FEC_X_DES_ACTIVE(X) (((X) == 1) ? FEC_X_DES_ACTIVE_1 : \ ++ (((X) == 2) ? \ ++ FEC_X_DES_ACTIVE_2 : FEC_X_DES_ACTIVE_0)) + + #define FEC_DMA_CFG(X) (((X) == 2) ? FEC_DMA_CFG_2 : FEC_DMA_CFG_1) + +@@ -379,7 +368,6 @@ struct bufdesc_ex { + #define FEC_ENET_TS_TIMER ((uint)0x00008000) + + #define FEC_DEFAULT_IMASK (FEC_ENET_TXF | FEC_ENET_RXF | FEC_ENET_MII | FEC_ENET_TS_TIMER) +-#define FEC_NAPI_IMASK (FEC_ENET_MII | FEC_ENET_TS_TIMER) + #define FEC_RX_DISABLED_IMASK (FEC_DEFAULT_IMASK & (~FEC_ENET_RXF)) + + #define FEC_ENET_ETHEREN ((uint)0x00000002) +@@ -448,32 +436,12 @@ struct bufdesc_ex { + #define FEC_QUIRK_SINGLE_MDIO (1 << 11) + /* Controller supports RACC register */ + #define FEC_QUIRK_HAS_RACC (1 << 12) +-/* Controller supports interrupt coalesc */ +-#define FEC_QUIRK_HAS_COALESCE (1 << 13) +-/* Interrupt doesn't wake CPU from deep idle */ +-#define FEC_QUIRK_ERR006687 (1 << 14) + /* + * i.MX6Q/DL ENET cannot wake up system in wait mode because ENET tx & rx + * interrupt signal don't connect to GPC. So use pm qos to avoid cpu enter + * to wait mode. + */ +-#define FEC_QUIRK_BUG_WAITMODE (1 << 15) +- +-/* PHY fixup flag define */ +-#define FEC_QUIRK_AR8031_FIXUP (1 << 0) +- +-struct bufdesc_prop { +- int qid; +- /* Address of Rx and Tx buffers */ +- struct bufdesc *base; +- struct bufdesc *last; +- struct bufdesc *cur; +- void __iomem *reg_desc_active; +- dma_addr_t dma; +- unsigned short ring_size; +- unsigned char dsize; +- unsigned char dsize_log2; +-}; ++#define FEC_QUIRK_BUG_WAITMODE (1 << 13) + + struct fec_enet_stop_mode { + struct regmap *gpr; +@@ -482,21 +450,32 @@ struct fec_enet_stop_mode { + }; + + struct fec_enet_priv_tx_q { +- struct bufdesc_prop bd; ++ int index; + unsigned char *tx_bounce[TX_RING_SIZE]; + struct sk_buff *tx_skbuff[TX_RING_SIZE]; + ++ dma_addr_t bd_dma; ++ struct bufdesc *tx_bd_base; ++ uint tx_ring_size; ++ + unsigned short tx_stop_threshold; + unsigned short tx_wake_threshold; + ++ struct bufdesc *cur_tx; + struct bufdesc *dirty_tx; + char *tso_hdrs; + dma_addr_t tso_hdrs_dma; + }; + + struct fec_enet_priv_rx_q { +- struct bufdesc_prop bd; ++ int index; + struct sk_buff *rx_skbuff[RX_RING_SIZE]; ++ ++ dma_addr_t bd_dma; ++ struct bufdesc *rx_bd_base; ++ uint rx_ring_size; ++ ++ struct bufdesc *cur_rx; + }; + + /* The FEC buffer descriptors track the ring buffers. The rx_bd_base and +@@ -536,20 +515,22 @@ struct fec_enet_private { + unsigned long work_ts; + unsigned long work_mdio; + ++ unsigned short bufdesc_size; ++ + struct platform_device *pdev; + + int dev_id; + + /* Phylib and MDIO interface */ + struct mii_bus *mii_bus; ++ struct phy_device *phy_dev; + int mii_timeout; + int mii_bus_share; +- bool active_in_suspend; ++ bool miibus_up_failed; + uint phy_speed; + phy_interface_t phy_interface; + struct device_node *phy_node; + int link; +- bool fixed_link; + int full_duplex; + int speed; + struct completion mdio_done; +@@ -559,7 +540,8 @@ struct fec_enet_private { + int wol_flag; + int wake_irq; + u32 quirks; +- u32 fixups; ++ int phy_reset_gpio; ++ int phy_reset_duration; + + struct napi_struct napi; + int csum_flags; +@@ -602,19 +584,14 @@ struct fec_enet_private { + int pps_enable; + unsigned int next_counter; + +- u64 ethtool_stats[0]; +- + struct fec_enet_stop_mode gpr; + }; + + void fec_ptp_init(struct platform_device *pdev); +-void fec_ptp_stop(struct platform_device *pdev); + void fec_ptp_start_cyclecounter(struct net_device *ndev); + int fec_ptp_set(struct net_device *ndev, struct ifreq *ifr); + int fec_ptp_get(struct net_device *ndev, struct ifreq *ifr); + uint fec_ptp_check_pps_event(struct fec_enet_private *fep); +-void fec_enet_register_fixup(struct net_device *ndev); +-int of_fec_enet_parse_fixup(struct device_node *np); + + /****************************************************************************/ + #endif /* FEC_H */ +diff --git a/drivers/net/ethernet/freescale/fec_fixup.c b/drivers/net/ethernet/freescale/fec_fixup.c +deleted file mode 100644 +index 5a8497c..0000000 +--- a/drivers/net/ethernet/freescale/fec_fixup.c ++++ /dev/null +@@ -1,74 +0,0 @@ +-/* +- * Copyright 2017 NXP +- * +- * 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 "fec.h" +- +-#define PHY_ID_AR8031 0x004dd074 +- +-static int ar8031_phy_fixup(struct phy_device *dev) +-{ +- u16 val; +- +- /* Set RGMII IO voltage to 1.8V */ +- phy_write(dev, 0x1d, 0x1f); +- phy_write(dev, 0x1e, 0x8); +- +- /* Disable phy AR8031 SmartEEE function */ +- phy_write(dev, 0xd, 0x3); +- phy_write(dev, 0xe, 0x805d); +- phy_write(dev, 0xd, 0x4003); +- val = phy_read(dev, 0xe); +- val &= ~(0x1 << 8); +- phy_write(dev, 0xe, val); +- +- /* Introduce tx clock delay */ +- phy_write(dev, 0x1d, 0x5); +- phy_write(dev, 0x1e, 0x100); +- +- return 0; +-} +- +-void fec_enet_register_fixup(struct net_device *ndev) +-{ +- struct fec_enet_private *fep = netdev_priv(ndev); +- static int registered = 0; +- int err; +- +- if (!IS_BUILTIN(CONFIG_PHYLIB)) +- return; +- +- if (fep->fixups & FEC_QUIRK_AR8031_FIXUP) { +- static int ar8031_registered = 0; +- +- if (ar8031_registered) +- return; +- err = phy_register_fixup_for_uid(PHY_ID_AR8031, 0xffffffef, +- ar8031_phy_fixup); +- if (err) +- netdev_info(ndev, "Cannot register PHY board fixup\n"); +- registered = 1; +- } +-} +- +-int of_fec_enet_parse_fixup(struct device_node *np) +-{ +- int fixups = 0; +- +- if (of_get_property(np, "fsl,ar8031-phy-fixup", NULL)) +- fixups |= FEC_QUIRK_AR8031_FIXUP; +- +- return fixups; +-} +diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c +index 41a31f2..15c06df 100644 +--- a/drivers/net/ethernet/freescale/fec_main.c ++++ b/drivers/net/ethernet/freescale/fec_main.c +@@ -19,8 +19,6 @@ + * Copyright (c) 2004-2006 Macq Electronique SA. + * + * Copyright (C) 2010-2014 Freescale Semiconductor, Inc. +- * +- * Copyright 2017 NXP + */ + + #include +@@ -48,9 +46,7 @@ + #include + #include + #include +-#include + #include +-#include + #include + #include + #include +@@ -68,12 +64,12 @@ + #include + + #include +-#include + + #include "fec.h" + + static void set_multicast_list(struct net_device *ndev); + static void fec_enet_itr_coal_init(struct net_device *ndev); ++static void fec_reset_phy(struct platform_device *pdev); + + #define DRIVER_NAME "fec" + +@@ -87,7 +83,6 @@ static const u16 fec_enet_vlan_pri_to_queue[8] = {1, 1, 1, 1, 2, 2, 2, 2}; + #define FEC_ENET_RAEM_V 0x8 + #define FEC_ENET_RAFL_V 0x8 + #define FEC_ENET_OPD_V 0xFFF0 +-#define FEC_MDIO_PM_TIMEOUT 100 /* ms */ + + static struct platform_device_id fec_devtype[] = { + { +@@ -96,10 +91,10 @@ static struct platform_device_id fec_devtype[] = { + .driver_data = 0, + }, { + .name = "imx25-fec", +- .driver_data = FEC_QUIRK_USE_GASKET, ++ .driver_data = FEC_QUIRK_USE_GASKET | FEC_QUIRK_HAS_RACC, + }, { + .name = "imx27-fec", +- .driver_data = 0, ++ .driver_data = FEC_QUIRK_HAS_RACC, + }, { + .name = "imx28-fec", + .driver_data = FEC_QUIRK_ENET_MAC | FEC_QUIRK_SWAP_FRAME | +@@ -119,20 +114,12 @@ static struct platform_device_id fec_devtype[] = { + FEC_QUIRK_HAS_BUFDESC_EX | FEC_QUIRK_HAS_CSUM | + FEC_QUIRK_HAS_VLAN | FEC_QUIRK_HAS_AVB | + FEC_QUIRK_ERR007885 | FEC_QUIRK_BUG_CAPTURE | +- FEC_QUIRK_HAS_RACC | FEC_QUIRK_HAS_COALESCE, ++ FEC_QUIRK_HAS_RACC, + }, { + .name = "imx6ul-fec", + .driver_data = FEC_QUIRK_ENET_MAC | FEC_QUIRK_HAS_GBIT | + FEC_QUIRK_HAS_BUFDESC_EX | FEC_QUIRK_HAS_CSUM | +- FEC_QUIRK_HAS_VLAN | FEC_QUIRK_BUG_CAPTURE | +- FEC_QUIRK_HAS_RACC | FEC_QUIRK_HAS_COALESCE, +- }, { +- .name = "imx8qm-fec", +- .driver_data = FEC_QUIRK_ENET_MAC | FEC_QUIRK_HAS_GBIT | +- FEC_QUIRK_HAS_BUFDESC_EX | FEC_QUIRK_HAS_CSUM | +- FEC_QUIRK_HAS_VLAN | FEC_QUIRK_HAS_AVB | +- FEC_QUIRK_ERR007885 | FEC_QUIRK_BUG_CAPTURE | +- FEC_QUIRK_HAS_RACC | FEC_QUIRK_HAS_COALESCE, ++ FEC_QUIRK_HAS_VLAN, + }, { + /* sentinel */ + } +@@ -147,7 +134,6 @@ enum imx_fec_type { + MVF600_FEC, + IMX6SX_FEC, + IMX6UL_FEC, +- IMX8QM_FEC, + }; + + static const struct of_device_id fec_dt_ids[] = { +@@ -158,7 +144,6 @@ static const struct of_device_id fec_dt_ids[] = { + { .compatible = "fsl,mvf600-fec", .data = &fec_devtype[MVF600_FEC], }, + { .compatible = "fsl,imx6sx-fec", .data = &fec_devtype[IMX6SX_FEC], }, + { .compatible = "fsl,imx6ul-fec", .data = &fec_devtype[IMX6UL_FEC], }, +- { .compatible = "fsl,imx8qm-fec", .data = &fec_devtype[IMX8QM_FEC], }, + { /* sentinel */ } + }; + MODULE_DEVICE_TABLE(of, fec_dt_ids); +@@ -196,7 +181,6 @@ MODULE_PARM_DESC(macaddr, "FEC Ethernet MAC address"); + /* FEC receive acceleration */ + #define FEC_RACC_IPDIS (1 << 1) + #define FEC_RACC_PRODIS (1 << 2) +-#define FEC_RACC_SHIFT16 BIT(7) + #define FEC_RACC_OPTIONS (FEC_RACC_IPDIS | FEC_RACC_PRODIS) + + /* +@@ -205,8 +189,7 @@ MODULE_PARM_DESC(macaddr, "FEC Ethernet MAC address"); + * account when setting it. + */ + #if defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x) || \ +- defined(CONFIG_M520x) || defined(CONFIG_M532x) || defined(CONFIG_ARM) || \ +- defined(CONFIG_ARM64) ++ defined(CONFIG_M520x) || defined(CONFIG_M532x) || defined(CONFIG_ARM) + #define OPT_FRAME_SIZE (PKT_MAXBUF_SIZE << 16) + #else + #define OPT_FRAME_SIZE 0 +@@ -244,38 +227,86 @@ MODULE_PARM_DESC(macaddr, "FEC Ethernet MAC address"); + + #define IS_TSO_HEADER(txq, addr) \ + ((addr >= txq->tso_hdrs_dma) && \ +- (addr < txq->tso_hdrs_dma + txq->bd.ring_size * TSO_HEADER_SIZE)) ++ (addr < txq->tso_hdrs_dma + txq->tx_ring_size * TSO_HEADER_SIZE)) + + static int mii_cnt; + +-static struct bufdesc *fec_enet_get_nextdesc(struct bufdesc *bdp, +- struct bufdesc_prop *bd) +-{ +- return (bdp >= bd->last) ? bd->base +- : (struct bufdesc *)(((void *)bdp) + bd->dsize); +-} ++static inline ++struct bufdesc *fec_enet_get_nextdesc(struct bufdesc *bdp, ++ struct fec_enet_private *fep, ++ int queue_id) ++{ ++ struct bufdesc *new_bd = bdp + 1; ++ struct bufdesc_ex *ex_new_bd = (struct bufdesc_ex *)bdp + 1; ++ struct fec_enet_priv_tx_q *txq = fep->tx_queue[queue_id]; ++ struct fec_enet_priv_rx_q *rxq = fep->rx_queue[queue_id]; ++ struct bufdesc_ex *ex_base; ++ struct bufdesc *base; ++ int ring_size; ++ ++ if (bdp >= txq->tx_bd_base) { ++ base = txq->tx_bd_base; ++ ring_size = txq->tx_ring_size; ++ ex_base = (struct bufdesc_ex *)txq->tx_bd_base; ++ } else { ++ base = rxq->rx_bd_base; ++ ring_size = rxq->rx_ring_size; ++ ex_base = (struct bufdesc_ex *)rxq->rx_bd_base; ++ } + +-static struct bufdesc *fec_enet_get_prevdesc(struct bufdesc *bdp, +- struct bufdesc_prop *bd) +-{ +- return (bdp <= bd->base) ? bd->last +- : (struct bufdesc *)(((void *)bdp) - bd->dsize); ++ if (fep->bufdesc_ex) ++ return (struct bufdesc *)((ex_new_bd >= (ex_base + ring_size)) ? ++ ex_base : ex_new_bd); ++ else ++ return (new_bd >= (base + ring_size)) ? ++ base : new_bd; ++} ++ ++static inline ++struct bufdesc *fec_enet_get_prevdesc(struct bufdesc *bdp, ++ struct fec_enet_private *fep, ++ int queue_id) ++{ ++ struct bufdesc *new_bd = bdp - 1; ++ struct bufdesc_ex *ex_new_bd = (struct bufdesc_ex *)bdp - 1; ++ struct fec_enet_priv_tx_q *txq = fep->tx_queue[queue_id]; ++ struct fec_enet_priv_rx_q *rxq = fep->rx_queue[queue_id]; ++ struct bufdesc_ex *ex_base; ++ struct bufdesc *base; ++ int ring_size; ++ ++ if (bdp >= txq->tx_bd_base) { ++ base = txq->tx_bd_base; ++ ring_size = txq->tx_ring_size; ++ ex_base = (struct bufdesc_ex *)txq->tx_bd_base; ++ } else { ++ base = rxq->rx_bd_base; ++ ring_size = rxq->rx_ring_size; ++ ex_base = (struct bufdesc_ex *)rxq->rx_bd_base; ++ } ++ ++ if (fep->bufdesc_ex) ++ return (struct bufdesc *)((ex_new_bd < ex_base) ? ++ (ex_new_bd + ring_size) : ex_new_bd); ++ else ++ return (new_bd < base) ? (new_bd + ring_size) : new_bd; + } + +-static int fec_enet_get_bd_index(struct bufdesc *bdp, +- struct bufdesc_prop *bd) ++static int fec_enet_get_bd_index(struct bufdesc *base, struct bufdesc *bdp, ++ struct fec_enet_private *fep) + { +- return ((const char *)bdp - (const char *)bd->base) >> bd->dsize_log2; ++ return ((const char *)bdp - (const char *)base) / fep->bufdesc_size; + } + +-static int fec_enet_get_free_txdesc_num(struct fec_enet_priv_tx_q *txq) ++static int fec_enet_get_free_txdesc_num(struct fec_enet_private *fep, ++ struct fec_enet_priv_tx_q *txq) + { + int entries; + +- entries = (((const char *)txq->dirty_tx - +- (const char *)txq->bd.cur) >> txq->bd.dsize_log2) - 1; ++ entries = ((const char *)txq->dirty_tx - ++ (const char *)txq->cur_tx) / fep->bufdesc_size - 1; + +- return entries >= 0 ? entries : entries + txq->bd.ring_size; ++ return entries >= 0 ? entries : entries + txq->tx_ring_size; + } + + static void swap_buffer(void *bufaddr, int len) +@@ -308,20 +339,18 @@ static void fec_dump(struct net_device *ndev) + pr_info("Nr SC addr len SKB\n"); + + txq = fep->tx_queue[0]; +- bdp = txq->bd.base; ++ bdp = txq->tx_bd_base; + + do { +- pr_info("%3u %c%c 0x%04x 0x%08x %4u %p\n", ++ pr_info("%3u %c%c 0x%04x 0x%08lx %4u %p\n", + index, +- bdp == txq->bd.cur ? 'S' : ' ', ++ bdp == txq->cur_tx ? 'S' : ' ', + bdp == txq->dirty_tx ? 'H' : ' ', +- fec16_to_cpu(bdp->cbd_sc), +- fec32_to_cpu(bdp->cbd_bufaddr), +- fec16_to_cpu(bdp->cbd_datlen), ++ bdp->cbd_sc, bdp->cbd_bufaddr, bdp->cbd_datlen, + txq->tx_skbuff[index]); +- bdp = fec_enet_get_nextdesc(bdp, &txq->bd); ++ bdp = fec_enet_get_nextdesc(bdp, fep, 0); + index++; +- } while (bdp != txq->bd.base); ++ } while (bdp != txq->tx_bd_base); + } + + static inline bool is_ipv4_pkt(struct sk_buff *skb) +@@ -352,9 +381,10 @@ fec_enet_txq_submit_frag_skb(struct fec_enet_priv_tx_q *txq, + struct net_device *ndev) + { + struct fec_enet_private *fep = netdev_priv(ndev); +- struct bufdesc *bdp = txq->bd.cur; ++ struct bufdesc *bdp = txq->cur_tx; + struct bufdesc_ex *ebdp; + int nr_frags = skb_shinfo(skb)->nr_frags; ++ unsigned short queue = skb_get_queue_mapping(skb); + int frag, frag_len; + unsigned short status; + unsigned int estatus = 0; +@@ -366,10 +396,10 @@ fec_enet_txq_submit_frag_skb(struct fec_enet_priv_tx_q *txq, + + for (frag = 0; frag < nr_frags; frag++) { + this_frag = &skb_shinfo(skb)->frags[frag]; +- bdp = fec_enet_get_nextdesc(bdp, &txq->bd); ++ bdp = fec_enet_get_nextdesc(bdp, fep, queue); + ebdp = (struct bufdesc_ex *)bdp; + +- status = fec16_to_cpu(bdp->cbd_sc); ++ status = bdp->cbd_sc; + status &= ~BD_ENET_TX_STATS; + status |= (BD_ENET_TX_TC | BD_ENET_TX_READY); + frag_len = skb_shinfo(skb)->frags[frag].size; +@@ -387,16 +417,16 @@ fec_enet_txq_submit_frag_skb(struct fec_enet_priv_tx_q *txq, + + if (fep->bufdesc_ex) { + if (fep->quirks & FEC_QUIRK_HAS_AVB) +- estatus |= FEC_TX_BD_FTYPE(txq->bd.qid); ++ estatus |= FEC_TX_BD_FTYPE(queue); + if (skb->ip_summed == CHECKSUM_PARTIAL) + estatus |= BD_ENET_TX_PINS | BD_ENET_TX_IINS; + ebdp->cbd_bdu = 0; +- ebdp->cbd_esc = cpu_to_fec32(estatus); ++ ebdp->cbd_esc = estatus; + } + + bufaddr = page_address(this_frag->page.p) + this_frag->page_offset; + +- index = fec_enet_get_bd_index(bdp, &txq->bd); ++ index = fec_enet_get_bd_index(txq->tx_bd_base, bdp, fep); + if (((unsigned long) bufaddr) & fep->tx_align || + fep->quirks & FEC_QUIRK_SWAP_FRAME) { + memcpy(txq->tx_bounce[index], bufaddr, frag_len); +@@ -409,27 +439,24 @@ fec_enet_txq_submit_frag_skb(struct fec_enet_priv_tx_q *txq, + addr = dma_map_single(&fep->pdev->dev, bufaddr, frag_len, + DMA_TO_DEVICE); + if (dma_mapping_error(&fep->pdev->dev, addr)) { ++ dev_kfree_skb_any(skb); + if (net_ratelimit()) + netdev_err(ndev, "Tx DMA memory map failed\n"); + goto dma_mapping_error; + } + +- bdp->cbd_bufaddr = cpu_to_fec32(addr); +- bdp->cbd_datlen = cpu_to_fec16(frag_len); +- /* Make sure the updates to rest of the descriptor are +- * performed before transferring ownership. +- */ +- wmb(); +- bdp->cbd_sc = cpu_to_fec16(status); ++ bdp->cbd_bufaddr = addr; ++ bdp->cbd_datlen = frag_len; ++ bdp->cbd_sc = status; + } + + return bdp; + dma_mapping_error: +- bdp = txq->bd.cur; ++ bdp = txq->cur_tx; + for (i = 0; i < frag; i++) { +- bdp = fec_enet_get_nextdesc(bdp, &txq->bd); +- dma_unmap_single(&fep->pdev->dev, fec32_to_cpu(bdp->cbd_bufaddr), +- fec16_to_cpu(bdp->cbd_datlen), DMA_TO_DEVICE); ++ bdp = fec_enet_get_nextdesc(bdp, fep, queue); ++ dma_unmap_single(&fep->pdev->dev, bdp->cbd_bufaddr, ++ bdp->cbd_datlen, DMA_TO_DEVICE); + } + return ERR_PTR(-ENOMEM); + } +@@ -444,11 +471,12 @@ static int fec_enet_txq_submit_skb(struct fec_enet_priv_tx_q *txq, + dma_addr_t addr; + unsigned short status; + unsigned short buflen; ++ unsigned short queue; + unsigned int estatus = 0; + unsigned int index; + int entries_free; + +- entries_free = fec_enet_get_free_txdesc_num(txq); ++ entries_free = fec_enet_get_free_txdesc_num(fep, txq); + if (entries_free < MAX_SKB_FRAGS + 1) { + dev_kfree_skb_any(skb); + if (net_ratelimit()) +@@ -463,16 +491,17 @@ static int fec_enet_txq_submit_skb(struct fec_enet_priv_tx_q *txq, + } + + /* Fill in a Tx ring entry */ +- bdp = txq->bd.cur; ++ bdp = txq->cur_tx; + last_bdp = bdp; +- status = fec16_to_cpu(bdp->cbd_sc); ++ status = bdp->cbd_sc; + status &= ~BD_ENET_TX_STATS; + + /* Set buffer length and buffer pointer */ + bufaddr = skb->data; + buflen = skb_headlen(skb); + +- index = fec_enet_get_bd_index(bdp, &txq->bd); ++ queue = skb_get_queue_mapping(skb); ++ index = fec_enet_get_bd_index(txq->tx_bd_base, bdp, fep); + if (((unsigned long) bufaddr) & fep->tx_align || + fep->quirks & FEC_QUIRK_SWAP_FRAME) { + memcpy(txq->tx_bounce[index], skb->data, buflen); +@@ -493,12 +522,8 @@ static int fec_enet_txq_submit_skb(struct fec_enet_priv_tx_q *txq, + + if (nr_frags) { + last_bdp = fec_enet_txq_submit_frag_skb(txq, skb, ndev); +- if (IS_ERR(last_bdp)) { +- dma_unmap_single(&fep->pdev->dev, addr, +- buflen, DMA_TO_DEVICE); +- dev_kfree_skb_any(skb); ++ if (IS_ERR(last_bdp)) + return NETDEV_TX_OK; +- } + } else { + status |= (BD_ENET_TX_INTR | BD_ENET_TX_LAST); + if (fep->bufdesc_ex) { +@@ -508,8 +533,6 @@ static int fec_enet_txq_submit_skb(struct fec_enet_priv_tx_q *txq, + estatus |= BD_ENET_TX_TS; + } + } +- bdp->cbd_bufaddr = cpu_to_fec32(addr); +- bdp->cbd_datlen = cpu_to_fec16(buflen); + + if (fep->bufdesc_ex) { + +@@ -520,43 +543,41 @@ static int fec_enet_txq_submit_skb(struct fec_enet_priv_tx_q *txq, + skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS; + + if (fep->quirks & FEC_QUIRK_HAS_AVB) +- estatus |= FEC_TX_BD_FTYPE(txq->bd.qid); ++ estatus |= FEC_TX_BD_FTYPE(queue); + + if (skb->ip_summed == CHECKSUM_PARTIAL) + estatus |= BD_ENET_TX_PINS | BD_ENET_TX_IINS; + + ebdp->cbd_bdu = 0; +- ebdp->cbd_esc = cpu_to_fec32(estatus); ++ ebdp->cbd_esc = estatus; + } + +- index = fec_enet_get_bd_index(last_bdp, &txq->bd); ++ index = fec_enet_get_bd_index(txq->tx_bd_base, last_bdp, fep); + /* Save skb pointer */ + txq->tx_skbuff[index] = skb; + +- /* Make sure the updates to rest of the descriptor are performed before +- * transferring ownership. +- */ +- wmb(); ++ bdp->cbd_datlen = buflen; ++ bdp->cbd_bufaddr = addr; + + /* Send it on its way. Tell FEC it's ready, interrupt when done, + * it's the last BD of the frame, and to put the CRC on the end. + */ + status |= (BD_ENET_TX_READY | BD_ENET_TX_TC); +- bdp->cbd_sc = cpu_to_fec16(status); ++ bdp->cbd_sc = status; + + /* If this was the last BD in the ring, start at the beginning again. */ +- bdp = fec_enet_get_nextdesc(last_bdp, &txq->bd); ++ bdp = fec_enet_get_nextdesc(last_bdp, fep, queue); + + skb_tx_timestamp(skb); + + /* Make sure the update to bdp and tx_skbuff are performed before +- * txq->bd.cur. ++ * cur_tx. + */ + wmb(); +- txq->bd.cur = bdp; ++ txq->cur_tx = bdp; + + /* Trigger transmission start */ +- writel(0, txq->bd.reg_desc_active); ++ writel(0, fep->hwp + FEC_X_DES_ACTIVE(queue)); + + return 0; + } +@@ -569,11 +590,12 @@ fec_enet_txq_put_data_tso(struct fec_enet_priv_tx_q *txq, struct sk_buff *skb, + { + struct fec_enet_private *fep = netdev_priv(ndev); + struct bufdesc_ex *ebdp = container_of(bdp, struct bufdesc_ex, desc); ++ unsigned short queue = skb_get_queue_mapping(skb); + unsigned short status; + unsigned int estatus = 0; + dma_addr_t addr; + +- status = fec16_to_cpu(bdp->cbd_sc); ++ status = bdp->cbd_sc; + status &= ~BD_ENET_TX_STATS; + + status |= (BD_ENET_TX_TC | BD_ENET_TX_READY); +@@ -595,16 +617,16 @@ fec_enet_txq_put_data_tso(struct fec_enet_priv_tx_q *txq, struct sk_buff *skb, + return NETDEV_TX_BUSY; + } + +- bdp->cbd_datlen = cpu_to_fec16(size); +- bdp->cbd_bufaddr = cpu_to_fec32(addr); ++ bdp->cbd_datlen = size; ++ bdp->cbd_bufaddr = addr; + + if (fep->bufdesc_ex) { + if (fep->quirks & FEC_QUIRK_HAS_AVB) +- estatus |= FEC_TX_BD_FTYPE(txq->bd.qid); ++ estatus |= FEC_TX_BD_FTYPE(queue); + if (skb->ip_summed == CHECKSUM_PARTIAL) + estatus |= BD_ENET_TX_PINS | BD_ENET_TX_IINS; + ebdp->cbd_bdu = 0; +- ebdp->cbd_esc = cpu_to_fec32(estatus); ++ ebdp->cbd_esc = estatus; + } + + /* Handle the last BD specially */ +@@ -613,10 +635,10 @@ fec_enet_txq_put_data_tso(struct fec_enet_priv_tx_q *txq, struct sk_buff *skb, + if (is_last) { + status |= BD_ENET_TX_INTR; + if (fep->bufdesc_ex) +- ebdp->cbd_esc |= cpu_to_fec32(BD_ENET_TX_INT); ++ ebdp->cbd_esc |= BD_ENET_TX_INT; + } + +- bdp->cbd_sc = cpu_to_fec16(status); ++ bdp->cbd_sc = status; + + return 0; + } +@@ -629,12 +651,13 @@ fec_enet_txq_put_hdr_tso(struct fec_enet_priv_tx_q *txq, + struct fec_enet_private *fep = netdev_priv(ndev); + int hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb); + struct bufdesc_ex *ebdp = container_of(bdp, struct bufdesc_ex, desc); ++ unsigned short queue = skb_get_queue_mapping(skb); + void *bufaddr; + unsigned long dmabuf; + unsigned short status; + unsigned int estatus = 0; + +- status = fec16_to_cpu(bdp->cbd_sc); ++ status = bdp->cbd_sc; + status &= ~BD_ENET_TX_STATS; + status |= (BD_ENET_TX_TC | BD_ENET_TX_READY); + +@@ -658,19 +681,19 @@ fec_enet_txq_put_hdr_tso(struct fec_enet_priv_tx_q *txq, + } + } + +- bdp->cbd_bufaddr = cpu_to_fec32(dmabuf); +- bdp->cbd_datlen = cpu_to_fec16(hdr_len); ++ bdp->cbd_bufaddr = dmabuf; ++ bdp->cbd_datlen = hdr_len; + + if (fep->bufdesc_ex) { + if (fep->quirks & FEC_QUIRK_HAS_AVB) +- estatus |= FEC_TX_BD_FTYPE(txq->bd.qid); ++ estatus |= FEC_TX_BD_FTYPE(queue); + if (skb->ip_summed == CHECKSUM_PARTIAL) + estatus |= BD_ENET_TX_PINS | BD_ENET_TX_IINS; + ebdp->cbd_bdu = 0; +- ebdp->cbd_esc = cpu_to_fec32(estatus); ++ ebdp->cbd_esc = estatus; + } + +- bdp->cbd_sc = cpu_to_fec16(status); ++ bdp->cbd_sc = status; + + return 0; + } +@@ -682,12 +705,13 @@ static int fec_enet_txq_submit_tso(struct fec_enet_priv_tx_q *txq, + struct fec_enet_private *fep = netdev_priv(ndev); + int hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb); + int total_len, data_left; +- struct bufdesc *bdp = txq->bd.cur; ++ struct bufdesc *bdp = txq->cur_tx; ++ unsigned short queue = skb_get_queue_mapping(skb); + struct tso_t tso; + unsigned int index = 0; + int ret; + +- if (tso_count_descs(skb) >= fec_enet_get_free_txdesc_num(txq)) { ++ if (tso_count_descs(skb) >= fec_enet_get_free_txdesc_num(fep, txq)) { + dev_kfree_skb_any(skb); + if (net_ratelimit()) + netdev_err(ndev, "NOT enough BD for TSO!\n"); +@@ -707,7 +731,7 @@ static int fec_enet_txq_submit_tso(struct fec_enet_priv_tx_q *txq, + while (total_len > 0) { + char *hdr; + +- index = fec_enet_get_bd_index(bdp, &txq->bd); ++ index = fec_enet_get_bd_index(txq->tx_bd_base, bdp, fep); + data_left = min_t(int, skb_shinfo(skb)->gso_size, total_len); + total_len -= data_left; + +@@ -722,8 +746,9 @@ static int fec_enet_txq_submit_tso(struct fec_enet_priv_tx_q *txq, + int size; + + size = min_t(int, tso.size, data_left); +- bdp = fec_enet_get_nextdesc(bdp, &txq->bd); +- index = fec_enet_get_bd_index(bdp, &txq->bd); ++ bdp = fec_enet_get_nextdesc(bdp, fep, queue); ++ index = fec_enet_get_bd_index(txq->tx_bd_base, ++ bdp, fep); + ret = fec_enet_txq_put_data_tso(txq, skb, ndev, + bdp, index, + tso.data, size, +@@ -736,22 +761,22 @@ static int fec_enet_txq_submit_tso(struct fec_enet_priv_tx_q *txq, + tso_build_data(skb, &tso, size); + } + +- bdp = fec_enet_get_nextdesc(bdp, &txq->bd); ++ bdp = fec_enet_get_nextdesc(bdp, fep, queue); + } + + /* Save skb pointer */ + txq->tx_skbuff[index] = skb; + + skb_tx_timestamp(skb); +- txq->bd.cur = bdp; ++ txq->cur_tx = bdp; + + /* Trigger transmission start */ + if (!(fep->quirks & FEC_QUIRK_ERR007885) || +- !readl(txq->bd.reg_desc_active) || +- !readl(txq->bd.reg_desc_active) || +- !readl(txq->bd.reg_desc_active) || +- !readl(txq->bd.reg_desc_active)) +- writel(0, txq->bd.reg_desc_active); ++ !readl(fep->hwp + FEC_X_DES_ACTIVE(queue)) || ++ !readl(fep->hwp + FEC_X_DES_ACTIVE(queue)) || ++ !readl(fep->hwp + FEC_X_DES_ACTIVE(queue)) || ++ !readl(fep->hwp + FEC_X_DES_ACTIVE(queue))) ++ writel(0, fep->hwp + FEC_X_DES_ACTIVE(queue)); + + return 0; + +@@ -781,7 +806,7 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *ndev) + if (ret) + return ret; + +- entries_free = fec_enet_get_free_txdesc_num(txq); ++ entries_free = fec_enet_get_free_txdesc_num(fep, txq); + if (entries_free <= txq->tx_stop_threshold) + netif_tx_stop_queue(nq); + +@@ -802,45 +827,45 @@ static void fec_enet_bd_init(struct net_device *dev) + for (q = 0; q < fep->num_rx_queues; q++) { + /* Initialize the receive buffer descriptors. */ + rxq = fep->rx_queue[q]; +- bdp = rxq->bd.base; ++ bdp = rxq->rx_bd_base; + +- for (i = 0; i < rxq->bd.ring_size; i++) { ++ for (i = 0; i < rxq->rx_ring_size; i++) { + + /* Initialize the BD for every fragment in the page. */ + if (bdp->cbd_bufaddr) +- bdp->cbd_sc = cpu_to_fec16(BD_ENET_RX_EMPTY); ++ bdp->cbd_sc = BD_ENET_RX_EMPTY; + else +- bdp->cbd_sc = cpu_to_fec16(0); +- bdp = fec_enet_get_nextdesc(bdp, &rxq->bd); ++ bdp->cbd_sc = 0; ++ bdp = fec_enet_get_nextdesc(bdp, fep, q); + } + + /* Set the last buffer to wrap */ +- bdp = fec_enet_get_prevdesc(bdp, &rxq->bd); +- bdp->cbd_sc |= cpu_to_fec16(BD_SC_WRAP); ++ bdp = fec_enet_get_prevdesc(bdp, fep, q); ++ bdp->cbd_sc |= BD_SC_WRAP; + +- rxq->bd.cur = rxq->bd.base; ++ rxq->cur_rx = rxq->rx_bd_base; + } + + for (q = 0; q < fep->num_tx_queues; q++) { + /* ...and the same for transmit */ + txq = fep->tx_queue[q]; +- bdp = txq->bd.base; +- txq->bd.cur = bdp; ++ bdp = txq->tx_bd_base; ++ txq->cur_tx = bdp; + +- for (i = 0; i < txq->bd.ring_size; i++) { ++ for (i = 0; i < txq->tx_ring_size; i++) { + /* Initialize the BD for every fragment in the page. */ +- bdp->cbd_sc = cpu_to_fec16(0); ++ bdp->cbd_sc = 0; + if (txq->tx_skbuff[i]) { + dev_kfree_skb_any(txq->tx_skbuff[i]); + txq->tx_skbuff[i] = NULL; + } +- bdp->cbd_bufaddr = cpu_to_fec32(0); +- bdp = fec_enet_get_nextdesc(bdp, &txq->bd); ++ bdp->cbd_bufaddr = 0; ++ bdp = fec_enet_get_nextdesc(bdp, fep, q); + } + + /* Set the last buffer to wrap */ +- bdp = fec_enet_get_prevdesc(bdp, &txq->bd); +- bdp->cbd_sc |= cpu_to_fec16(BD_SC_WRAP); ++ bdp = fec_enet_get_prevdesc(bdp, fep, q); ++ bdp->cbd_sc |= BD_SC_WRAP; + txq->dirty_tx = bdp; + } + } +@@ -851,7 +876,7 @@ static void fec_enet_active_rxring(struct net_device *ndev) + int i; + + for (i = 0; i < fep->num_rx_queues; i++) +- writel(0, fep->rx_queue[i]->bd.reg_desc_active); ++ writel(0, fep->hwp + FEC_R_DES_ACTIVE(i)); + } + + static void fec_enet_enable_ring(struct net_device *ndev) +@@ -863,7 +888,7 @@ static void fec_enet_enable_ring(struct net_device *ndev) + + for (i = 0; i < fep->num_rx_queues; i++) { + rxq = fep->rx_queue[i]; +- writel(rxq->bd.dma, fep->hwp + FEC_R_DES_START(i)); ++ writel(rxq->bd_dma, fep->hwp + FEC_R_DES_START(i)); + writel(PKT_MAXBLR_SIZE, fep->hwp + FEC_R_BUFF_SIZE(i)); + + /* enable DMA1/2 */ +@@ -874,7 +899,7 @@ static void fec_enet_enable_ring(struct net_device *ndev) + + for (i = 0; i < fep->num_tx_queues; i++) { + txq = fep->tx_queue[i]; +- writel(txq->bd.dma, fep->hwp + FEC_X_DES_START(i)); ++ writel(txq->bd_dma, fep->hwp + FEC_X_DES_START(i)); + + /* enable DMA1/2 */ + if (i) +@@ -892,7 +917,7 @@ static void fec_enet_reset_skb(struct net_device *ndev) + for (i = 0; i < fep->num_tx_queues; i++) { + txq = fep->tx_queue[i]; + +- for (j = 0; j < txq->bd.ring_size; j++) { ++ for (j = 0; j < txq->tx_ring_size; j++) { + if (txq->tx_skbuff[j]) { + dev_kfree_skb_any(txq->tx_skbuff[j]); + txq->tx_skbuff[j] = NULL; +@@ -930,11 +955,11 @@ fec_restart(struct net_device *ndev) + * enet-mac reset will reset mac address registers too, + * so need to reconfigure it. + */ +- memcpy(&temp_mac, ndev->dev_addr, ETH_ALEN); +- writel((__force u32)cpu_to_be32(temp_mac[0]), +- fep->hwp + FEC_ADDR_LOW); +- writel((__force u32)cpu_to_be32(temp_mac[1]), +- fep->hwp + FEC_ADDR_HIGH); ++ if (fep->quirks & FEC_QUIRK_ENET_MAC) { ++ memcpy(&temp_mac, ndev->dev_addr, ETH_ALEN); ++ writel(cpu_to_be32(temp_mac[0]), fep->hwp + FEC_ADDR_LOW); ++ writel(cpu_to_be32(temp_mac[1]), fep->hwp + FEC_ADDR_HIGH); ++ } + + /* Clear any outstanding interrupt. */ + writel(0xffffffff, fep->hwp + FEC_IEVENT); +@@ -961,16 +986,13 @@ fec_restart(struct net_device *ndev) + + #if !defined(CONFIG_M5272) + if (fep->quirks & FEC_QUIRK_HAS_RACC) { ++ /* set RX checksum */ + val = readl(fep->hwp + FEC_RACC); +- /* align IP header */ +- val |= FEC_RACC_SHIFT16; + if (fep->csum_flags & FLAG_RX_CSUM_ENABLED) +- /* set RX checksum */ + val |= FEC_RACC_OPTIONS; + else + val &= ~FEC_RACC_OPTIONS; + writel(val, fep->hwp + FEC_RACC); +- writel(PKT_MAXBUF_SIZE, fep->hwp + FEC_FTRL); + } + writel(PKT_MAXBUF_SIZE, fep->hwp + FEC_FTRL); + #endif +@@ -995,10 +1017,10 @@ fec_restart(struct net_device *ndev) + rcntl &= ~(1 << 8); + + /* 1G, 100M or 10M */ +- if (ndev->phydev) { +- if (ndev->phydev->speed == SPEED_1000) ++ if (fep->phy_dev) { ++ if (fep->phy_dev->speed == SPEED_1000) + ecntl |= (1 << 5); +- else if (ndev->phydev->speed == SPEED_100) ++ else if (fep->phy_dev->speed == SPEED_100) + rcntl &= ~(1 << 9); + else + rcntl |= (1 << 9); +@@ -1019,7 +1041,7 @@ fec_restart(struct net_device *ndev) + */ + cfgr = (fep->phy_interface == PHY_INTERFACE_MODE_RMII) + ? BM_MIIGSK_CFGR_RMII : BM_MIIGSK_CFGR_MII; +- if (ndev->phydev && ndev->phydev->speed == SPEED_10) ++ if (fep->phy_dev && fep->phy_dev->speed == SPEED_10) + cfgr |= BM_MIIGSK_CFGR_FRCONT_10M; + writel(cfgr, fep->hwp + FEC_MIIGSK_CFGR); + +@@ -1033,7 +1055,7 @@ fec_restart(struct net_device *ndev) + /* enable pause frame*/ + if ((fep->pause_flag & FEC_PAUSE_FLAG_ENABLE) || + ((fep->pause_flag & FEC_PAUSE_FLAG_AUTONEG) && +- ndev->phydev && ndev->phydev->pause)) { ++ fep->phy_dev && fep->phy_dev->pause)) { + rcntl |= FEC_ENET_FCE; + + /* set FIFO threshold parameter to reduce overrun */ +@@ -1213,12 +1235,13 @@ static void + fec_enet_tx_queue(struct net_device *ndev, u16 queue_id) + { + struct fec_enet_private *fep; +- struct bufdesc *bdp; ++ struct bufdesc *bdp, *bdp_t; + unsigned short status; + struct sk_buff *skb; + struct fec_enet_priv_tx_q *txq; + struct netdev_queue *nq; + int index = 0; ++ int i, bdnum; + int entries_free; + + fep = netdev_priv(ndev); +@@ -1231,27 +1254,37 @@ fec_enet_tx_queue(struct net_device *ndev, u16 queue_id) + bdp = txq->dirty_tx; + + /* get next bdp of dirty_tx */ +- bdp = fec_enet_get_nextdesc(bdp, &txq->bd); ++ bdp = fec_enet_get_nextdesc(bdp, fep, queue_id); + +- while (bdp != READ_ONCE(txq->bd.cur)) { +- /* Order the load of bd.cur and cbd_sc */ ++ while (bdp != READ_ONCE(txq->cur_tx)) { ++ /* Order the load of cur_tx and cbd_sc */ + rmb(); +- status = fec16_to_cpu(READ_ONCE(bdp->cbd_sc)); ++ status = READ_ONCE(bdp->cbd_sc); + if (status & BD_ENET_TX_READY) + break; + +- index = fec_enet_get_bd_index(bdp, &txq->bd); +- ++ bdp_t = bdp; ++ bdnum = 1; ++ index = fec_enet_get_bd_index(txq->tx_bd_base, bdp_t, fep); + skb = txq->tx_skbuff[index]; ++ while (!skb) { ++ bdp_t = fec_enet_get_nextdesc(bdp_t, fep, queue_id); ++ index = fec_enet_get_bd_index(txq->tx_bd_base, bdp_t, fep); ++ skb = txq->tx_skbuff[index]; ++ bdnum++; ++ } ++ if ((status = bdp_t->cbd_sc) & BD_ENET_TX_READY) ++ break; ++ ++ for (i = 0; i < bdnum; i++) { ++ if (!IS_TSO_HEADER(txq, bdp->cbd_bufaddr)) ++ dma_unmap_single(&fep->pdev->dev, bdp->cbd_bufaddr, ++ bdp->cbd_datlen, DMA_TO_DEVICE); ++ bdp->cbd_bufaddr = 0; ++ if (i < bdnum - 1) ++ bdp = fec_enet_get_nextdesc(bdp, fep, queue_id); ++ } + txq->tx_skbuff[index] = NULL; +- if (!IS_TSO_HEADER(txq, fec32_to_cpu(bdp->cbd_bufaddr))) +- dma_unmap_single(&fep->pdev->dev, +- fec32_to_cpu(bdp->cbd_bufaddr), +- fec16_to_cpu(bdp->cbd_datlen), +- DMA_TO_DEVICE); +- bdp->cbd_bufaddr = cpu_to_fec32(0); +- if (!skb) +- goto skb_done; + + /* Check for errors. */ + if (status & (BD_ENET_TX_HB | BD_ENET_TX_LC | +@@ -1278,7 +1311,7 @@ fec_enet_tx_queue(struct net_device *ndev, u16 queue_id) + struct skb_shared_hwtstamps shhwtstamps; + struct bufdesc_ex *ebdp = (struct bufdesc_ex *)bdp; + +- fec_enet_hwtstamp(fep, fec32_to_cpu(ebdp->ts), &shhwtstamps); ++ fec_enet_hwtstamp(fep, ebdp->ts, &shhwtstamps); + skb_tstamp_tx(skb, &shhwtstamps); + } + +@@ -1290,7 +1323,7 @@ fec_enet_tx_queue(struct net_device *ndev, u16 queue_id) + + /* Free the sk buffer associated with this last transmit */ + dev_kfree_skb_any(skb); +-skb_done: ++ + /* Make sure the update to bdp and tx_skbuff are performed + * before dirty_tx + */ +@@ -1298,21 +1331,21 @@ fec_enet_tx_queue(struct net_device *ndev, u16 queue_id) + txq->dirty_tx = bdp; + + /* Update pointer to next buffer descriptor to be transmitted */ +- bdp = fec_enet_get_nextdesc(bdp, &txq->bd); ++ bdp = fec_enet_get_nextdesc(bdp, fep, queue_id); + + /* Since we have freed up a buffer, the ring is no longer full + */ + if (netif_queue_stopped(ndev)) { +- entries_free = fec_enet_get_free_txdesc_num(txq); ++ entries_free = fec_enet_get_free_txdesc_num(fep, txq); + if (entries_free >= txq->tx_wake_threshold) + netif_tx_wake_queue(nq); + } + } + + /* ERR006538: Keep the transmitter going */ +- if (bdp != txq->bd.cur && +- readl(txq->bd.reg_desc_active) == 0) +- writel(0, txq->bd.reg_desc_active); ++ if (bdp != txq->cur_tx && ++ readl(fep->hwp + FEC_X_DES_ACTIVE(queue_id)) == 0) ++ writel(0, fep->hwp + FEC_X_DES_ACTIVE(queue_id)); + } + + static void +@@ -1338,8 +1371,10 @@ fec_enet_new_rxbdp(struct net_device *ndev, struct bufdesc *bdp, struct sk_buff + if (off) + skb_reserve(skb, fep->rx_align + 1 - off); + +- bdp->cbd_bufaddr = cpu_to_fec32(dma_map_single(&fep->pdev->dev, skb->data, FEC_ENET_RX_FRSIZE - fep->rx_align, DMA_FROM_DEVICE)); +- if (dma_mapping_error(&fep->pdev->dev, fec32_to_cpu(bdp->cbd_bufaddr))) { ++ bdp->cbd_bufaddr = dma_map_single(&fep->pdev->dev, skb->data, ++ FEC_ENET_RX_FRSIZE - fep->rx_align, ++ DMA_FROM_DEVICE); ++ if (dma_mapping_error(&fep->pdev->dev, bdp->cbd_bufaddr)) { + if (net_ratelimit()) + netdev_err(ndev, "Rx DMA memory map failed\n"); + return -ENOMEM; +@@ -1361,8 +1396,7 @@ static bool fec_enet_copybreak(struct net_device *ndev, struct sk_buff **skb, + if (!new_skb) + return false; + +- dma_sync_single_for_cpu(&fep->pdev->dev, +- fec32_to_cpu(bdp->cbd_bufaddr), ++ dma_sync_single_for_cpu(&fep->pdev->dev, bdp->cbd_bufaddr, + FEC_ENET_RX_FRSIZE - fep->rx_align, + DMA_FROM_DEVICE); + if (!swap) +@@ -1374,7 +1408,7 @@ static bool fec_enet_copybreak(struct net_device *ndev, struct sk_buff **skb, + return true; + } + +-/* During a receive, the bd_rx.cur points to the current incoming buffer. ++/* During a receive, the cur_rx points to the current incoming buffer. + * When we update through the ring, if the next incoming buffer has + * not been given to the system, we just set the empty indicator, + * effectively tossing the packet. +@@ -1407,9 +1441,9 @@ fec_enet_rx_queue(struct net_device *ndev, int budget, u16 queue_id) + /* First, grab all of the stats for the incoming packet. + * These get messed up if we get called due to a busy condition. + */ +- bdp = rxq->bd.cur; ++ bdp = rxq->cur_rx; + +- while (!((status = fec16_to_cpu(bdp->cbd_sc)) & BD_ENET_RX_EMPTY)) { ++ while (!((status = bdp->cbd_sc) & BD_ENET_RX_EMPTY)) { + + if (pkt_received >= budget) + break; +@@ -1445,10 +1479,10 @@ fec_enet_rx_queue(struct net_device *ndev, int budget, u16 queue_id) + + /* Process the incoming frame. */ + ndev->stats.rx_packets++; +- pkt_len = fec16_to_cpu(bdp->cbd_datlen); ++ pkt_len = bdp->cbd_datlen; + ndev->stats.rx_bytes += pkt_len; + +- index = fec_enet_get_bd_index(bdp, &rxq->bd); ++ index = fec_enet_get_bd_index(rxq->rx_bd_base, bdp, fep); + skb = rxq->rx_skbuff[index]; + + /* The packet length includes FCS, but we don't want to +@@ -1463,8 +1497,7 @@ fec_enet_rx_queue(struct net_device *ndev, int budget, u16 queue_id) + ndev->stats.rx_dropped++; + goto rx_processing_done; + } +- dma_unmap_single(&fep->pdev->dev, +- fec32_to_cpu(bdp->cbd_bufaddr), ++ dma_unmap_single(&fep->pdev->dev, bdp->cbd_bufaddr, + FEC_ENET_RX_FRSIZE - fep->rx_align, + DMA_FROM_DEVICE); + } +@@ -1472,15 +1505,9 @@ fec_enet_rx_queue(struct net_device *ndev, int budget, u16 queue_id) + prefetch(skb->data - NET_IP_ALIGN); + skb_put(skb, pkt_len - 4); + data = skb->data; +- + if (!is_copybreak && need_swap) + swap_buffer(data, pkt_len); + +-#if !defined(CONFIG_M5272) +- if (fep->quirks & FEC_QUIRK_HAS_RACC) +- data = skb_pull_inline(skb, 2); +-#endif +- + /* Extract the enhanced buffer descriptor */ + ebdp = NULL; + if (fep->bufdesc_ex) +@@ -1489,8 +1516,7 @@ fec_enet_rx_queue(struct net_device *ndev, int budget, u16 queue_id) + /* If this is a VLAN packet remove the VLAN Tag */ + vlan_packet_rcvd = false; + if ((ndev->features & NETIF_F_HW_VLAN_CTAG_RX) && +- fep->bufdesc_ex && +- (ebdp->cbd_esc & cpu_to_fec32(BD_ENET_RX_VLAN))) { ++ fep->bufdesc_ex && (ebdp->cbd_esc & BD_ENET_RX_VLAN)) { + /* Push and remove the vlan tag */ + struct vlan_hdr *vlan_header = + (struct vlan_hdr *) (data + ETH_HLEN); +@@ -1506,12 +1532,12 @@ fec_enet_rx_queue(struct net_device *ndev, int budget, u16 queue_id) + + /* Get receive timestamp from the skb */ + if (fep->hwts_rx_en && fep->bufdesc_ex) +- fec_enet_hwtstamp(fep, fec32_to_cpu(ebdp->ts), ++ fec_enet_hwtstamp(fep, ebdp->ts, + skb_hwtstamps(skb)); + + if (fep->bufdesc_ex && + (fep->csum_flags & FLAG_RX_CSUM_ENABLED)) { +- if (!(ebdp->cbd_esc & cpu_to_fec32(FLAG_RX_CSUM_ERROR))) { ++ if (!(ebdp->cbd_esc & FLAG_RX_CSUM_ERROR)) { + /* don't check it */ + skb->ip_summed = CHECKSUM_UNNECESSARY; + } else { +@@ -1528,8 +1554,7 @@ fec_enet_rx_queue(struct net_device *ndev, int budget, u16 queue_id) + napi_gro_receive(&fep->napi, skb); + + if (is_copybreak) { +- dma_sync_single_for_device(&fep->pdev->dev, +- fec32_to_cpu(bdp->cbd_bufaddr), ++ dma_sync_single_for_device(&fep->pdev->dev, bdp->cbd_bufaddr, + FEC_ENET_RX_FRSIZE - fep->rx_align, + DMA_FROM_DEVICE); + } else { +@@ -1543,30 +1568,26 @@ fec_enet_rx_queue(struct net_device *ndev, int budget, u16 queue_id) + + /* Mark the buffer empty */ + status |= BD_ENET_RX_EMPTY; ++ bdp->cbd_sc = status; + + if (fep->bufdesc_ex) { + struct bufdesc_ex *ebdp = (struct bufdesc_ex *)bdp; + +- ebdp->cbd_esc = cpu_to_fec32(BD_ENET_RX_INT); ++ ebdp->cbd_esc = BD_ENET_RX_INT; + ebdp->cbd_prot = 0; + ebdp->cbd_bdu = 0; + } +- /* Make sure the updates to rest of the descriptor are +- * performed before transferring ownership. +- */ +- wmb(); +- bdp->cbd_sc = cpu_to_fec16(status); + + /* Update BD pointer to next entry */ +- bdp = fec_enet_get_nextdesc(bdp, &rxq->bd); ++ bdp = fec_enet_get_nextdesc(bdp, fep, queue_id); + + /* Doing this here will keep the FEC running while we process + * incoming frames. On a heavily loaded network, we should be + * able to keep up at the expense of system resources. + */ +- writel(0, rxq->bd.reg_desc_active); ++ writel(0, fep->hwp + FEC_R_DES_ACTIVE(queue_id)); + } +- rxq->bd.cur = bdp; ++ rxq->cur_rx = bdp; + return pkt_received; + } + +@@ -1578,15 +1599,9 @@ fec_enet_rx(struct net_device *ndev, int budget) + struct fec_enet_private *fep = netdev_priv(ndev); + + for_each_set_bit(queue_id, &fep->work_rx, FEC_ENET_MAX_RX_QS) { +- int ret; +- +- ret = fec_enet_rx_queue(ndev, ++ clear_bit(queue_id, &fep->work_rx); ++ pkt_received += fec_enet_rx_queue(ndev, + budget - pkt_received, queue_id); +- +- if (ret < budget - pkt_received) +- clear_bit(queue_id, &fep->work_rx); +- +- pkt_received += ret; + } + return pkt_received; + } +@@ -1631,7 +1646,7 @@ fec_enet_interrupt(int irq, void *dev_id) + + if (napi_schedule_prep(&fep->napi)) { + /* Disable the NAPI interrupts */ +- writel(FEC_NAPI_IMASK, fep->hwp + FEC_IMASK); ++ writel(FEC_ENET_MII, fep->hwp + FEC_IMASK); + __napi_schedule(&fep->napi); + } + } +@@ -1742,7 +1757,7 @@ static void fec_get_mac(struct net_device *ndev) + static void fec_enet_adjust_link(struct net_device *ndev) + { + struct fec_enet_private *fep = netdev_priv(ndev); +- struct phy_device *phy_dev = ndev->phydev; ++ struct phy_device *phy_dev = fep->phy_dev; + int status_change = 0; + + /* Prevent a state halted on mii error */ +@@ -1802,16 +1817,10 @@ static void fec_enet_adjust_link(struct net_device *ndev) + static int fec_enet_mdio_read(struct mii_bus *bus, int mii_id, int regnum) + { + struct fec_enet_private *fep = bus->priv; +- struct device *dev = &fep->pdev->dev; + unsigned long time_left; +- int ret = 0; +- +- ret = pm_runtime_get_sync(dev); +- if (ret < 0) +- return ret; + + fep->mii_timeout = 0; +- reinit_completion(&fep->mdio_done); ++ init_completion(&fep->mdio_done); + + /* start a read op */ + writel(FEC_MMFR_ST | FEC_MMFR_OP_READ | +@@ -1824,35 +1833,21 @@ static int fec_enet_mdio_read(struct mii_bus *bus, int mii_id, int regnum) + if (time_left == 0) { + fep->mii_timeout = 1; + netdev_err(fep->netdev, "MDIO read timeout\n"); +- ret = -ETIMEDOUT; +- goto out; ++ return -ETIMEDOUT; + } + +- ret = FEC_MMFR_DATA(readl(fep->hwp + FEC_MII_DATA)); +- +-out: +- pm_runtime_mark_last_busy(dev); +- pm_runtime_put_autosuspend(dev); +- +- return ret; ++ /* return value */ ++ return FEC_MMFR_DATA(readl(fep->hwp + FEC_MII_DATA)); + } + + static int fec_enet_mdio_write(struct mii_bus *bus, int mii_id, int regnum, + u16 value) + { + struct fec_enet_private *fep = bus->priv; +- struct device *dev = &fep->pdev->dev; + unsigned long time_left; +- int ret; +- +- ret = pm_runtime_get_sync(dev); +- if (ret < 0) +- return ret; +- else +- ret = 0; + + fep->mii_timeout = 0; +- reinit_completion(&fep->mdio_done); ++ init_completion(&fep->mdio_done); + + /* start a write op */ + writel(FEC_MMFR_ST | FEC_MMFR_OP_WRITE | +@@ -1866,13 +1861,10 @@ static int fec_enet_mdio_write(struct mii_bus *bus, int mii_id, int regnum, + if (time_left == 0) { + fep->mii_timeout = 1; + netdev_err(fep->netdev, "MDIO write timeout\n"); +- ret = -ETIMEDOUT; ++ return -ETIMEDOUT; + } + +- pm_runtime_mark_last_busy(dev); +- pm_runtime_put_autosuspend(dev); +- +- return ret; ++ return 0; + } + + static int fec_enet_clk_enable(struct net_device *ndev, bool enable) +@@ -1881,10 +1873,18 @@ static int fec_enet_clk_enable(struct net_device *ndev, bool enable) + int ret; + + if (enable) { ++ ret = clk_prepare_enable(fep->clk_ahb); ++ if (ret) ++ return ret; ++ ret = clk_prepare_enable(fep->clk_ipg); ++ if (ret) ++ goto failed_clk_ipg; + if (fep->clk_enet_out) { + ret = clk_prepare_enable(fep->clk_enet_out); + if (ret) +- return ret; ++ goto failed_clk_enet_out; ++ ++ fec_reset_phy(fep->pdev); + } + if (fep->clk_ptp) { + mutex_lock(&fep->ptp_clk_mutex); +@@ -1903,6 +1903,8 @@ static int fec_enet_clk_enable(struct net_device *ndev, bool enable) + goto failed_clk_ref; + } + } else { ++ clk_disable_unprepare(fep->clk_ahb); ++ clk_disable_unprepare(fep->clk_ipg); + if (fep->clk_enet_out) + clk_disable_unprepare(fep->clk_enet_out); + if (fep->clk_ptp) { +@@ -1923,27 +1925,23 @@ static int fec_enet_clk_enable(struct net_device *ndev, bool enable) + failed_clk_ptp: + if (fep->clk_enet_out) + clk_disable_unprepare(fep->clk_enet_out); ++failed_clk_enet_out: ++ clk_disable_unprepare(fep->clk_ipg); ++failed_clk_ipg: ++ clk_disable_unprepare(fep->clk_ahb); + + return ret; + } + +-static int fec_restore_mii_bus(struct net_device *ndev) ++static void fec_restore_mii_bus(struct net_device *ndev) + { + struct fec_enet_private *fep = netdev_priv(ndev); +- int ret; +- +- ret = pm_runtime_get_sync(&fep->pdev->dev); +- if (ret < 0) +- return ret; + ++ fec_enet_clk_enable(ndev, true); + writel(0xffc00000, fep->hwp + FEC_IEVENT); + writel(fep->phy_speed, fep->hwp + FEC_MII_SPEED); + writel(FEC_ENET_MII, fep->hwp + FEC_IMASK); + writel(FEC_ENET_ETHEREN, fep->hwp + FEC_ECNTRL); +- +- pm_runtime_mark_last_busy(&fep->pdev->dev); +- pm_runtime_put_autosuspend(&fep->pdev->dev); +- return 0; + } + + static int fec_enet_mii_probe(struct net_device *ndev) +@@ -1955,6 +1953,8 @@ static int fec_enet_mii_probe(struct net_device *ndev) + int phy_id; + int dev_id = fep->dev_id; + ++ fep->phy_dev = NULL; ++ + if (fep->phy_node) { + phy_dev = of_phy_connect(ndev, fep->phy_node, + &fec_enet_adjust_link, 0, +@@ -1964,7 +1964,11 @@ static int fec_enet_mii_probe(struct net_device *ndev) + } else { + /* check for attached phy */ + for (phy_id = 0; (phy_id < PHY_MAX_ADDR); phy_id++) { +- if (!mdiobus_is_registered_device(fep->mii_bus, phy_id)) ++ if ((fep->mii_bus->phy_mask & (1 << phy_id))) ++ continue; ++ if (fep->mii_bus->mdio_map[phy_id] == NULL) ++ continue; ++ if (fep->mii_bus->mdio_map[phy_id]->addr == 0) + continue; + if (dev_id--) + continue; +@@ -2002,10 +2006,13 @@ static int fec_enet_mii_probe(struct net_device *ndev) + + phy_dev->advertising = phy_dev->supported; + ++ fep->phy_dev = phy_dev; + fep->link = 0; + fep->full_duplex = 0; + +- phy_attached_info(phy_dev); ++ netdev_info(ndev, "Freescale FEC PHY driver [%s] (mii_bus:phy_addr=%s, irq=%d)\n", ++ fep->phy_dev->drv->name, NULL, ++ fep->phy_dev->irq); + + return 0; + } +@@ -2017,7 +2024,7 @@ static int fec_enet_mii_init(struct platform_device *pdev) + struct net_device *ndev = platform_get_drvdata(pdev); + struct fec_enet_private *fep = netdev_priv(ndev); + struct device_node *node; +- int err = -ENXIO; ++ int err = -ENXIO, i; + u32 mii_speed, holdtime; + + /* +@@ -2036,7 +2043,7 @@ static int fec_enet_mii_init(struct platform_device *pdev) + * mdio interface in board design, and need to be configured by + * fec0 mii_bus. + */ +- if ((fep->quirks & FEC_QUIRK_SINGLE_MDIO) && fep->dev_id > 0) { ++ if ((fep->quirks & FEC_QUIRK_ENET_MAC) && fep->dev_id > 0) { + /* fec1 uses fec0 mii_bus */ + if (mii_cnt && fec0_mii_bus) { + fep->mii_bus = fec0_mii_bus; +@@ -2100,29 +2107,38 @@ static int fec_enet_mii_init(struct platform_device *pdev) + fep->mii_bus->priv = fep; + fep->mii_bus->parent = &pdev->dev; + ++/* fep->mii_bus->irq = kmalloc(sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL); ++ if (!fep->mii_bus->irq) { ++ err = -ENOMEM; ++ goto err_out_free_mdiobus; ++ } ++*/ ++ for (i = 0; i < PHY_MAX_ADDR; i++) ++ fep->mii_bus->irq[i] = PHY_POLL; ++ + node = of_get_child_by_name(pdev->dev.of_node, "mdio"); + if (node) { + err = of_mdiobus_register(fep->mii_bus, node); + of_node_put(node); +- } else if (fep->phy_node && !fep->fixed_link) { +- err = -EPROBE_DEFER; + } else { + err = mdiobus_register(fep->mii_bus); + } + + if (err) +- goto err_out_free_mdiobus; ++ goto err_out_free_mdio_irq; + + mii_cnt++; + + /* save fec0 mii_bus */ +- if (fep->quirks & FEC_QUIRK_SINGLE_MDIO) { ++ if (fep->quirks & FEC_QUIRK_ENET_MAC) { + fec0_mii_bus = fep->mii_bus; + fec_mii_bus_share = &fep->mii_bus_share; + } + + return 0; + ++err_out_free_mdio_irq: ++ kfree(fep->mii_bus->irq); + err_out_free_mdiobus: + mdiobus_free(fep->mii_bus); + err_out: +@@ -2133,10 +2149,35 @@ static void fec_enet_mii_remove(struct fec_enet_private *fep) + { + if (--mii_cnt == 0) { + mdiobus_unregister(fep->mii_bus); ++ kfree(fep->mii_bus->irq); + mdiobus_free(fep->mii_bus); + } + } + ++static int fec_enet_get_settings(struct net_device *ndev, ++ struct ethtool_cmd *cmd) ++{ ++ struct fec_enet_private *fep = netdev_priv(ndev); ++ struct phy_device *phydev = fep->phy_dev; ++ ++ if (!phydev) ++ return -ENODEV; ++ ++ return phy_ethtool_gset(phydev, cmd); ++} ++ ++static int fec_enet_set_settings(struct net_device *ndev, ++ struct ethtool_cmd *cmd) ++{ ++ struct fec_enet_private *fep = netdev_priv(ndev); ++ struct phy_device *phydev = fep->phy_dev; ++ ++ if (!phydev) ++ return -ENODEV; ++ ++ return phy_ethtool_sset(phydev, cmd); ++} ++ + static void fec_enet_get_drvinfo(struct net_device *ndev, + struct ethtool_drvinfo *info) + { +@@ -2163,8 +2204,8 @@ static int fec_enet_get_regs_len(struct net_device *ndev) + + /* List of registers that can be safety be read to dump them with ethtool */ + #if defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x) || \ +- defined(CONFIG_M520x) || defined(CONFIG_M532x) || defined(CONFIG_ARM) || \ +- defined(CONFIG_ARM64) ++ defined(CONFIG_M520x) || defined(CONFIG_M532x) || \ ++ defined(CONFIG_ARCH_MXC) || defined(CONFIG_SOC_IMX28) + static u32 fec_enet_register_offset[] = { + FEC_IEVENT, FEC_IMASK, FEC_R_DES_ACTIVE_0, FEC_X_DES_ACTIVE_0, + FEC_ECNTRL, FEC_MII_DATA, FEC_MII_SPEED, FEC_MIB_CTRLSTAT, FEC_R_CNTRL, +@@ -2270,7 +2311,7 @@ static int fec_enet_set_pauseparam(struct net_device *ndev, + { + struct fec_enet_private *fep = netdev_priv(ndev); + +- if (!ndev->phydev) ++ if (!fep->phy_dev) + return -ENODEV; + + if (pause->tx_pause != pause->rx_pause) { +@@ -2286,17 +2327,17 @@ static int fec_enet_set_pauseparam(struct net_device *ndev, + fep->pause_flag |= pause->autoneg ? FEC_PAUSE_FLAG_AUTONEG : 0; + + if (pause->rx_pause || pause->autoneg) { +- ndev->phydev->supported |= ADVERTISED_Pause; +- ndev->phydev->advertising |= ADVERTISED_Pause; ++ fep->phy_dev->supported |= ADVERTISED_Pause; ++ fep->phy_dev->advertising |= ADVERTISED_Pause; + } else { +- ndev->phydev->supported &= ~ADVERTISED_Pause; +- ndev->phydev->advertising &= ~ADVERTISED_Pause; ++ fep->phy_dev->supported &= ~ADVERTISED_Pause; ++ fep->phy_dev->advertising &= ~ADVERTISED_Pause; + } + + if (pause->autoneg) { + if (netif_running(ndev)) + fec_stop(ndev); +- phy_start_aneg(ndev->phydev); ++ phy_start_aneg(fep->phy_dev); + } + if (netif_running(ndev)) { + napi_disable(&fep->napi); +@@ -2376,26 +2417,14 @@ static const struct fec_stat { + { "IEEE_rx_octets_ok", IEEE_R_OCTETS_OK }, + }; + +-#define FEC_STATS_SIZE (ARRAY_SIZE(fec_stats) * sizeof(u64)) +- +-static void fec_enet_update_ethtool_stats(struct net_device *dev) ++static void fec_enet_get_ethtool_stats(struct net_device *dev, ++ struct ethtool_stats *stats, u64 *data) + { + struct fec_enet_private *fep = netdev_priv(dev); + int i; + + for (i = 0; i < ARRAY_SIZE(fec_stats); i++) +- fep->ethtool_stats[i] = readl(fep->hwp + fec_stats[i].offset); +-} +- +-static void fec_enet_get_ethtool_stats(struct net_device *dev, +- struct ethtool_stats *stats, u64 *data) +-{ +- struct fec_enet_private *fep = netdev_priv(dev); +- +- if (netif_running(dev)) +- fec_enet_update_ethtool_stats(dev); +- +- memcpy(data, fep->ethtool_stats, FEC_STATS_SIZE); ++ data[i] = readl(fep->hwp + fec_stats[i].offset); + } + + static void fec_enet_get_strings(struct net_device *netdev, +@@ -2420,17 +2449,12 @@ static int fec_enet_get_sset_count(struct net_device *dev, int sset) + return -EOPNOTSUPP; + } + } +- +-#else /* !defined(CONFIG_M5272) */ +-#define FEC_STATS_SIZE 0 +-static inline void fec_enet_update_ethtool_stats(struct net_device *dev) +-{ +-} + #endif /* !defined(CONFIG_M5272) */ + + static int fec_enet_nway_reset(struct net_device *dev) + { +- struct phy_device *phydev = dev->phydev; ++ struct fec_enet_private *fep = netdev_priv(dev); ++ struct phy_device *phydev = fep->phy_dev; + + if (!phydev) + return -ENODEV; +@@ -2455,6 +2479,9 @@ static void fec_enet_itr_coal_set(struct net_device *ndev) + struct fec_enet_private *fep = netdev_priv(ndev); + int rx_itr, tx_itr; + ++ if (!(fep->quirks & FEC_QUIRK_HAS_AVB)) ++ return; ++ + /* Must be greater than zero to avoid unpredictable behavior */ + if (!fep->rx_time_itr || !fep->rx_pkts_itr || + !fep->tx_time_itr || !fep->tx_pkts_itr) +@@ -2477,12 +2504,10 @@ static void fec_enet_itr_coal_set(struct net_device *ndev) + + writel(tx_itr, fep->hwp + FEC_TXIC0); + writel(rx_itr, fep->hwp + FEC_RXIC0); +- if (fep->quirks & FEC_QUIRK_HAS_AVB) { +- writel(tx_itr, fep->hwp + FEC_TXIC1); +- writel(rx_itr, fep->hwp + FEC_RXIC1); +- writel(tx_itr, fep->hwp + FEC_TXIC2); +- writel(rx_itr, fep->hwp + FEC_RXIC2); +- } ++ writel(tx_itr, fep->hwp + FEC_TXIC1); ++ writel(rx_itr, fep->hwp + FEC_RXIC1); ++ writel(tx_itr, fep->hwp + FEC_TXIC2); ++ writel(rx_itr, fep->hwp + FEC_RXIC2); + } + + static int +@@ -2490,7 +2515,7 @@ fec_enet_get_coalesce(struct net_device *ndev, struct ethtool_coalesce *ec) + { + struct fec_enet_private *fep = netdev_priv(ndev); + +- if (!(fep->quirks & FEC_QUIRK_HAS_COALESCE)) ++ if (!(fep->quirks & FEC_QUIRK_HAS_AVB)) + return -EOPNOTSUPP; + + ec->rx_coalesce_usecs = fep->rx_time_itr; +@@ -2508,28 +2533,28 @@ fec_enet_set_coalesce(struct net_device *ndev, struct ethtool_coalesce *ec) + struct fec_enet_private *fep = netdev_priv(ndev); + unsigned int cycle; + +- if (!(fep->quirks & FEC_QUIRK_HAS_COALESCE)) ++ if (!(fep->quirks & FEC_QUIRK_HAS_AVB)) + return -EOPNOTSUPP; + + if (ec->rx_max_coalesced_frames > 255) { +- pr_err("Rx coalesced frames exceed hardware limitation\n"); ++ pr_err("Rx coalesced frames exceed hardware limiation"); + return -EINVAL; + } + + if (ec->tx_max_coalesced_frames > 255) { +- pr_err("Tx coalesced frame exceed hardware limitation\n"); ++ pr_err("Tx coalesced frame exceed hardware limiation"); + return -EINVAL; + } + + cycle = fec_enet_us_to_itr_clock(ndev, fep->rx_time_itr); + if (cycle > 0xFFFF) { +- pr_err("Rx coalesced usec exceed hardware limitation\n"); ++ pr_err("Rx coalesed usec exceeed hardware limiation"); + return -EINVAL; + } + + cycle = fec_enet_us_to_itr_clock(ndev, fep->tx_time_itr); + if (cycle > 0xFFFF) { +- pr_err("Rx coalesced usec exceed hardware limitation\n"); ++ pr_err("Rx coalesed usec exceeed hardware limiation"); + return -EINVAL; + } + +@@ -2629,6 +2654,8 @@ fec_enet_set_wol(struct net_device *ndev, struct ethtool_wolinfo *wol) + } + + static const struct ethtool_ops fec_enet_ethtool_ops = { ++ .get_settings = fec_enet_get_settings, ++ .set_settings = fec_enet_set_settings, + .get_drvinfo = fec_enet_get_drvinfo, + .get_regs_len = fec_enet_get_regs_len, + .get_regs = fec_enet_get_regs, +@@ -2648,14 +2675,12 @@ static const struct ethtool_ops fec_enet_ethtool_ops = { + .set_tunable = fec_enet_set_tunable, + .get_wol = fec_enet_get_wol, + .set_wol = fec_enet_set_wol, +- .get_link_ksettings = phy_ethtool_get_link_ksettings, +- .set_link_ksettings = phy_ethtool_set_link_ksettings, + }; + + static int fec_enet_ioctl(struct net_device *ndev, struct ifreq *rq, int cmd) + { + struct fec_enet_private *fep = netdev_priv(ndev); +- struct phy_device *phydev = ndev->phydev; ++ struct phy_device *phydev = fep->phy_dev; + + if (!netif_running(ndev)) + return -EINVAL; +@@ -2685,25 +2710,25 @@ static void fec_enet_free_buffers(struct net_device *ndev) + + for (q = 0; q < fep->num_rx_queues; q++) { + rxq = fep->rx_queue[q]; +- bdp = rxq->bd.base; +- for (i = 0; i < rxq->bd.ring_size; i++) { ++ bdp = rxq->rx_bd_base; ++ for (i = 0; i < rxq->rx_ring_size; i++) { + skb = rxq->rx_skbuff[i]; + rxq->rx_skbuff[i] = NULL; + if (skb) { + dma_unmap_single(&fep->pdev->dev, +- fec32_to_cpu(bdp->cbd_bufaddr), ++ bdp->cbd_bufaddr, + FEC_ENET_RX_FRSIZE - fep->rx_align, + DMA_FROM_DEVICE); + dev_kfree_skb(skb); + } +- bdp = fec_enet_get_nextdesc(bdp, &rxq->bd); ++ bdp = fec_enet_get_nextdesc(bdp, fep, q); + } + } + + for (q = 0; q < fep->num_tx_queues; q++) { + txq = fep->tx_queue[q]; +- bdp = txq->bd.base; +- for (i = 0; i < txq->bd.ring_size; i++) { ++ bdp = txq->tx_bd_base; ++ for (i = 0; i < txq->tx_ring_size; i++) { + kfree(txq->tx_bounce[i]); + txq->tx_bounce[i] = NULL; + skb = txq->tx_skbuff[i]; +@@ -2722,8 +2747,8 @@ static void fec_enet_free_queue(struct net_device *ndev) + for (i = 0; i < fep->num_tx_queues; i++) + if (fep->tx_queue[i] && fep->tx_queue[i]->tso_hdrs) { + txq = fep->tx_queue[i]; +- dma_free_coherent(&fep->pdev->dev, +- txq->bd.ring_size * TSO_HEADER_SIZE, ++ dma_free_coherent(NULL, ++ txq->tx_ring_size * TSO_HEADER_SIZE, + txq->tso_hdrs, + txq->tso_hdrs_dma); + } +@@ -2749,15 +2774,15 @@ static int fec_enet_alloc_queue(struct net_device *ndev) + } + + fep->tx_queue[i] = txq; +- txq->bd.ring_size = TX_RING_SIZE; +- fep->total_tx_ring_size += fep->tx_queue[i]->bd.ring_size; ++ txq->tx_ring_size = TX_RING_SIZE; ++ fep->total_tx_ring_size += fep->tx_queue[i]->tx_ring_size; + + txq->tx_stop_threshold = FEC_MAX_SKB_DESCS; + txq->tx_wake_threshold = +- (txq->bd.ring_size - txq->tx_stop_threshold) / 2; ++ (txq->tx_ring_size - txq->tx_stop_threshold) / 2; + +- txq->tso_hdrs = dma_alloc_coherent(&fep->pdev->dev, +- txq->bd.ring_size * TSO_HEADER_SIZE, ++ txq->tso_hdrs = dma_alloc_coherent(NULL, ++ txq->tx_ring_size * TSO_HEADER_SIZE, + &txq->tso_hdrs_dma, + GFP_KERNEL); + if (!txq->tso_hdrs) { +@@ -2774,8 +2799,8 @@ static int fec_enet_alloc_queue(struct net_device *ndev) + goto alloc_failed; + } + +- fep->rx_queue[i]->bd.ring_size = RX_RING_SIZE; +- fep->total_rx_ring_size += fep->rx_queue[i]->bd.ring_size; ++ fep->rx_queue[i]->rx_ring_size = RX_RING_SIZE; ++ fep->total_rx_ring_size += fep->rx_queue[i]->rx_ring_size; + } + return ret; + +@@ -2794,8 +2819,8 @@ fec_enet_alloc_rxq_buffers(struct net_device *ndev, unsigned int queue) + struct fec_enet_priv_rx_q *rxq; + + rxq = fep->rx_queue[queue]; +- bdp = rxq->bd.base; +- for (i = 0; i < rxq->bd.ring_size; i++) { ++ bdp = rxq->rx_bd_base; ++ for (i = 0; i < rxq->rx_ring_size; i++) { + skb = netdev_alloc_skb(ndev, FEC_ENET_RX_FRSIZE); + if (!skb) + goto err_alloc; +@@ -2806,19 +2831,19 @@ fec_enet_alloc_rxq_buffers(struct net_device *ndev, unsigned int queue) + } + + rxq->rx_skbuff[i] = skb; +- bdp->cbd_sc = cpu_to_fec16(BD_ENET_RX_EMPTY); ++ bdp->cbd_sc = BD_ENET_RX_EMPTY; + + if (fep->bufdesc_ex) { + struct bufdesc_ex *ebdp = (struct bufdesc_ex *)bdp; +- ebdp->cbd_esc = cpu_to_fec32(BD_ENET_RX_INT); ++ ebdp->cbd_esc = BD_ENET_RX_INT; + } + +- bdp = fec_enet_get_nextdesc(bdp, &rxq->bd); ++ bdp = fec_enet_get_nextdesc(bdp, fep, queue); + } + + /* Set the last buffer to wrap. */ +- bdp = fec_enet_get_prevdesc(bdp, &rxq->bd); +- bdp->cbd_sc |= cpu_to_fec16(BD_SC_WRAP); ++ bdp = fec_enet_get_prevdesc(bdp, fep, queue); ++ bdp->cbd_sc |= BD_SC_WRAP; + return 0; + + err_alloc: +@@ -2835,26 +2860,26 @@ fec_enet_alloc_txq_buffers(struct net_device *ndev, unsigned int queue) + struct fec_enet_priv_tx_q *txq; + + txq = fep->tx_queue[queue]; +- bdp = txq->bd.base; +- for (i = 0; i < txq->bd.ring_size; i++) { ++ bdp = txq->tx_bd_base; ++ for (i = 0; i < txq->tx_ring_size; i++) { + txq->tx_bounce[i] = kmalloc(FEC_ENET_TX_FRSIZE, GFP_KERNEL); + if (!txq->tx_bounce[i]) + goto err_alloc; + +- bdp->cbd_sc = cpu_to_fec16(0); +- bdp->cbd_bufaddr = cpu_to_fec32(0); ++ bdp->cbd_sc = 0; ++ bdp->cbd_bufaddr = 0; + + if (fep->bufdesc_ex) { + struct bufdesc_ex *ebdp = (struct bufdesc_ex *)bdp; +- ebdp->cbd_esc = cpu_to_fec32(BD_ENET_TX_INT); ++ ebdp->cbd_esc = BD_ENET_TX_INT; + } + +- bdp = fec_enet_get_nextdesc(bdp, &txq->bd); ++ bdp = fec_enet_get_nextdesc(bdp, fep, queue); + } + + /* Set the last buffer to wrap. */ +- bdp = fec_enet_get_prevdesc(bdp, &txq->bd); +- bdp->cbd_sc |= cpu_to_fec16(BD_SC_WRAP); ++ bdp = fec_enet_get_prevdesc(bdp, fep, queue); ++ bdp->cbd_sc |= BD_SC_WRAP; + + return 0; + +@@ -2903,14 +2928,10 @@ fec_enet_open(struct net_device *ndev) + platform_get_device_id(fep->pdev); + int ret; + +- ret = pm_runtime_get_sync(&fep->pdev->dev); +- if (ret < 0) +- return ret; +- + pinctrl_pm_select_default_state(&fep->pdev->dev); + ret = fec_enet_clk_enable(ndev, true); + if (ret) +- goto clk_enable; ++ return ret; + + /* I should reset the ring buffers here, but I don't yet know + * a simple way to do that. +@@ -2928,13 +2949,11 @@ fec_enet_open(struct net_device *ndev) + if (ret) + goto err_enet_mii_probe; + +- if (fep->quirks & FEC_QUIRK_ERR006687) +- imx6q_cpuidle_fec_irqs_used(); +- + napi_enable(&fep->napi); +- phy_start(ndev->phydev); ++ phy_start(fep->phy_dev); + netif_tx_start_all_queues(ndev); + ++ pm_runtime_get_sync(ndev->dev.parent); + if ((id_entry->driver_data & FEC_QUIRK_BUG_WAITMODE) && + !fec_enet_irq_workaround(fep)) + pm_qos_add_request(&fep->pm_qos_req, +@@ -2947,16 +2966,14 @@ fec_enet_open(struct net_device *ndev) + + device_set_wakeup_enable(&ndev->dev, fep->wol_flag & + FEC_WOL_FLAG_ENABLE); ++ fep->miibus_up_failed = false; + + return 0; + + err_enet_mii_probe: + fec_enet_free_buffers(ndev); + err_enet_alloc: +- fec_enet_clk_enable(ndev, false); +-clk_enable: +- pm_runtime_mark_last_busy(&fep->pdev->dev); +- pm_runtime_put_autosuspend(&fep->pdev->dev); ++ fep->miibus_up_failed = true; + if (!fep->mii_bus_share) + pinctrl_pm_select_sleep_state(&fep->pdev->dev); + return ret; +@@ -2967,7 +2984,7 @@ fec_enet_close(struct net_device *ndev) + { + struct fec_enet_private *fep = netdev_priv(ndev); + +- phy_stop(ndev->phydev); ++ phy_stop(fep->phy_dev); + + if (netif_device_present(ndev)) { + napi_disable(&fep->napi); +@@ -2975,21 +2992,13 @@ fec_enet_close(struct net_device *ndev) + fec_stop(ndev); + } + +- phy_disconnect(ndev->phydev); +- ndev->phydev = NULL; +- +- if (fep->quirks & FEC_QUIRK_ERR006687) +- imx6q_cpuidle_fec_irqs_unused(); +- +- fec_enet_update_ethtool_stats(ndev); ++ phy_disconnect(fep->phy_dev); ++ fep->phy_dev = NULL; + + fec_enet_clk_enable(ndev, false); + pm_qos_remove_request(&fep->pm_qos_req); +- if (!fep->mii_bus_share) +- pinctrl_pm_select_sleep_state(&fep->pdev->dev); +- pm_runtime_mark_last_busy(&fep->pdev->dev); +- pm_runtime_put_autosuspend(&fep->pdev->dev); +- ++ pinctrl_pm_select_sleep_state(&fep->pdev->dev); ++ pm_runtime_put_sync_suspend(ndev->dev.parent); + fec_enet_free_buffers(ndev); + + return 0; +@@ -3005,7 +3014,7 @@ fec_enet_close(struct net_device *ndev) + * this kind of feature?). + */ + +-#define FEC_HASH_BITS 6 /* #bits in hash */ ++#define HASH_BITS 6 /* #bits in hash */ + #define CRC32_POLY 0xEDB88320 + + static void set_multicast_list(struct net_device *ndev) +@@ -3014,7 +3023,6 @@ static void set_multicast_list(struct net_device *ndev) + struct netdev_hw_addr *ha; + unsigned int i, bit, data, crc, tmp; + unsigned char hash; +- unsigned int hash_high, hash_low; + + if (ndev->flags & IFF_PROMISC) { + tmp = readl(fep->hwp + FEC_R_CNTRL); +@@ -3037,10 +3045,10 @@ static void set_multicast_list(struct net_device *ndev) + return; + } + +- /* Add the addresses in hash register ++ /* Clear filter and add the addresses in hash register + */ +- hash_high = 0; +- hash_low = 0; ++ writel(0, fep->hwp + FEC_GRP_HASH_TABLE_HIGH); ++ writel(0, fep->hwp + FEC_GRP_HASH_TABLE_LOW); + + netdev_for_each_mc_addr(ha, ndev) { + /* calculate crc32 value of mac address */ +@@ -3054,20 +3062,21 @@ static void set_multicast_list(struct net_device *ndev) + } + } + +- /* only upper 6 bits (FEC_HASH_BITS) are used ++ /* only upper 6 bits (HASH_BITS) are used + * which point to specific bit in he hash registers + */ +- hash = (crc >> (32 - FEC_HASH_BITS)) & 0x3f; ++ hash = (crc >> (32 - HASH_BITS)) & 0x3f; + + if (hash > 31) { +- hash_high |= 1 << (hash - 32); ++ tmp = readl(fep->hwp + FEC_GRP_HASH_TABLE_HIGH); ++ tmp |= 1 << (hash - 32); ++ writel(tmp, fep->hwp + FEC_GRP_HASH_TABLE_HIGH); + } else { +- hash_low |= 1 << hash; ++ tmp = readl(fep->hwp + FEC_GRP_HASH_TABLE_LOW); ++ tmp |= 1 << hash; ++ writel(tmp, fep->hwp + FEC_GRP_HASH_TABLE_LOW); + } + } +- +- writel_relaxed(hash_high, fep->hwp + FEC_GRP_HASH_TABLE_HIGH); +- writel_relaxed(hash_low, fep->hwp + FEC_GRP_HASH_TABLE_LOW); + } + + /* Set a MAC change in hardware. */ +@@ -3122,6 +3131,7 @@ static void fec_poll_controller(struct net_device *dev) + } + #endif + ++#define FEATURES_NEED_QUIESCE NETIF_F_RXCSUM + static inline void fec_enet_set_netdev_features(struct net_device *netdev, + netdev_features_t features) + { +@@ -3145,7 +3155,7 @@ static int fec_set_features(struct net_device *netdev, + struct fec_enet_private *fep = netdev_priv(netdev); + netdev_features_t changed = features ^ netdev->features; + +- if (netif_running(netdev) && changed & NETIF_F_RXCSUM) { ++ if (netif_running(netdev) && changed & FEATURES_NEED_QUIESCE) { + napi_disable(&fep->napi); + netif_tx_lock_bh(netdev); + fec_stop(netdev); +@@ -3209,14 +3219,6 @@ static const struct net_device_ops fec_netdev_ops = { + .ndo_set_features = fec_set_features, + }; + +-static const unsigned short offset_des_active_rxq[] = { +- FEC_R_DES_ACTIVE_0, FEC_R_DES_ACTIVE_1, FEC_R_DES_ACTIVE_2 +-}; +- +-static const unsigned short offset_des_active_txq[] = { +- FEC_X_DES_ACTIVE_0, FEC_X_DES_ACTIVE_1, FEC_X_DES_ACTIVE_2 +-}; +- + /* + * XXX: We need to clean up on failure exits here. + * +@@ -3224,16 +3226,14 @@ static const unsigned short offset_des_active_txq[] = { + static int fec_enet_init(struct net_device *ndev) + { + struct fec_enet_private *fep = netdev_priv(ndev); ++ struct fec_enet_priv_tx_q *txq; ++ struct fec_enet_priv_rx_q *rxq; + struct bufdesc *cbd_base; + dma_addr_t bd_dma; + int bd_size; + unsigned int i; +- unsigned dsize = fep->bufdesc_ex ? sizeof(struct bufdesc_ex) : +- sizeof(struct bufdesc); +- unsigned dsize_log2 = __fls(dsize); + +- WARN_ON(dsize != (1 << dsize_log2)); +-#if defined(CONFIG_ARM) || defined(CONFIG_ARM64) ++#if defined(CONFIG_ARM) + fep->rx_align = 0xf; + fep->tx_align = 0xf; + #else +@@ -3243,11 +3243,16 @@ static int fec_enet_init(struct net_device *ndev) + + fec_enet_alloc_queue(ndev); + +- bd_size = (fep->total_tx_ring_size + fep->total_rx_ring_size) * dsize; ++ if (fep->bufdesc_ex) ++ fep->bufdesc_size = sizeof(struct bufdesc_ex); ++ else ++ fep->bufdesc_size = sizeof(struct bufdesc); ++ bd_size = (fep->total_tx_ring_size + fep->total_rx_ring_size) * ++ fep->bufdesc_size; + + /* Allocate memory for buffer descriptors. */ +- cbd_base = dmam_alloc_coherent(&fep->pdev->dev, bd_size, &bd_dma, +- GFP_KERNEL); ++ cbd_base = dma_alloc_coherent(NULL, bd_size, &bd_dma, ++ GFP_KERNEL); + if (!cbd_base) { + return -ENOMEM; + } +@@ -3261,35 +3266,33 @@ static int fec_enet_init(struct net_device *ndev) + + /* Set receive and transmit descriptor base. */ + for (i = 0; i < fep->num_rx_queues; i++) { +- struct fec_enet_priv_rx_q *rxq = fep->rx_queue[i]; +- unsigned size = dsize * rxq->bd.ring_size; +- +- rxq->bd.qid = i; +- rxq->bd.base = cbd_base; +- rxq->bd.cur = cbd_base; +- rxq->bd.dma = bd_dma; +- rxq->bd.dsize = dsize; +- rxq->bd.dsize_log2 = dsize_log2; +- rxq->bd.reg_desc_active = fep->hwp + offset_des_active_rxq[i]; +- bd_dma += size; +- cbd_base = (struct bufdesc *)(((void *)cbd_base) + size); +- rxq->bd.last = (struct bufdesc *)(((void *)cbd_base) - dsize); ++ rxq = fep->rx_queue[i]; ++ rxq->index = i; ++ rxq->rx_bd_base = (struct bufdesc *)cbd_base; ++ rxq->bd_dma = bd_dma; ++ if (fep->bufdesc_ex) { ++ bd_dma += sizeof(struct bufdesc_ex) * rxq->rx_ring_size; ++ cbd_base = (struct bufdesc *) ++ (((struct bufdesc_ex *)cbd_base) + rxq->rx_ring_size); ++ } else { ++ bd_dma += sizeof(struct bufdesc) * rxq->rx_ring_size; ++ cbd_base += rxq->rx_ring_size; ++ } + } + + for (i = 0; i < fep->num_tx_queues; i++) { +- struct fec_enet_priv_tx_q *txq = fep->tx_queue[i]; +- unsigned size = dsize * txq->bd.ring_size; +- +- txq->bd.qid = i; +- txq->bd.base = cbd_base; +- txq->bd.cur = cbd_base; +- txq->bd.dma = bd_dma; +- txq->bd.dsize = dsize; +- txq->bd.dsize_log2 = dsize_log2; +- txq->bd.reg_desc_active = fep->hwp + offset_des_active_txq[i]; +- bd_dma += size; +- cbd_base = (struct bufdesc *)(((void *)cbd_base) + size); +- txq->bd.last = (struct bufdesc *)(((void *)cbd_base) - dsize); ++ txq = fep->tx_queue[i]; ++ txq->index = i; ++ txq->tx_bd_base = (struct bufdesc *)cbd_base; ++ txq->bd_dma = bd_dma; ++ if (fep->bufdesc_ex) { ++ bd_dma += sizeof(struct bufdesc_ex) * txq->tx_ring_size; ++ cbd_base = (struct bufdesc *) ++ (((struct bufdesc_ex *)cbd_base) + txq->tx_ring_size); ++ } else { ++ bd_dma += sizeof(struct bufdesc) * txq->tx_ring_size; ++ cbd_base += txq->tx_ring_size; ++ } + } + + +@@ -3323,60 +3326,62 @@ static int fec_enet_init(struct net_device *ndev) + + fec_restart(ndev); + +- fec_enet_update_ethtool_stats(ndev); +- + return 0; + } + + #ifdef CONFIG_OF +-static int fec_reset_phy(struct platform_device *pdev) ++static void fec_reset_phy(struct platform_device *pdev) ++{ ++ struct net_device *ndev = platform_get_drvdata(pdev); ++ struct fec_enet_private *fep = netdev_priv(ndev); ++ ++ if (!gpio_is_valid(fep->phy_reset_gpio)) ++ return; ++ ++ gpio_set_value_cansleep(fep->phy_reset_gpio, 0); ++ msleep(fep->phy_reset_duration); ++ gpio_set_value_cansleep(fep->phy_reset_gpio, 1); ++} ++ ++static int fec_get_reset_gpio(struct platform_device *pdev) + { + int err, phy_reset; +- bool active_high = false; + int msec = 1; + struct device_node *np = pdev->dev.of_node; +- +- if (!np) +- return 0; +- +- err = of_property_read_u32(np, "phy-reset-duration", &msec); +- /* A sane reset duration should not be longer than 1s */ +- if (!err && msec > 1000) +- msec = 1; ++ struct net_device *ndev = platform_get_drvdata(pdev); ++ struct fec_enet_private *fep = netdev_priv(ndev); + + phy_reset = of_get_named_gpio(np, "phy-reset-gpios", 0); +- if (phy_reset == -EPROBE_DEFER) ++ if (!gpio_is_valid(phy_reset)) + return phy_reset; +- else if (!gpio_is_valid(phy_reset)) +- return 0; +- +- active_high = of_property_read_bool(np, "phy-reset-active-high"); + + err = devm_gpio_request_one(&pdev->dev, phy_reset, +- active_high ? GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW, +- "phy-reset"); ++ GPIOF_OUT_INIT_LOW, "phy-reset"); + if (err) { + dev_err(&pdev->dev, "failed to get phy-reset-gpios: %d\n", err); + return err; + } +- +- if (msec > 20) +- msleep(msec); +- else +- usleep_range(msec * 1000, msec * 1000 + 1000); +- +- gpio_set_value_cansleep(phy_reset, !active_high); +- +- return 0; ++ ++ of_property_read_u32(np, "phy-reset-duration", &msec); ++ /* A sane reset duration should not be longer than 1s */ ++ if (msec > 1000) ++ msec = 1; ++ fep->phy_reset_duration = msec; ++ ++ return phy_reset; + } + #else /* CONFIG_OF */ +-static int fec_reset_phy(struct platform_device *pdev) ++static void fec_reset_phy(struct platform_device *pdev) + { + /* + * In case of platform probe, the reset has been done + * by machine code. + */ +- return 0; ++} ++ ++static inline int fec_get_reset_gpio(struct platform_device *pdev) ++{ ++ return -EINVAL; + } + #endif /* CONFIG_OF */ + +@@ -3384,6 +3389,7 @@ static void + fec_enet_get_queue_num(struct platform_device *pdev, int *num_tx, int *num_rx) + { + struct device_node *np = pdev->dev.of_node; ++ int err; + + *num_tx = *num_rx = 1; + +@@ -3391,9 +3397,13 @@ fec_enet_get_queue_num(struct platform_device *pdev, int *num_tx, int *num_rx) + return; + + /* parse the num of tx and rx queues */ +- of_property_read_u32(np, "fsl,num-tx-queues", num_tx); ++ err = of_property_read_u32(np, "fsl,num-tx-queues", num_tx); ++ if (err) ++ *num_tx = 1; + +- of_property_read_u32(np, "fsl,num-rx-queues", num_rx); ++ err = of_property_read_u32(np, "fsl,num-rx-queues", num_rx); ++ if (err) ++ *num_rx = 1; + + if (*num_tx < 1 || *num_tx > FEC_ENET_MAX_TX_QS) { + dev_warn(&pdev->dev, "Invalid num_tx(=%d), fall back to 1\n", +@@ -3460,13 +3470,11 @@ fec_probe(struct platform_device *pdev) + int num_tx_qs; + int num_rx_qs; + +- of_dma_configure(&pdev->dev, np); +- + fec_enet_get_queue_num(pdev, &num_tx_qs, &num_rx_qs); + + /* Init network device */ +- ndev = alloc_etherdev_mqs(sizeof(struct fec_enet_private) + +- FEC_STATS_SIZE, num_tx_qs, num_rx_qs); ++ ndev = alloc_etherdev_mqs(sizeof(struct fec_enet_private), ++ num_tx_qs, num_rx_qs); + if (!ndev) + return -ENOMEM; + +@@ -3505,13 +3513,14 @@ fec_probe(struct platform_device *pdev) + + platform_set_drvdata(pdev, ndev); + +- if ((of_machine_is_compatible("fsl,imx6q") || +- of_machine_is_compatible("fsl,imx6dl")) && +- !of_property_read_bool(np, "fsl,err006687-workaround-present")) +- fep->quirks |= FEC_QUIRK_ERR006687; +- + fec_enet_of_parse_stop_mode(pdev); + ++ ret = fec_get_reset_gpio(pdev); ++ if (ret == -EPROBE_DEFER) ++ goto gpio_defer; ++ fep->phy_reset_gpio = ret; ++ ++ + if (of_get_property(np, "fsl,magic-packet", NULL)) + fep->wol_flag |= FEC_WOL_HAS_MAGIC_PACKET; + +@@ -3524,7 +3533,6 @@ fec_probe(struct platform_device *pdev) + goto failed_phy; + } + phy_node = of_node_get(np); +- fep->fixed_link = true; + } + fep->phy_node = phy_node; + +@@ -3539,10 +3547,6 @@ fec_probe(struct platform_device *pdev) + fep->phy_interface = ret; + } + +-#if !defined(CONFIG_ARM64) +- request_bus_freq(BUS_FREQ_HIGH); +-#endif +- + fep->clk_ipg = devm_clk_get(&pdev->dev, "ipg"); + if (IS_ERR(fep->clk_ipg)) { + ret = PTR_ERR(fep->clk_ipg); +@@ -3577,39 +3581,24 @@ fec_probe(struct platform_device *pdev) + fep->bufdesc_ex = false; + } + ++ pm_runtime_enable(&pdev->dev); + ret = fec_enet_clk_enable(ndev, true); + if (ret) + goto failed_clk; + +- ret = clk_prepare_enable(fep->clk_ipg); +- if (ret) +- goto failed_clk_ipg; +- ret = clk_prepare_enable(fep->clk_ahb); +- if (ret) +- goto failed_clk_ahb; +- + fep->reg_phy = devm_regulator_get(&pdev->dev, "phy"); + if (!IS_ERR(fep->reg_phy)) { + ret = regulator_enable(fep->reg_phy); + if (ret) { + dev_err(&pdev->dev, + "Failed to enable phy regulator: %d\n", ret); +- clk_disable_unprepare(fep->clk_ipg); + goto failed_regulator; + } + } else { + fep->reg_phy = NULL; + } + +- pm_runtime_set_autosuspend_delay(&pdev->dev, FEC_MDIO_PM_TIMEOUT); +- pm_runtime_use_autosuspend(&pdev->dev); +- pm_runtime_get_noresume(&pdev->dev); +- pm_runtime_set_active(&pdev->dev); +- pm_runtime_enable(&pdev->dev); +- +- ret = fec_reset_phy(pdev); +- if (ret) +- goto failed_reset; ++ fec_reset_phy(pdev); + + if (fep->bufdesc_ex) + fec_ptp_init(pdev); +@@ -3641,15 +3630,9 @@ fec_probe(struct platform_device *pdev) + fep->wake_irq = fep->irq[0]; + + init_completion(&fep->mdio_done); +- +- /* board only enable one mii bus in default */ +- if (!of_get_property(np, "fsl,mii-exclusive", NULL)) +- fep->quirks |= FEC_QUIRK_SINGLE_MDIO; + ret = fec_enet_mii_init(pdev); +- if (ret) { +- dev_id = 0; ++ if (ret) + goto failed_mii_init; +- } + + /* Carrier starts down, phylib will bring it up */ + netif_carrier_off(ndev); +@@ -3660,11 +3643,6 @@ fec_probe(struct platform_device *pdev) + if (ret) + goto failed_register; + +- if (!fep->fixed_link) { +- fep->fixups = of_fec_enet_parse_fixup(np); +- fec_enet_register_fixup(ndev); +- } +- + device_init_wakeup(&ndev->dev, fep->wol_flag & + FEC_WOL_HAS_MAGIC_PACKET); + +@@ -3673,10 +3651,6 @@ fec_probe(struct platform_device *pdev) + + fep->rx_copybreak = COPYBREAK_DEFAULT; + INIT_WORK(&fep->tx_timeout_work, fec_enet_timeout_work); +- +- pm_runtime_mark_last_busy(&pdev->dev); +- pm_runtime_put_autosuspend(&pdev->dev); +- + return 0; + + failed_register: +@@ -3684,22 +3658,14 @@ fec_probe(struct platform_device *pdev) + failed_mii_init: + failed_irq: + failed_init: +- fec_ptp_stop(pdev); + if (fep->reg_phy) + regulator_disable(fep->reg_phy); +-failed_reset: +- pm_runtime_put(&pdev->dev); +- pm_runtime_disable(&pdev->dev); + failed_regulator: +-failed_clk_ahb: +- clk_disable_unprepare(fep->clk_ipg); +-failed_clk_ipg: + fec_enet_clk_enable(ndev, false); + failed_clk: +- if (of_phy_is_fixed_link(np)) +- of_phy_deregister_fixed_link(np); + failed_phy: + of_node_put(phy_node); ++gpio_defer: + failed_ioremap: + free_netdev(ndev); + +@@ -3711,16 +3677,15 @@ fec_drv_remove(struct platform_device *pdev) + { + struct net_device *ndev = platform_get_drvdata(pdev); + struct fec_enet_private *fep = netdev_priv(ndev); +- struct device_node *np = pdev->dev.of_node; + ++ cancel_delayed_work_sync(&fep->time_keep); + cancel_work_sync(&fep->tx_timeout_work); +- fec_ptp_stop(pdev); + unregister_netdev(ndev); + fec_enet_mii_remove(fep); + if (fep->reg_phy) + regulator_disable(fep->reg_phy); +- if (of_phy_is_fixed_link(np)) +- of_phy_deregister_fixed_link(np); ++ if (fep->ptp_clock) ++ ptp_clock_unregister(fep->ptp_clock); + of_node_put(fep->phy_node); + free_netdev(ndev); + +@@ -3731,13 +3696,12 @@ static int __maybe_unused fec_suspend(struct device *dev) + { + struct net_device *ndev = dev_get_drvdata(dev); + struct fec_enet_private *fep = netdev_priv(ndev); +- int ret = 0; + + rtnl_lock(); + if (netif_running(ndev)) { + if (fep->wol_flag & FEC_WOL_FLAG_ENABLE) + fep->wol_flag |= FEC_WOL_FLAG_SLEEP_ON; +- phy_stop(ndev->phydev); ++ phy_stop(fep->phy_dev); + napi_disable(&fep->napi); + netif_tx_lock_bh(ndev); + netif_device_detach(ndev); +@@ -3751,12 +3715,8 @@ static int __maybe_unused fec_suspend(struct device *dev) + enable_irq_wake(fep->wake_irq); + } + fec_enet_clk_enable(ndev, false); +- fep->active_in_suspend = !pm_runtime_status_suspended(dev); +- if (fep->active_in_suspend) +- ret = pm_runtime_force_suspend(dev); +- if (ret < 0) +- return ret; +- } else if (fep->mii_bus_share && !ndev->phydev) { ++ } else if (fep->mii_bus_share && fep->miibus_up_failed && !fep->phy_dev) { ++ fec_enet_clk_enable(ndev, false); + pinctrl_pm_select_sleep_state(&fep->pdev->dev); + } + rtnl_unlock(); +@@ -3777,7 +3737,7 @@ static int __maybe_unused fec_resume(struct device *dev) + { + struct net_device *ndev = dev_get_drvdata(dev); + struct fec_enet_private *fep = netdev_priv(ndev); +- int ret = 0; ++ int ret; + int val; + + if (fep->reg_phy && !(fep->wol_flag & FEC_WOL_FLAG_ENABLE)) { +@@ -3788,8 +3748,6 @@ static int __maybe_unused fec_resume(struct device *dev) + + rtnl_lock(); + if (netif_running(ndev)) { +- if (fep->active_in_suspend) +- pm_runtime_force_resume(dev); + ret = fec_enet_clk_enable(ndev, true); + if (ret) { + rtnl_unlock(); +@@ -3812,15 +3770,16 @@ static int __maybe_unused fec_resume(struct device *dev) + netif_device_attach(ndev); + netif_tx_unlock_bh(ndev); + napi_enable(&fep->napi); +- phy_start(ndev->phydev); +- } else if (fep->mii_bus_share && !ndev->phydev) { ++ phy_start(fep->phy_dev); ++ } else if (fep->mii_bus_share && !fep->phy_dev) { + pinctrl_pm_select_default_state(&fep->pdev->dev); ++ fep->miibus_up_failed = true; + /* And then recovery mii bus */ +- ret = fec_restore_mii_bus(ndev); ++ fec_restore_mii_bus(ndev); + } + rtnl_unlock(); + +- return ret; ++ return 0; + + failed_clk: + if (fep->reg_phy) +@@ -3828,46 +3787,21 @@ static int __maybe_unused fec_resume(struct device *dev) + return ret; + } + +-static int __maybe_unused fec_runtime_suspend(struct device *dev) ++static int fec_runtime_suspend(struct device *dev) + { +- struct net_device *ndev = dev_get_drvdata(dev); +- struct fec_enet_private *fep = netdev_priv(ndev); +- +- clk_disable_unprepare(fep->clk_ahb); +- clk_disable_unprepare(fep->clk_ipg); +-#if !defined(CONFIG_ARM64) + release_bus_freq(BUS_FREQ_HIGH); +-#endif +- + return 0; + } + +-static int __maybe_unused fec_runtime_resume(struct device *dev) ++static int fec_runtime_resume(struct device *dev) + { +- struct net_device *ndev = dev_get_drvdata(dev); +- struct fec_enet_private *fep = netdev_priv(ndev); +- int ret; +- +-#if !defined(CONFIG_ARM64) + request_bus_freq(BUS_FREQ_HIGH); +-#endif +- ret = clk_prepare_enable(fep->clk_ahb); +- if (ret) +- return ret; +- ret = clk_prepare_enable(fep->clk_ipg); +- if (ret) +- goto failed_clk_ipg; +- + return 0; +- +-failed_clk_ipg: +- clk_disable_unprepare(fep->clk_ahb); +- return ret; + } + + static const struct dev_pm_ops fec_pm_ops = { +- SET_SYSTEM_SLEEP_PM_OPS(fec_suspend, fec_resume) + SET_RUNTIME_PM_OPS(fec_runtime_suspend, fec_runtime_resume, NULL) ++ SET_SYSTEM_SLEEP_PM_OPS(fec_suspend, fec_resume) + }; + + static struct platform_driver fec_driver = { +diff --git a/drivers/net/ethernet/freescale/fec_mpc52xx.c b/drivers/net/ethernet/freescale/fec_mpc52xx.c +index 446ae9d..afe7f39 100644 +--- a/drivers/net/ethernet/freescale/fec_mpc52xx.c ++++ b/drivers/net/ethernet/freescale/fec_mpc52xx.c +@@ -66,6 +66,7 @@ struct mpc52xx_fec_priv { + /* MDIO link details */ + unsigned int mdio_speed; + struct device_node *phy_node; ++ struct phy_device *phydev; + enum phy_state link; + int seven_wire_mode; + }; +@@ -164,7 +165,7 @@ static int mpc52xx_fec_alloc_rx_buffers(struct net_device *dev, struct bcom_task + static void mpc52xx_fec_adjust_link(struct net_device *dev) + { + struct mpc52xx_fec_priv *priv = netdev_priv(dev); +- struct phy_device *phydev = dev->phydev; ++ struct phy_device *phydev = priv->phydev; + int new_state = 0; + + if (phydev->link != PHY_DOWN) { +@@ -214,17 +215,16 @@ static void mpc52xx_fec_adjust_link(struct net_device *dev) + static int mpc52xx_fec_open(struct net_device *dev) + { + struct mpc52xx_fec_priv *priv = netdev_priv(dev); +- struct phy_device *phydev = NULL; + int err = -EBUSY; + + if (priv->phy_node) { +- phydev = of_phy_connect(priv->ndev, priv->phy_node, +- mpc52xx_fec_adjust_link, 0, 0); +- if (!phydev) { ++ priv->phydev = of_phy_connect(priv->ndev, priv->phy_node, ++ mpc52xx_fec_adjust_link, 0, 0); ++ if (!priv->phydev) { + dev_err(&dev->dev, "of_phy_connect failed\n"); + return -ENODEV; + } +- phy_start(phydev); ++ phy_start(priv->phydev); + } + + if (request_irq(dev->irq, mpc52xx_fec_interrupt, IRQF_SHARED, +@@ -268,9 +268,10 @@ static int mpc52xx_fec_open(struct net_device *dev) + free_ctrl_irq: + free_irq(dev->irq, dev); + free_phy: +- if (phydev) { +- phy_stop(phydev); +- phy_disconnect(phydev); ++ if (priv->phydev) { ++ phy_stop(priv->phydev); ++ phy_disconnect(priv->phydev); ++ priv->phydev = NULL; + } + + return err; +@@ -279,7 +280,6 @@ static int mpc52xx_fec_open(struct net_device *dev) + static int mpc52xx_fec_close(struct net_device *dev) + { + struct mpc52xx_fec_priv *priv = netdev_priv(dev); +- struct phy_device *phydev = dev->phydev; + + netif_stop_queue(dev); + +@@ -291,10 +291,11 @@ static int mpc52xx_fec_close(struct net_device *dev) + free_irq(priv->r_irq, dev); + free_irq(priv->t_irq, dev); + +- if (phydev) { ++ if (priv->phydev) { + /* power down phy */ +- phy_stop(phydev); +- phy_disconnect(phydev); ++ phy_stop(priv->phydev); ++ phy_disconnect(priv->phydev); ++ priv->phydev = NULL; + } + + return 0; +@@ -762,6 +763,26 @@ static void mpc52xx_fec_reset(struct net_device *dev) + + /* ethtool interface */ + ++static int mpc52xx_fec_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) ++{ ++ struct mpc52xx_fec_priv *priv = netdev_priv(dev); ++ ++ if (!priv->phydev) ++ return -ENODEV; ++ ++ return phy_ethtool_gset(priv->phydev, cmd); ++} ++ ++static int mpc52xx_fec_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) ++{ ++ struct mpc52xx_fec_priv *priv = netdev_priv(dev); ++ ++ if (!priv->phydev) ++ return -ENODEV; ++ ++ return phy_ethtool_sset(priv->phydev, cmd); ++} ++ + static u32 mpc52xx_fec_get_msglevel(struct net_device *dev) + { + struct mpc52xx_fec_priv *priv = netdev_priv(dev); +@@ -775,23 +796,23 @@ static void mpc52xx_fec_set_msglevel(struct net_device *dev, u32 level) + } + + static const struct ethtool_ops mpc52xx_fec_ethtool_ops = { ++ .get_settings = mpc52xx_fec_get_settings, ++ .set_settings = mpc52xx_fec_set_settings, + .get_link = ethtool_op_get_link, + .get_msglevel = mpc52xx_fec_get_msglevel, + .set_msglevel = mpc52xx_fec_set_msglevel, + .get_ts_info = ethtool_op_get_ts_info, +- .get_link_ksettings = phy_ethtool_get_link_ksettings, +- .set_link_ksettings = phy_ethtool_set_link_ksettings, + }; + + + static int mpc52xx_fec_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) + { +- struct phy_device *phydev = dev->phydev; ++ struct mpc52xx_fec_priv *priv = netdev_priv(dev); + +- if (!phydev) ++ if (!priv->phydev) + return -ENOTSUPP; + +- return phy_mii_ioctl(phydev, rq, cmd); ++ return phy_mii_ioctl(priv->phydev, rq, cmd); + } + + static const struct net_device_ops mpc52xx_fec_netdev_ops = { +@@ -1063,23 +1084,27 @@ static struct platform_driver mpc52xx_fec_driver = { + /* Module */ + /* ======================================================================== */ + +-static struct platform_driver * const drivers[] = { +-#ifdef CONFIG_FEC_MPC52xx_MDIO +- &mpc52xx_fec_mdio_driver, +-#endif +- &mpc52xx_fec_driver, +-}; +- + static int __init + mpc52xx_fec_init(void) + { +- return platform_register_drivers(drivers, ARRAY_SIZE(drivers)); ++#ifdef CONFIG_FEC_MPC52xx_MDIO ++ int ret; ++ ret = platform_driver_register(&mpc52xx_fec_mdio_driver); ++ if (ret) { ++ pr_err("failed to register mdio driver\n"); ++ return ret; ++ } ++#endif ++ return platform_driver_register(&mpc52xx_fec_driver); + } + + static void __exit + mpc52xx_fec_exit(void) + { +- platform_unregister_drivers(drivers, ARRAY_SIZE(drivers)); ++ platform_driver_unregister(&mpc52xx_fec_driver); ++#ifdef CONFIG_FEC_MPC52xx_MDIO ++ platform_driver_unregister(&mpc52xx_fec_mdio_driver); ++#endif + } + + +diff --git a/drivers/net/ethernet/freescale/fec_mpc52xx_phy.c b/drivers/net/ethernet/freescale/fec_mpc52xx_phy.c +index b5497e3..1e647be 100644 +--- a/drivers/net/ethernet/freescale/fec_mpc52xx_phy.c ++++ b/drivers/net/ethernet/freescale/fec_mpc52xx_phy.c +@@ -22,6 +22,7 @@ + + struct mpc52xx_fec_mdio_priv { + struct mpc52xx_fec __iomem *regs; ++ int mdio_irqs[PHY_MAX_ADDR]; + }; + + static int mpc52xx_fec_mdio_transfer(struct mii_bus *bus, int phy_id, +@@ -82,6 +83,9 @@ static int mpc52xx_fec_mdio_probe(struct platform_device *of) + bus->read = mpc52xx_fec_mdio_read; + bus->write = mpc52xx_fec_mdio_write; + ++ /* setup irqs */ ++ bus->irq = priv->mdio_irqs; ++ + /* setup registers */ + err = of_address_to_resource(np, 0, &res); + if (err) +diff --git a/drivers/net/ethernet/freescale/fec_ptp.c b/drivers/net/ethernet/freescale/fec_ptp.c +index f9e7446..7a8386a 100644 +--- a/drivers/net/ethernet/freescale/fec_ptp.c ++++ b/drivers/net/ethernet/freescale/fec_ptp.c +@@ -112,8 +112,9 @@ static int fec_ptp_enable_pps(struct fec_enet_private *fep, uint enable) + unsigned long flags; + u32 val, tempval; + int inc; +- struct timespec64 ts; ++ struct timespec ts; + u64 ns; ++ u32 remainder; + val = 0; + + if (!(fep->hwts_tx_en || fep->hwts_rx_en)) { +@@ -162,7 +163,8 @@ static int fec_ptp_enable_pps(struct fec_enet_private *fep, uint enable) + tempval = readl(fep->hwp + FEC_ATIME); + /* Convert the ptp local counter to 1588 timestamp */ + ns = timecounter_cyc2time(&fep->tc, tempval); +- ts = ns_to_timespec64(ns); ++ ts.tv_sec = div_u64_rem(ns, 1000000000ULL, &remainder); ++ ts.tv_nsec = remainder; + + /* The tempval is less than 3 seconds, and so val is less than + * 4 seconds. No overflow for 32bit calculation. +@@ -596,16 +598,6 @@ void fec_ptp_init(struct platform_device *pdev) + schedule_delayed_work(&fep->time_keep, HZ); + } + +-void fec_ptp_stop(struct platform_device *pdev) +-{ +- struct net_device *ndev = platform_get_drvdata(pdev); +- struct fec_enet_private *fep = netdev_priv(ndev); +- +- cancel_delayed_work_sync(&fep->time_keep); +- if (fep->ptp_clock) +- ptp_clock_unregister(fep->ptp_clock); +-} +- + /** + * fec_ptp_check_pps_event + * @fep: the fec_enet_private structure handle +diff --git a/drivers/net/ethernet/freescale/fman/Kconfig b/drivers/net/ethernet/freescale/fman/Kconfig +deleted file mode 100644 +index 79b7c84..0000000 +--- a/drivers/net/ethernet/freescale/fman/Kconfig ++++ /dev/null +@@ -1,9 +0,0 @@ +-config FSL_FMAN +- tristate "FMan support" +- depends on FSL_SOC || COMPILE_TEST +- select GENERIC_ALLOCATOR +- select PHYLIB +- default n +- help +- Freescale Data-Path Acceleration Architecture Frame Manager +- (FMan) support +diff --git a/drivers/net/ethernet/freescale/fman/Makefile b/drivers/net/ethernet/freescale/fman/Makefile +deleted file mode 100644 +index 6049177..0000000 +--- a/drivers/net/ethernet/freescale/fman/Makefile ++++ /dev/null +@@ -1,9 +0,0 @@ +-subdir-ccflags-y += -I$(srctree)/drivers/net/ethernet/freescale/fman +- +-obj-$(CONFIG_FSL_FMAN) += fsl_fman.o +-obj-$(CONFIG_FSL_FMAN) += fsl_fman_port.o +-obj-$(CONFIG_FSL_FMAN) += fsl_mac.o +- +-fsl_fman-objs := fman_muram.o fman.o fman_sp.o +-fsl_fman_port-objs := fman_port.o +-fsl_mac-objs:= mac.o fman_dtsec.o fman_memac.o fman_tgec.o +diff --git a/drivers/net/ethernet/freescale/fman/fman.c b/drivers/net/ethernet/freescale/fman/fman.c +deleted file mode 100644 +index dafd9e1..0000000 +--- a/drivers/net/ethernet/freescale/fman/fman.c ++++ /dev/null +@@ -1,2967 +0,0 @@ +-/* +- * Copyright 2008-2015 Freescale Semiconductor Inc. +- * +- * Redistribution and use in source and binary forms, with or without +- * modification, are permitted provided that the following conditions are met: +- * * Redistributions of source code must retain the above copyright +- * notice, this list of conditions and the following disclaimer. +- * * Redistributions in binary form must reproduce the above copyright +- * notice, this list of conditions and the following disclaimer in the +- * documentation and/or other materials provided with the distribution. +- * * Neither the name of Freescale Semiconductor nor the +- * names of its contributors may be used to endorse or promote products +- * derived from this software without specific prior written permission. +- * +- * +- * ALTERNATIVELY, this software may be distributed under the terms of the +- * GNU General Public License ("GPL") as published by the Free Software +- * Foundation, either version 2 of that License or (at your option) any +- * later version. +- * +- * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY +- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +- * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY +- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +- */ +- +-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +- +-#include "fman.h" +-#include "fman_muram.h" +- +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-/* General defines */ +-#define FMAN_LIODN_TBL 64 /* size of LIODN table */ +-#define MAX_NUM_OF_MACS 10 +-#define FM_NUM_OF_FMAN_CTRL_EVENT_REGS 4 +-#define BASE_RX_PORTID 0x08 +-#define BASE_TX_PORTID 0x28 +- +-/* Modules registers offsets */ +-#define BMI_OFFSET 0x00080000 +-#define QMI_OFFSET 0x00080400 +-#define DMA_OFFSET 0x000C2000 +-#define FPM_OFFSET 0x000C3000 +-#define IMEM_OFFSET 0x000C4000 +-#define CGP_OFFSET 0x000DB000 +- +-/* Exceptions bit map */ +-#define EX_DMA_BUS_ERROR 0x80000000 +-#define EX_DMA_READ_ECC 0x40000000 +-#define EX_DMA_SYSTEM_WRITE_ECC 0x20000000 +-#define EX_DMA_FM_WRITE_ECC 0x10000000 +-#define EX_FPM_STALL_ON_TASKS 0x08000000 +-#define EX_FPM_SINGLE_ECC 0x04000000 +-#define EX_FPM_DOUBLE_ECC 0x02000000 +-#define EX_QMI_SINGLE_ECC 0x01000000 +-#define EX_QMI_DEQ_FROM_UNKNOWN_PORTID 0x00800000 +-#define EX_QMI_DOUBLE_ECC 0x00400000 +-#define EX_BMI_LIST_RAM_ECC 0x00200000 +-#define EX_BMI_STORAGE_PROFILE_ECC 0x00100000 +-#define EX_BMI_STATISTICS_RAM_ECC 0x00080000 +-#define EX_IRAM_ECC 0x00040000 +-#define EX_MURAM_ECC 0x00020000 +-#define EX_BMI_DISPATCH_RAM_ECC 0x00010000 +-#define EX_DMA_SINGLE_PORT_ECC 0x00008000 +- +-/* DMA defines */ +-/* masks */ +-#define DMA_MODE_BER 0x00200000 +-#define DMA_MODE_ECC 0x00000020 +-#define DMA_MODE_SECURE_PROT 0x00000800 +-#define DMA_MODE_AXI_DBG_MASK 0x0F000000 +- +-#define DMA_TRANSFER_PORTID_MASK 0xFF000000 +-#define DMA_TRANSFER_TNUM_MASK 0x00FF0000 +-#define DMA_TRANSFER_LIODN_MASK 0x00000FFF +- +-#define DMA_STATUS_BUS_ERR 0x08000000 +-#define DMA_STATUS_READ_ECC 0x04000000 +-#define DMA_STATUS_SYSTEM_WRITE_ECC 0x02000000 +-#define DMA_STATUS_FM_WRITE_ECC 0x01000000 +-#define DMA_STATUS_FM_SPDAT_ECC 0x00080000 +- +-#define DMA_MODE_CACHE_OR_SHIFT 30 +-#define DMA_MODE_AXI_DBG_SHIFT 24 +-#define DMA_MODE_CEN_SHIFT 13 +-#define DMA_MODE_CEN_MASK 0x00000007 +-#define DMA_MODE_DBG_SHIFT 7 +-#define DMA_MODE_AID_MODE_SHIFT 4 +- +-#define DMA_THRESH_COMMQ_SHIFT 24 +-#define DMA_THRESH_READ_INT_BUF_SHIFT 16 +-#define DMA_THRESH_READ_INT_BUF_MASK 0x0000003f +-#define DMA_THRESH_WRITE_INT_BUF_MASK 0x0000003f +- +-#define DMA_TRANSFER_PORTID_SHIFT 24 +-#define DMA_TRANSFER_TNUM_SHIFT 16 +- +-#define DMA_CAM_SIZEOF_ENTRY 0x40 +-#define DMA_CAM_UNITS 8 +- +-#define DMA_LIODN_SHIFT 16 +-#define DMA_LIODN_BASE_MASK 0x00000FFF +- +-/* FPM defines */ +-#define FPM_EV_MASK_DOUBLE_ECC 0x80000000 +-#define FPM_EV_MASK_STALL 0x40000000 +-#define FPM_EV_MASK_SINGLE_ECC 0x20000000 +-#define FPM_EV_MASK_RELEASE_FM 0x00010000 +-#define FPM_EV_MASK_DOUBLE_ECC_EN 0x00008000 +-#define FPM_EV_MASK_STALL_EN 0x00004000 +-#define FPM_EV_MASK_SINGLE_ECC_EN 0x00002000 +-#define FPM_EV_MASK_EXTERNAL_HALT 0x00000008 +-#define FPM_EV_MASK_ECC_ERR_HALT 0x00000004 +- +-#define FPM_RAM_MURAM_ECC 0x00008000 +-#define FPM_RAM_IRAM_ECC 0x00004000 +-#define FPM_IRAM_ECC_ERR_EX_EN 0x00020000 +-#define FPM_MURAM_ECC_ERR_EX_EN 0x00040000 +-#define FPM_RAM_IRAM_ECC_EN 0x40000000 +-#define FPM_RAM_RAMS_ECC_EN 0x80000000 +-#define FPM_RAM_RAMS_ECC_EN_SRC_SEL 0x08000000 +- +-#define FPM_REV1_MAJOR_MASK 0x0000FF00 +-#define FPM_REV1_MINOR_MASK 0x000000FF +- +-#define FPM_DISP_LIMIT_SHIFT 24 +- +-#define FPM_PRT_FM_CTL1 0x00000001 +-#define FPM_PRT_FM_CTL2 0x00000002 +-#define FPM_PORT_FM_CTL_PORTID_SHIFT 24 +-#define FPM_PRC_ORA_FM_CTL_SEL_SHIFT 16 +- +-#define FPM_THR1_PRS_SHIFT 24 +-#define FPM_THR1_KG_SHIFT 16 +-#define FPM_THR1_PLCR_SHIFT 8 +-#define FPM_THR1_BMI_SHIFT 0 +- +-#define FPM_THR2_QMI_ENQ_SHIFT 24 +-#define FPM_THR2_QMI_DEQ_SHIFT 0 +-#define FPM_THR2_FM_CTL1_SHIFT 16 +-#define FPM_THR2_FM_CTL2_SHIFT 8 +- +-#define FPM_EV_MASK_CAT_ERR_SHIFT 1 +-#define FPM_EV_MASK_DMA_ERR_SHIFT 0 +- +-#define FPM_REV1_MAJOR_SHIFT 8 +- +-#define FPM_RSTC_FM_RESET 0x80000000 +-#define FPM_RSTC_MAC0_RESET 0x40000000 +-#define FPM_RSTC_MAC1_RESET 0x20000000 +-#define FPM_RSTC_MAC2_RESET 0x10000000 +-#define FPM_RSTC_MAC3_RESET 0x08000000 +-#define FPM_RSTC_MAC8_RESET 0x04000000 +-#define FPM_RSTC_MAC4_RESET 0x02000000 +-#define FPM_RSTC_MAC5_RESET 0x01000000 +-#define FPM_RSTC_MAC6_RESET 0x00800000 +-#define FPM_RSTC_MAC7_RESET 0x00400000 +-#define FPM_RSTC_MAC9_RESET 0x00200000 +- +-#define FPM_TS_INT_SHIFT 16 +-#define FPM_TS_CTL_EN 0x80000000 +- +-/* BMI defines */ +-#define BMI_INIT_START 0x80000000 +-#define BMI_ERR_INTR_EN_STORAGE_PROFILE_ECC 0x80000000 +-#define BMI_ERR_INTR_EN_LIST_RAM_ECC 0x40000000 +-#define BMI_ERR_INTR_EN_STATISTICS_RAM_ECC 0x20000000 +-#define BMI_ERR_INTR_EN_DISPATCH_RAM_ECC 0x10000000 +-#define BMI_NUM_OF_TASKS_MASK 0x3F000000 +-#define BMI_NUM_OF_EXTRA_TASKS_MASK 0x000F0000 +-#define BMI_NUM_OF_DMAS_MASK 0x00000F00 +-#define BMI_NUM_OF_EXTRA_DMAS_MASK 0x0000000F +-#define BMI_FIFO_SIZE_MASK 0x000003FF +-#define BMI_EXTRA_FIFO_SIZE_MASK 0x03FF0000 +-#define BMI_CFG2_DMAS_MASK 0x0000003F +-#define BMI_CFG2_TASKS_MASK 0x0000003F +- +-#define BMI_CFG2_TASKS_SHIFT 16 +-#define BMI_CFG2_DMAS_SHIFT 0 +-#define BMI_CFG1_FIFO_SIZE_SHIFT 16 +-#define BMI_NUM_OF_TASKS_SHIFT 24 +-#define BMI_EXTRA_NUM_OF_TASKS_SHIFT 16 +-#define BMI_NUM_OF_DMAS_SHIFT 8 +-#define BMI_EXTRA_NUM_OF_DMAS_SHIFT 0 +- +-#define BMI_FIFO_ALIGN 0x100 +- +-#define BMI_EXTRA_FIFO_SIZE_SHIFT 16 +- +-/* QMI defines */ +-#define QMI_CFG_ENQ_EN 0x80000000 +-#define QMI_CFG_DEQ_EN 0x40000000 +-#define QMI_CFG_EN_COUNTERS 0x10000000 +-#define QMI_CFG_DEQ_MASK 0x0000003F +-#define QMI_CFG_ENQ_MASK 0x00003F00 +-#define QMI_CFG_ENQ_SHIFT 8 +- +-#define QMI_ERR_INTR_EN_DOUBLE_ECC 0x80000000 +-#define QMI_ERR_INTR_EN_DEQ_FROM_DEF 0x40000000 +-#define QMI_INTR_EN_SINGLE_ECC 0x80000000 +- +-#define QMI_GS_HALT_NOT_BUSY 0x00000002 +- +-/* IRAM defines */ +-#define IRAM_IADD_AIE 0x80000000 +-#define IRAM_READY 0x80000000 +- +-/* Default values */ +-#define DEFAULT_CATASTROPHIC_ERR 0 +-#define DEFAULT_DMA_ERR 0 +-#define DEFAULT_AID_MODE FMAN_DMA_AID_OUT_TNUM +-#define DEFAULT_DMA_COMM_Q_LOW 0x2A +-#define DEFAULT_DMA_COMM_Q_HIGH 0x3F +-#define DEFAULT_CACHE_OVERRIDE 0 +-#define DEFAULT_DMA_CAM_NUM_OF_ENTRIES 64 +-#define DEFAULT_DMA_DBG_CNT_MODE 0 +-#define DEFAULT_DMA_SOS_EMERGENCY 0 +-#define DEFAULT_DMA_WATCHDOG 0 +-#define DEFAULT_DISP_LIMIT 0 +-#define DEFAULT_PRS_DISP_TH 16 +-#define DEFAULT_PLCR_DISP_TH 16 +-#define DEFAULT_KG_DISP_TH 16 +-#define DEFAULT_BMI_DISP_TH 16 +-#define DEFAULT_QMI_ENQ_DISP_TH 16 +-#define DEFAULT_QMI_DEQ_DISP_TH 16 +-#define DEFAULT_FM_CTL1_DISP_TH 16 +-#define DEFAULT_FM_CTL2_DISP_TH 16 +- +-#define DFLT_AXI_DBG_NUM_OF_BEATS 1 +- +-#define DFLT_DMA_READ_INT_BUF_LOW(dma_thresh_max_buf) \ +- ((dma_thresh_max_buf + 1) / 2) +-#define DFLT_DMA_READ_INT_BUF_HIGH(dma_thresh_max_buf) \ +- ((dma_thresh_max_buf + 1) * 3 / 4) +-#define DFLT_DMA_WRITE_INT_BUF_LOW(dma_thresh_max_buf) \ +- ((dma_thresh_max_buf + 1) / 2) +-#define DFLT_DMA_WRITE_INT_BUF_HIGH(dma_thresh_max_buf)\ +- ((dma_thresh_max_buf + 1) * 3 / 4) +- +-#define DMA_COMM_Q_LOW_FMAN_V3 0x2A +-#define DMA_COMM_Q_LOW_FMAN_V2(dma_thresh_max_commq) \ +- ((dma_thresh_max_commq + 1) / 2) +-#define DFLT_DMA_COMM_Q_LOW(major, dma_thresh_max_commq) \ +- ((major == 6) ? DMA_COMM_Q_LOW_FMAN_V3 : \ +- DMA_COMM_Q_LOW_FMAN_V2(dma_thresh_max_commq)) +- +-#define DMA_COMM_Q_HIGH_FMAN_V3 0x3f +-#define DMA_COMM_Q_HIGH_FMAN_V2(dma_thresh_max_commq) \ +- ((dma_thresh_max_commq + 1) * 3 / 4) +-#define DFLT_DMA_COMM_Q_HIGH(major, dma_thresh_max_commq) \ +- ((major == 6) ? DMA_COMM_Q_HIGH_FMAN_V3 : \ +- DMA_COMM_Q_HIGH_FMAN_V2(dma_thresh_max_commq)) +- +-#define TOTAL_NUM_OF_TASKS_FMAN_V3L 59 +-#define TOTAL_NUM_OF_TASKS_FMAN_V3H 124 +-#define DFLT_TOTAL_NUM_OF_TASKS(major, minor, bmi_max_num_of_tasks) \ +- ((major == 6) ? ((minor == 1 || minor == 4) ? \ +- TOTAL_NUM_OF_TASKS_FMAN_V3L : TOTAL_NUM_OF_TASKS_FMAN_V3H) : \ +- bmi_max_num_of_tasks) +- +-#define DMA_CAM_NUM_OF_ENTRIES_FMAN_V3 64 +-#define DMA_CAM_NUM_OF_ENTRIES_FMAN_V2 32 +-#define DFLT_DMA_CAM_NUM_OF_ENTRIES(major) \ +- (major == 6 ? DMA_CAM_NUM_OF_ENTRIES_FMAN_V3 : \ +- DMA_CAM_NUM_OF_ENTRIES_FMAN_V2) +- +-#define FM_TIMESTAMP_1_USEC_BIT 8 +- +-/* Defines used for enabling/disabling FMan interrupts */ +-#define ERR_INTR_EN_DMA 0x00010000 +-#define ERR_INTR_EN_FPM 0x80000000 +-#define ERR_INTR_EN_BMI 0x00800000 +-#define ERR_INTR_EN_QMI 0x00400000 +-#define ERR_INTR_EN_MURAM 0x00040000 +-#define ERR_INTR_EN_MAC0 0x00004000 +-#define ERR_INTR_EN_MAC1 0x00002000 +-#define ERR_INTR_EN_MAC2 0x00001000 +-#define ERR_INTR_EN_MAC3 0x00000800 +-#define ERR_INTR_EN_MAC4 0x00000400 +-#define ERR_INTR_EN_MAC5 0x00000200 +-#define ERR_INTR_EN_MAC6 0x00000100 +-#define ERR_INTR_EN_MAC7 0x00000080 +-#define ERR_INTR_EN_MAC8 0x00008000 +-#define ERR_INTR_EN_MAC9 0x00000040 +- +-#define INTR_EN_QMI 0x40000000 +-#define INTR_EN_MAC0 0x00080000 +-#define INTR_EN_MAC1 0x00040000 +-#define INTR_EN_MAC2 0x00020000 +-#define INTR_EN_MAC3 0x00010000 +-#define INTR_EN_MAC4 0x00000040 +-#define INTR_EN_MAC5 0x00000020 +-#define INTR_EN_MAC6 0x00000008 +-#define INTR_EN_MAC7 0x00000002 +-#define INTR_EN_MAC8 0x00200000 +-#define INTR_EN_MAC9 0x00100000 +-#define INTR_EN_REV0 0x00008000 +-#define INTR_EN_REV1 0x00004000 +-#define INTR_EN_REV2 0x00002000 +-#define INTR_EN_REV3 0x00001000 +-#define INTR_EN_TMR 0x01000000 +- +-enum fman_dma_aid_mode { +- FMAN_DMA_AID_OUT_PORT_ID = 0, /* 4 LSB of PORT_ID */ +- FMAN_DMA_AID_OUT_TNUM /* 4 LSB of TNUM */ +-}; +- +-struct fman_iram_regs { +- u32 iadd; /* FM IRAM instruction address register */ +- u32 idata; /* FM IRAM instruction data register */ +- u32 itcfg; /* FM IRAM timing config register */ +- u32 iready; /* FM IRAM ready register */ +-}; +- +-struct fman_fpm_regs { +- u32 fmfp_tnc; /* FPM TNUM Control 0x00 */ +- u32 fmfp_prc; /* FPM Port_ID FmCtl Association 0x04 */ +- u32 fmfp_brkc; /* FPM Breakpoint Control 0x08 */ +- u32 fmfp_mxd; /* FPM Flush Control 0x0c */ +- u32 fmfp_dist1; /* FPM Dispatch Thresholds1 0x10 */ +- u32 fmfp_dist2; /* FPM Dispatch Thresholds2 0x14 */ +- u32 fm_epi; /* FM Error Pending Interrupts 0x18 */ +- u32 fm_rie; /* FM Error Interrupt Enable 0x1c */ +- u32 fmfp_fcev[4]; /* FPM FMan-Controller Event 1-4 0x20-0x2f */ +- u32 res0030[4]; /* res 0x30 - 0x3f */ +- u32 fmfp_cee[4]; /* PM FMan-Controller Event 1-4 0x40-0x4f */ +- u32 res0050[4]; /* res 0x50-0x5f */ +- u32 fmfp_tsc1; /* FPM TimeStamp Control1 0x60 */ +- u32 fmfp_tsc2; /* FPM TimeStamp Control2 0x64 */ +- u32 fmfp_tsp; /* FPM Time Stamp 0x68 */ +- u32 fmfp_tsf; /* FPM Time Stamp Fraction 0x6c */ +- u32 fm_rcr; /* FM Rams Control 0x70 */ +- u32 fmfp_extc; /* FPM External Requests Control 0x74 */ +- u32 fmfp_ext1; /* FPM External Requests Config1 0x78 */ +- u32 fmfp_ext2; /* FPM External Requests Config2 0x7c */ +- u32 fmfp_drd[16]; /* FPM Data_Ram Data 0-15 0x80 - 0xbf */ +- u32 fmfp_dra; /* FPM Data Ram Access 0xc0 */ +- u32 fm_ip_rev_1; /* FM IP Block Revision 1 0xc4 */ +- u32 fm_ip_rev_2; /* FM IP Block Revision 2 0xc8 */ +- u32 fm_rstc; /* FM Reset Command 0xcc */ +- u32 fm_cld; /* FM Classifier Debug 0xd0 */ +- u32 fm_npi; /* FM Normal Pending Interrupts 0xd4 */ +- u32 fmfp_exte; /* FPM External Requests Enable 0xd8 */ +- u32 fmfp_ee; /* FPM Event&Mask 0xdc */ +- u32 fmfp_cev[4]; /* FPM CPU Event 1-4 0xe0-0xef */ +- u32 res00f0[4]; /* res 0xf0-0xff */ +- u32 fmfp_ps[50]; /* FPM Port Status 0x100-0x1c7 */ +- u32 res01c8[14]; /* res 0x1c8-0x1ff */ +- u32 fmfp_clfabc; /* FPM CLFABC 0x200 */ +- u32 fmfp_clfcc; /* FPM CLFCC 0x204 */ +- u32 fmfp_clfaval; /* FPM CLFAVAL 0x208 */ +- u32 fmfp_clfbval; /* FPM CLFBVAL 0x20c */ +- u32 fmfp_clfcval; /* FPM CLFCVAL 0x210 */ +- u32 fmfp_clfamsk; /* FPM CLFAMSK 0x214 */ +- u32 fmfp_clfbmsk; /* FPM CLFBMSK 0x218 */ +- u32 fmfp_clfcmsk; /* FPM CLFCMSK 0x21c */ +- u32 fmfp_clfamc; /* FPM CLFAMC 0x220 */ +- u32 fmfp_clfbmc; /* FPM CLFBMC 0x224 */ +- u32 fmfp_clfcmc; /* FPM CLFCMC 0x228 */ +- u32 fmfp_decceh; /* FPM DECCEH 0x22c */ +- u32 res0230[116]; /* res 0x230 - 0x3ff */ +- u32 fmfp_ts[128]; /* 0x400: FPM Task Status 0x400 - 0x5ff */ +- u32 res0600[0x400 - 384]; +-}; +- +-struct fman_bmi_regs { +- u32 fmbm_init; /* BMI Initialization 0x00 */ +- u32 fmbm_cfg1; /* BMI Configuration 1 0x04 */ +- u32 fmbm_cfg2; /* BMI Configuration 2 0x08 */ +- u32 res000c[5]; /* 0x0c - 0x1f */ +- u32 fmbm_ievr; /* Interrupt Event Register 0x20 */ +- u32 fmbm_ier; /* Interrupt Enable Register 0x24 */ +- u32 fmbm_ifr; /* Interrupt Force Register 0x28 */ +- u32 res002c[5]; /* 0x2c - 0x3f */ +- u32 fmbm_arb[8]; /* BMI Arbitration 0x40 - 0x5f */ +- u32 res0060[12]; /* 0x60 - 0x8f */ +- u32 fmbm_dtc[3]; /* Debug Trap Counter 0x90 - 0x9b */ +- u32 res009c; /* 0x9c */ +- u32 fmbm_dcv[3][4]; /* Debug Compare val 0xa0-0xcf */ +- u32 fmbm_dcm[3][4]; /* Debug Compare Mask 0xd0-0xff */ +- u32 fmbm_gde; /* BMI Global Debug Enable 0x100 */ +- u32 fmbm_pp[63]; /* BMI Port Parameters 0x104 - 0x1ff */ +- u32 res0200; /* 0x200 */ +- u32 fmbm_pfs[63]; /* BMI Port FIFO Size 0x204 - 0x2ff */ +- u32 res0300; /* 0x300 */ +- u32 fmbm_spliodn[63]; /* Port Partition ID 0x304 - 0x3ff */ +-}; +- +-struct fman_qmi_regs { +- u32 fmqm_gc; /* General Configuration Register 0x00 */ +- u32 res0004; /* 0x04 */ +- u32 fmqm_eie; /* Error Interrupt Event Register 0x08 */ +- u32 fmqm_eien; /* Error Interrupt Enable Register 0x0c */ +- u32 fmqm_eif; /* Error Interrupt Force Register 0x10 */ +- u32 fmqm_ie; /* Interrupt Event Register 0x14 */ +- u32 fmqm_ien; /* Interrupt Enable Register 0x18 */ +- u32 fmqm_if; /* Interrupt Force Register 0x1c */ +- u32 fmqm_gs; /* Global Status Register 0x20 */ +- u32 fmqm_ts; /* Task Status Register 0x24 */ +- u32 fmqm_etfc; /* Enqueue Total Frame Counter 0x28 */ +- u32 fmqm_dtfc; /* Dequeue Total Frame Counter 0x2c */ +- u32 fmqm_dc0; /* Dequeue Counter 0 0x30 */ +- u32 fmqm_dc1; /* Dequeue Counter 1 0x34 */ +- u32 fmqm_dc2; /* Dequeue Counter 2 0x38 */ +- u32 fmqm_dc3; /* Dequeue Counter 3 0x3c */ +- u32 fmqm_dfdc; /* Dequeue FQID from Default Counter 0x40 */ +- u32 fmqm_dfcc; /* Dequeue FQID from Context Counter 0x44 */ +- u32 fmqm_dffc; /* Dequeue FQID from FD Counter 0x48 */ +- u32 fmqm_dcc; /* Dequeue Confirm Counter 0x4c */ +- u32 res0050[7]; /* 0x50 - 0x6b */ +- u32 fmqm_tapc; /* Tnum Aging Period Control 0x6c */ +- u32 fmqm_dmcvc; /* Dequeue MAC Command Valid Counter 0x70 */ +- u32 fmqm_difdcc; /* Dequeue Invalid FD Command Counter 0x74 */ +- u32 fmqm_da1v; /* Dequeue A1 Valid Counter 0x78 */ +- u32 res007c; /* 0x7c */ +- u32 fmqm_dtc; /* 0x80 Debug Trap Counter 0x80 */ +- u32 fmqm_efddd; /* 0x84 Enqueue Frame desc Dynamic dbg 0x84 */ +- u32 res0088[2]; /* 0x88 - 0x8f */ +- struct { +- u32 fmqm_dtcfg1; /* 0x90 dbg trap cfg 1 Register 0x00 */ +- u32 fmqm_dtval1; /* Debug Trap Value 1 Register 0x04 */ +- u32 fmqm_dtm1; /* Debug Trap Mask 1 Register 0x08 */ +- u32 fmqm_dtc1; /* Debug Trap Counter 1 Register 0x0c */ +- u32 fmqm_dtcfg2; /* dbg Trap cfg 2 Register 0x10 */ +- u32 fmqm_dtval2; /* Debug Trap Value 2 Register 0x14 */ +- u32 fmqm_dtm2; /* Debug Trap Mask 2 Register 0x18 */ +- u32 res001c; /* 0x1c */ +- } dbg_traps[3]; /* 0x90 - 0xef */ +- u8 res00f0[0x400 - 0xf0]; /* 0xf0 - 0x3ff */ +-}; +- +-struct fman_dma_regs { +- u32 fmdmsr; /* FM DMA status register 0x00 */ +- u32 fmdmmr; /* FM DMA mode register 0x04 */ +- u32 fmdmtr; /* FM DMA bus threshold register 0x08 */ +- u32 fmdmhy; /* FM DMA bus hysteresis register 0x0c */ +- u32 fmdmsetr; /* FM DMA SOS emergency Threshold Register 0x10 */ +- u32 fmdmtah; /* FM DMA transfer bus address high reg 0x14 */ +- u32 fmdmtal; /* FM DMA transfer bus address low reg 0x18 */ +- u32 fmdmtcid; /* FM DMA transfer bus communication ID reg 0x1c */ +- u32 fmdmra; /* FM DMA bus internal ram address register 0x20 */ +- u32 fmdmrd; /* FM DMA bus internal ram data register 0x24 */ +- u32 fmdmwcr; /* FM DMA CAM watchdog counter value 0x28 */ +- u32 fmdmebcr; /* FM DMA CAM base in MURAM register 0x2c */ +- u32 fmdmccqdr; /* FM DMA CAM and CMD Queue Debug reg 0x30 */ +- u32 fmdmccqvr1; /* FM DMA CAM and CMD Queue Value reg #1 0x34 */ +- u32 fmdmccqvr2; /* FM DMA CAM and CMD Queue Value reg #2 0x38 */ +- u32 fmdmcqvr3; /* FM DMA CMD Queue Value register #3 0x3c */ +- u32 fmdmcqvr4; /* FM DMA CMD Queue Value register #4 0x40 */ +- u32 fmdmcqvr5; /* FM DMA CMD Queue Value register #5 0x44 */ +- u32 fmdmsefrc; /* FM DMA Semaphore Entry Full Reject Cntr 0x48 */ +- u32 fmdmsqfrc; /* FM DMA Semaphore Queue Full Reject Cntr 0x4c */ +- u32 fmdmssrc; /* FM DMA Semaphore SYNC Reject Counter 0x50 */ +- u32 fmdmdcr; /* FM DMA Debug Counter 0x54 */ +- u32 fmdmemsr; /* FM DMA Emergency Smoother Register 0x58 */ +- u32 res005c; /* 0x5c */ +- u32 fmdmplr[FMAN_LIODN_TBL / 2]; /* DMA LIODN regs 0x60-0xdf */ +- u32 res00e0[0x400 - 56]; +-}; +- +-/* Structure that holds current FMan state. +- * Used for saving run time information. +- */ +-struct fman_state_struct { +- u8 fm_id; +- u16 fm_clk_freq; +- struct fman_rev_info rev_info; +- bool enabled_time_stamp; +- u8 count1_micro_bit; +- u8 total_num_of_tasks; +- u8 accumulated_num_of_tasks; +- u32 accumulated_fifo_size; +- u8 accumulated_num_of_open_dmas; +- u8 accumulated_num_of_deq_tnums; +- u32 exceptions; +- u32 extra_fifo_pool_size; +- u8 extra_tasks_pool_size; +- u8 extra_open_dmas_pool_size; +- u16 port_mfl[MAX_NUM_OF_MACS]; +- u16 mac_mfl[MAX_NUM_OF_MACS]; +- +- /* SOC specific */ +- u32 fm_iram_size; +- /* DMA */ +- u32 dma_thresh_max_commq; +- u32 dma_thresh_max_buf; +- u32 max_num_of_open_dmas; +- /* QMI */ +- u32 qmi_max_num_of_tnums; +- u32 qmi_def_tnums_thresh; +- /* BMI */ +- u32 bmi_max_num_of_tasks; +- u32 bmi_max_fifo_size; +- /* General */ +- u32 fm_port_num_of_cg; +- u32 num_of_rx_ports; +- u32 total_fifo_size; +- +- u32 qman_channel_base; +- u32 num_of_qman_channels; +- +- struct resource *res; +-}; +- +-/* Structure that holds FMan initial configuration */ +-struct fman_cfg { +- u8 disp_limit_tsh; +- u8 prs_disp_tsh; +- u8 plcr_disp_tsh; +- u8 kg_disp_tsh; +- u8 bmi_disp_tsh; +- u8 qmi_enq_disp_tsh; +- u8 qmi_deq_disp_tsh; +- u8 fm_ctl1_disp_tsh; +- u8 fm_ctl2_disp_tsh; +- int dma_cache_override; +- enum fman_dma_aid_mode dma_aid_mode; +- u32 dma_axi_dbg_num_of_beats; +- u32 dma_cam_num_of_entries; +- u32 dma_watchdog; +- u8 dma_comm_qtsh_asrt_emer; +- u32 dma_write_buf_tsh_asrt_emer; +- u32 dma_read_buf_tsh_asrt_emer; +- u8 dma_comm_qtsh_clr_emer; +- u32 dma_write_buf_tsh_clr_emer; +- u32 dma_read_buf_tsh_clr_emer; +- u32 dma_sos_emergency; +- int dma_dbg_cnt_mode; +- int catastrophic_err; +- int dma_err; +- u32 exceptions; +- u16 clk_freq; +- u32 cam_base_addr; +- u32 fifo_base_addr; +- u32 total_fifo_size; +- u32 total_num_of_tasks; +- u32 qmi_def_tnums_thresh; +-}; +- +-/* Structure that holds information received from device tree */ +-struct fman_dts_params { +- void __iomem *base_addr; /* FMan virtual address */ +- struct resource *res; /* FMan memory resource */ +- u8 id; /* FMan ID */ +- +- int err_irq; /* FMan Error IRQ */ +- +- u16 clk_freq; /* FMan clock freq (In Mhz) */ +- +- u32 qman_channel_base; /* QMan channels base */ +- u32 num_of_qman_channels; /* Number of QMan channels */ +- +- struct resource muram_res; /* MURAM resource */ +-}; +- +-/** fman_exceptions_cb +- * fman - Pointer to FMan +- * exception - The exception. +- * +- * Exceptions user callback routine, will be called upon an exception +- * passing the exception identification. +- * +- * Return: irq status +- */ +-typedef irqreturn_t (fman_exceptions_cb)(struct fman *fman, +- enum fman_exceptions exception); +- +-/** fman_bus_error_cb +- * fman - Pointer to FMan +- * port_id - Port id +- * addr - Address that caused the error +- * tnum - Owner of error +- * liodn - Logical IO device number +- * +- * Bus error user callback routine, will be called upon bus error, +- * passing parameters describing the errors and the owner. +- * +- * Return: IRQ status +- */ +-typedef irqreturn_t (fman_bus_error_cb)(struct fman *fman, u8 port_id, +- u64 addr, u8 tnum, u16 liodn); +- +-struct fman { +- struct device *dev; +- void __iomem *base_addr; +- struct fman_intr_src intr_mng[FMAN_EV_CNT]; +- +- struct fman_fpm_regs __iomem *fpm_regs; +- struct fman_bmi_regs __iomem *bmi_regs; +- struct fman_qmi_regs __iomem *qmi_regs; +- struct fman_dma_regs __iomem *dma_regs; +- fman_exceptions_cb *exception_cb; +- fman_bus_error_cb *bus_error_cb; +- /* Spinlock for FMan use */ +- spinlock_t spinlock; +- struct fman_state_struct *state; +- +- struct fman_cfg *cfg; +- struct muram_info *muram; +- /* cam section in muram */ +- unsigned long cam_offset; +- size_t cam_size; +- /* Fifo in MURAM */ +- unsigned long fifo_offset; +- size_t fifo_size; +- +- u32 liodn_base[64]; +- u32 liodn_offset[64]; +- +- struct fman_dts_params dts_params; +-}; +- +-static irqreturn_t fman_exceptions(struct fman *fman, +- enum fman_exceptions exception) +-{ +- dev_dbg(fman->dev, "%s: FMan[%d] exception %d\n", +- __func__, fman->state->fm_id, exception); +- +- return IRQ_HANDLED; +-} +- +-static irqreturn_t fman_bus_error(struct fman *fman, u8 __maybe_unused port_id, +- u64 __maybe_unused addr, +- u8 __maybe_unused tnum, +- u16 __maybe_unused liodn) +-{ +- dev_dbg(fman->dev, "%s: FMan[%d] bus error: port_id[%d]\n", +- __func__, fman->state->fm_id, port_id); +- +- return IRQ_HANDLED; +-} +- +-static inline irqreturn_t call_mac_isr(struct fman *fman, u8 id) +-{ +- if (fman->intr_mng[id].isr_cb) { +- fman->intr_mng[id].isr_cb(fman->intr_mng[id].src_handle); +- +- return IRQ_HANDLED; +- } +- +- return IRQ_NONE; +-} +- +-static inline u8 hw_port_id_to_sw_port_id(u8 major, u8 hw_port_id) +-{ +- u8 sw_port_id = 0; +- +- if (hw_port_id >= BASE_TX_PORTID) +- sw_port_id = hw_port_id - BASE_TX_PORTID; +- else if (hw_port_id >= BASE_RX_PORTID) +- sw_port_id = hw_port_id - BASE_RX_PORTID; +- else +- sw_port_id = 0; +- +- return sw_port_id; +-} +- +-static void set_port_order_restoration(struct fman_fpm_regs __iomem *fpm_rg, +- u8 port_id) +-{ +- u32 tmp = 0; +- +- tmp = port_id << FPM_PORT_FM_CTL_PORTID_SHIFT; +- +- tmp |= FPM_PRT_FM_CTL2 | FPM_PRT_FM_CTL1; +- +- /* order restoration */ +- if (port_id % 2) +- tmp |= FPM_PRT_FM_CTL1 << FPM_PRC_ORA_FM_CTL_SEL_SHIFT; +- else +- tmp |= FPM_PRT_FM_CTL2 << FPM_PRC_ORA_FM_CTL_SEL_SHIFT; +- +- iowrite32be(tmp, &fpm_rg->fmfp_prc); +-} +- +-static void set_port_liodn(struct fman *fman, u8 port_id, +- u32 liodn_base, u32 liodn_ofst) +-{ +- u32 tmp; +- +- /* set LIODN base for this port */ +- tmp = ioread32be(&fman->dma_regs->fmdmplr[port_id / 2]); +- if (port_id % 2) { +- tmp &= ~DMA_LIODN_BASE_MASK; +- tmp |= liodn_base; +- } else { +- tmp &= ~(DMA_LIODN_BASE_MASK << DMA_LIODN_SHIFT); +- tmp |= liodn_base << DMA_LIODN_SHIFT; +- } +- iowrite32be(tmp, &fman->dma_regs->fmdmplr[port_id / 2]); +- iowrite32be(liodn_ofst, &fman->bmi_regs->fmbm_spliodn[port_id - 1]); +-} +- +-static void enable_rams_ecc(struct fman_fpm_regs __iomem *fpm_rg) +-{ +- u32 tmp; +- +- tmp = ioread32be(&fpm_rg->fm_rcr); +- if (tmp & FPM_RAM_RAMS_ECC_EN_SRC_SEL) +- iowrite32be(tmp | FPM_RAM_IRAM_ECC_EN, &fpm_rg->fm_rcr); +- else +- iowrite32be(tmp | FPM_RAM_RAMS_ECC_EN | +- FPM_RAM_IRAM_ECC_EN, &fpm_rg->fm_rcr); +-} +- +-static void disable_rams_ecc(struct fman_fpm_regs __iomem *fpm_rg) +-{ +- u32 tmp; +- +- tmp = ioread32be(&fpm_rg->fm_rcr); +- if (tmp & FPM_RAM_RAMS_ECC_EN_SRC_SEL) +- iowrite32be(tmp & ~FPM_RAM_IRAM_ECC_EN, &fpm_rg->fm_rcr); +- else +- iowrite32be(tmp & ~(FPM_RAM_RAMS_ECC_EN | FPM_RAM_IRAM_ECC_EN), +- &fpm_rg->fm_rcr); +-} +- +-static void fman_defconfig(struct fman_cfg *cfg) +-{ +- memset(cfg, 0, sizeof(struct fman_cfg)); +- +- cfg->catastrophic_err = DEFAULT_CATASTROPHIC_ERR; +- cfg->dma_err = DEFAULT_DMA_ERR; +- cfg->dma_aid_mode = DEFAULT_AID_MODE; +- cfg->dma_comm_qtsh_clr_emer = DEFAULT_DMA_COMM_Q_LOW; +- cfg->dma_comm_qtsh_asrt_emer = DEFAULT_DMA_COMM_Q_HIGH; +- cfg->dma_cache_override = DEFAULT_CACHE_OVERRIDE; +- cfg->dma_cam_num_of_entries = DEFAULT_DMA_CAM_NUM_OF_ENTRIES; +- cfg->dma_dbg_cnt_mode = DEFAULT_DMA_DBG_CNT_MODE; +- cfg->dma_sos_emergency = DEFAULT_DMA_SOS_EMERGENCY; +- cfg->dma_watchdog = DEFAULT_DMA_WATCHDOG; +- cfg->disp_limit_tsh = DEFAULT_DISP_LIMIT; +- cfg->prs_disp_tsh = DEFAULT_PRS_DISP_TH; +- cfg->plcr_disp_tsh = DEFAULT_PLCR_DISP_TH; +- cfg->kg_disp_tsh = DEFAULT_KG_DISP_TH; +- cfg->bmi_disp_tsh = DEFAULT_BMI_DISP_TH; +- cfg->qmi_enq_disp_tsh = DEFAULT_QMI_ENQ_DISP_TH; +- cfg->qmi_deq_disp_tsh = DEFAULT_QMI_DEQ_DISP_TH; +- cfg->fm_ctl1_disp_tsh = DEFAULT_FM_CTL1_DISP_TH; +- cfg->fm_ctl2_disp_tsh = DEFAULT_FM_CTL2_DISP_TH; +-} +- +-static int dma_init(struct fman *fman) +-{ +- struct fman_dma_regs __iomem *dma_rg = fman->dma_regs; +- struct fman_cfg *cfg = fman->cfg; +- u32 tmp_reg; +- +- /* Init DMA Registers */ +- +- /* clear status reg events */ +- tmp_reg = (DMA_STATUS_BUS_ERR | DMA_STATUS_READ_ECC | +- DMA_STATUS_SYSTEM_WRITE_ECC | DMA_STATUS_FM_WRITE_ECC); +- iowrite32be(ioread32be(&dma_rg->fmdmsr) | tmp_reg, &dma_rg->fmdmsr); +- +- /* configure mode register */ +- tmp_reg = 0; +- tmp_reg |= cfg->dma_cache_override << DMA_MODE_CACHE_OR_SHIFT; +- if (cfg->exceptions & EX_DMA_BUS_ERROR) +- tmp_reg |= DMA_MODE_BER; +- if ((cfg->exceptions & EX_DMA_SYSTEM_WRITE_ECC) | +- (cfg->exceptions & EX_DMA_READ_ECC) | +- (cfg->exceptions & EX_DMA_FM_WRITE_ECC)) +- tmp_reg |= DMA_MODE_ECC; +- if (cfg->dma_axi_dbg_num_of_beats) +- tmp_reg |= (DMA_MODE_AXI_DBG_MASK & +- ((cfg->dma_axi_dbg_num_of_beats - 1) +- << DMA_MODE_AXI_DBG_SHIFT)); +- +- tmp_reg |= (((cfg->dma_cam_num_of_entries / DMA_CAM_UNITS) - 1) & +- DMA_MODE_CEN_MASK) << DMA_MODE_CEN_SHIFT; +- tmp_reg |= DMA_MODE_SECURE_PROT; +- tmp_reg |= cfg->dma_dbg_cnt_mode << DMA_MODE_DBG_SHIFT; +- tmp_reg |= cfg->dma_aid_mode << DMA_MODE_AID_MODE_SHIFT; +- +- iowrite32be(tmp_reg, &dma_rg->fmdmmr); +- +- /* configure thresholds register */ +- tmp_reg = ((u32)cfg->dma_comm_qtsh_asrt_emer << +- DMA_THRESH_COMMQ_SHIFT); +- tmp_reg |= (cfg->dma_read_buf_tsh_asrt_emer & +- DMA_THRESH_READ_INT_BUF_MASK) << DMA_THRESH_READ_INT_BUF_SHIFT; +- tmp_reg |= cfg->dma_write_buf_tsh_asrt_emer & +- DMA_THRESH_WRITE_INT_BUF_MASK; +- +- iowrite32be(tmp_reg, &dma_rg->fmdmtr); +- +- /* configure hysteresis register */ +- tmp_reg = ((u32)cfg->dma_comm_qtsh_clr_emer << +- DMA_THRESH_COMMQ_SHIFT); +- tmp_reg |= (cfg->dma_read_buf_tsh_clr_emer & +- DMA_THRESH_READ_INT_BUF_MASK) << DMA_THRESH_READ_INT_BUF_SHIFT; +- tmp_reg |= cfg->dma_write_buf_tsh_clr_emer & +- DMA_THRESH_WRITE_INT_BUF_MASK; +- +- iowrite32be(tmp_reg, &dma_rg->fmdmhy); +- +- /* configure emergency threshold */ +- iowrite32be(cfg->dma_sos_emergency, &dma_rg->fmdmsetr); +- +- /* configure Watchdog */ +- iowrite32be((cfg->dma_watchdog * cfg->clk_freq), &dma_rg->fmdmwcr); +- +- iowrite32be(cfg->cam_base_addr, &dma_rg->fmdmebcr); +- +- /* Allocate MURAM for CAM */ +- fman->cam_size = +- (u32)(fman->cfg->dma_cam_num_of_entries * DMA_CAM_SIZEOF_ENTRY); +- fman->cam_offset = fman_muram_alloc(fman->muram, fman->cam_size); +- if (IS_ERR_VALUE(fman->cam_offset)) { +- dev_err(fman->dev, "%s: MURAM alloc for DMA CAM failed\n", +- __func__); +- return -ENOMEM; +- } +- +- if (fman->state->rev_info.major == 2) { +- u32 __iomem *cam_base_addr; +- +- fman_muram_free_mem(fman->muram, fman->cam_offset, +- fman->cam_size); +- +- fman->cam_size = fman->cfg->dma_cam_num_of_entries * 72 + 128; +- fman->cam_offset = fman_muram_alloc(fman->muram, +- fman->cam_size); +- if (IS_ERR_VALUE(fman->cam_offset)) { +- dev_err(fman->dev, "%s: MURAM alloc for DMA CAM failed\n", +- __func__); +- return -ENOMEM; +- } +- +- if (fman->cfg->dma_cam_num_of_entries % 8 || +- fman->cfg->dma_cam_num_of_entries > 32) { +- dev_err(fman->dev, "%s: wrong dma_cam_num_of_entries\n", +- __func__); +- return -EINVAL; +- } +- +- cam_base_addr = (u32 __iomem *) +- fman_muram_offset_to_vbase(fman->muram, +- fman->cam_offset); +- iowrite32be(~((1 << +- (32 - fman->cfg->dma_cam_num_of_entries)) - 1), +- cam_base_addr); +- } +- +- fman->cfg->cam_base_addr = fman->cam_offset; +- +- return 0; +-} +- +-static void fpm_init(struct fman_fpm_regs __iomem *fpm_rg, struct fman_cfg *cfg) +-{ +- u32 tmp_reg; +- int i; +- +- /* Init FPM Registers */ +- +- tmp_reg = (u32)(cfg->disp_limit_tsh << FPM_DISP_LIMIT_SHIFT); +- iowrite32be(tmp_reg, &fpm_rg->fmfp_mxd); +- +- tmp_reg = (((u32)cfg->prs_disp_tsh << FPM_THR1_PRS_SHIFT) | +- ((u32)cfg->kg_disp_tsh << FPM_THR1_KG_SHIFT) | +- ((u32)cfg->plcr_disp_tsh << FPM_THR1_PLCR_SHIFT) | +- ((u32)cfg->bmi_disp_tsh << FPM_THR1_BMI_SHIFT)); +- iowrite32be(tmp_reg, &fpm_rg->fmfp_dist1); +- +- tmp_reg = +- (((u32)cfg->qmi_enq_disp_tsh << FPM_THR2_QMI_ENQ_SHIFT) | +- ((u32)cfg->qmi_deq_disp_tsh << FPM_THR2_QMI_DEQ_SHIFT) | +- ((u32)cfg->fm_ctl1_disp_tsh << FPM_THR2_FM_CTL1_SHIFT) | +- ((u32)cfg->fm_ctl2_disp_tsh << FPM_THR2_FM_CTL2_SHIFT)); +- iowrite32be(tmp_reg, &fpm_rg->fmfp_dist2); +- +- /* define exceptions and error behavior */ +- tmp_reg = 0; +- /* Clear events */ +- tmp_reg |= (FPM_EV_MASK_STALL | FPM_EV_MASK_DOUBLE_ECC | +- FPM_EV_MASK_SINGLE_ECC); +- /* enable interrupts */ +- if (cfg->exceptions & EX_FPM_STALL_ON_TASKS) +- tmp_reg |= FPM_EV_MASK_STALL_EN; +- if (cfg->exceptions & EX_FPM_SINGLE_ECC) +- tmp_reg |= FPM_EV_MASK_SINGLE_ECC_EN; +- if (cfg->exceptions & EX_FPM_DOUBLE_ECC) +- tmp_reg |= FPM_EV_MASK_DOUBLE_ECC_EN; +- tmp_reg |= (cfg->catastrophic_err << FPM_EV_MASK_CAT_ERR_SHIFT); +- tmp_reg |= (cfg->dma_err << FPM_EV_MASK_DMA_ERR_SHIFT); +- /* FMan is not halted upon external halt activation */ +- tmp_reg |= FPM_EV_MASK_EXTERNAL_HALT; +- /* Man is not halted upon Unrecoverable ECC error behavior */ +- tmp_reg |= FPM_EV_MASK_ECC_ERR_HALT; +- iowrite32be(tmp_reg, &fpm_rg->fmfp_ee); +- +- /* clear all fmCtls event registers */ +- for (i = 0; i < FM_NUM_OF_FMAN_CTRL_EVENT_REGS; i++) +- iowrite32be(0xFFFFFFFF, &fpm_rg->fmfp_cev[i]); +- +- /* RAM ECC - enable and clear events */ +- /* first we need to clear all parser memory, +- * as it is uninitialized and may cause ECC errors +- */ +- /* event bits */ +- tmp_reg = (FPM_RAM_MURAM_ECC | FPM_RAM_IRAM_ECC); +- +- iowrite32be(tmp_reg, &fpm_rg->fm_rcr); +- +- tmp_reg = 0; +- if (cfg->exceptions & EX_IRAM_ECC) { +- tmp_reg |= FPM_IRAM_ECC_ERR_EX_EN; +- enable_rams_ecc(fpm_rg); +- } +- if (cfg->exceptions & EX_MURAM_ECC) { +- tmp_reg |= FPM_MURAM_ECC_ERR_EX_EN; +- enable_rams_ecc(fpm_rg); +- } +- iowrite32be(tmp_reg, &fpm_rg->fm_rie); +-} +- +-static void bmi_init(struct fman_bmi_regs __iomem *bmi_rg, +- struct fman_cfg *cfg) +-{ +- u32 tmp_reg; +- +- /* Init BMI Registers */ +- +- /* define common resources */ +- tmp_reg = cfg->fifo_base_addr; +- tmp_reg = tmp_reg / BMI_FIFO_ALIGN; +- +- tmp_reg |= ((cfg->total_fifo_size / FMAN_BMI_FIFO_UNITS - 1) << +- BMI_CFG1_FIFO_SIZE_SHIFT); +- iowrite32be(tmp_reg, &bmi_rg->fmbm_cfg1); +- +- tmp_reg = ((cfg->total_num_of_tasks - 1) & BMI_CFG2_TASKS_MASK) << +- BMI_CFG2_TASKS_SHIFT; +- /* num of DMA's will be dynamically updated when each port is set */ +- iowrite32be(tmp_reg, &bmi_rg->fmbm_cfg2); +- +- /* define unmaskable exceptions, enable and clear events */ +- tmp_reg = 0; +- iowrite32be(BMI_ERR_INTR_EN_LIST_RAM_ECC | +- BMI_ERR_INTR_EN_STORAGE_PROFILE_ECC | +- BMI_ERR_INTR_EN_STATISTICS_RAM_ECC | +- BMI_ERR_INTR_EN_DISPATCH_RAM_ECC, &bmi_rg->fmbm_ievr); +- +- if (cfg->exceptions & EX_BMI_LIST_RAM_ECC) +- tmp_reg |= BMI_ERR_INTR_EN_LIST_RAM_ECC; +- if (cfg->exceptions & EX_BMI_STORAGE_PROFILE_ECC) +- tmp_reg |= BMI_ERR_INTR_EN_STORAGE_PROFILE_ECC; +- if (cfg->exceptions & EX_BMI_STATISTICS_RAM_ECC) +- tmp_reg |= BMI_ERR_INTR_EN_STATISTICS_RAM_ECC; +- if (cfg->exceptions & EX_BMI_DISPATCH_RAM_ECC) +- tmp_reg |= BMI_ERR_INTR_EN_DISPATCH_RAM_ECC; +- iowrite32be(tmp_reg, &bmi_rg->fmbm_ier); +-} +- +-static void qmi_init(struct fman_qmi_regs __iomem *qmi_rg, +- struct fman_cfg *cfg) +-{ +- u32 tmp_reg; +- +- /* Init QMI Registers */ +- +- /* Clear error interrupt events */ +- +- iowrite32be(QMI_ERR_INTR_EN_DOUBLE_ECC | QMI_ERR_INTR_EN_DEQ_FROM_DEF, +- &qmi_rg->fmqm_eie); +- tmp_reg = 0; +- if (cfg->exceptions & EX_QMI_DEQ_FROM_UNKNOWN_PORTID) +- tmp_reg |= QMI_ERR_INTR_EN_DEQ_FROM_DEF; +- if (cfg->exceptions & EX_QMI_DOUBLE_ECC) +- tmp_reg |= QMI_ERR_INTR_EN_DOUBLE_ECC; +- /* enable events */ +- iowrite32be(tmp_reg, &qmi_rg->fmqm_eien); +- +- tmp_reg = 0; +- /* Clear interrupt events */ +- iowrite32be(QMI_INTR_EN_SINGLE_ECC, &qmi_rg->fmqm_ie); +- if (cfg->exceptions & EX_QMI_SINGLE_ECC) +- tmp_reg |= QMI_INTR_EN_SINGLE_ECC; +- /* enable events */ +- iowrite32be(tmp_reg, &qmi_rg->fmqm_ien); +-} +- +-static int enable(struct fman *fman, struct fman_cfg *cfg) +-{ +- u32 cfg_reg = 0; +- +- /* Enable all modules */ +- +- /* clear&enable global counters - calculate reg and save for later, +- * because it's the same reg for QMI enable +- */ +- cfg_reg = QMI_CFG_EN_COUNTERS; +- +- /* Set enqueue and dequeue thresholds */ +- cfg_reg |= (cfg->qmi_def_tnums_thresh << 8) | cfg->qmi_def_tnums_thresh; +- +- iowrite32be(BMI_INIT_START, &fman->bmi_regs->fmbm_init); +- iowrite32be(cfg_reg | QMI_CFG_ENQ_EN | QMI_CFG_DEQ_EN, +- &fman->qmi_regs->fmqm_gc); +- +- return 0; +-} +- +-static int set_exception(struct fman *fman, +- enum fman_exceptions exception, bool enable) +-{ +- u32 tmp; +- +- switch (exception) { +- case FMAN_EX_DMA_BUS_ERROR: +- tmp = ioread32be(&fman->dma_regs->fmdmmr); +- if (enable) +- tmp |= DMA_MODE_BER; +- else +- tmp &= ~DMA_MODE_BER; +- /* disable bus error */ +- iowrite32be(tmp, &fman->dma_regs->fmdmmr); +- break; +- case FMAN_EX_DMA_READ_ECC: +- case FMAN_EX_DMA_SYSTEM_WRITE_ECC: +- case FMAN_EX_DMA_FM_WRITE_ECC: +- tmp = ioread32be(&fman->dma_regs->fmdmmr); +- if (enable) +- tmp |= DMA_MODE_ECC; +- else +- tmp &= ~DMA_MODE_ECC; +- iowrite32be(tmp, &fman->dma_regs->fmdmmr); +- break; +- case FMAN_EX_FPM_STALL_ON_TASKS: +- tmp = ioread32be(&fman->fpm_regs->fmfp_ee); +- if (enable) +- tmp |= FPM_EV_MASK_STALL_EN; +- else +- tmp &= ~FPM_EV_MASK_STALL_EN; +- iowrite32be(tmp, &fman->fpm_regs->fmfp_ee); +- break; +- case FMAN_EX_FPM_SINGLE_ECC: +- tmp = ioread32be(&fman->fpm_regs->fmfp_ee); +- if (enable) +- tmp |= FPM_EV_MASK_SINGLE_ECC_EN; +- else +- tmp &= ~FPM_EV_MASK_SINGLE_ECC_EN; +- iowrite32be(tmp, &fman->fpm_regs->fmfp_ee); +- break; +- case FMAN_EX_FPM_DOUBLE_ECC: +- tmp = ioread32be(&fman->fpm_regs->fmfp_ee); +- if (enable) +- tmp |= FPM_EV_MASK_DOUBLE_ECC_EN; +- else +- tmp &= ~FPM_EV_MASK_DOUBLE_ECC_EN; +- iowrite32be(tmp, &fman->fpm_regs->fmfp_ee); +- break; +- case FMAN_EX_QMI_SINGLE_ECC: +- tmp = ioread32be(&fman->qmi_regs->fmqm_ien); +- if (enable) +- tmp |= QMI_INTR_EN_SINGLE_ECC; +- else +- tmp &= ~QMI_INTR_EN_SINGLE_ECC; +- iowrite32be(tmp, &fman->qmi_regs->fmqm_ien); +- break; +- case FMAN_EX_QMI_DOUBLE_ECC: +- tmp = ioread32be(&fman->qmi_regs->fmqm_eien); +- if (enable) +- tmp |= QMI_ERR_INTR_EN_DOUBLE_ECC; +- else +- tmp &= ~QMI_ERR_INTR_EN_DOUBLE_ECC; +- iowrite32be(tmp, &fman->qmi_regs->fmqm_eien); +- break; +- case FMAN_EX_QMI_DEQ_FROM_UNKNOWN_PORTID: +- tmp = ioread32be(&fman->qmi_regs->fmqm_eien); +- if (enable) +- tmp |= QMI_ERR_INTR_EN_DEQ_FROM_DEF; +- else +- tmp &= ~QMI_ERR_INTR_EN_DEQ_FROM_DEF; +- iowrite32be(tmp, &fman->qmi_regs->fmqm_eien); +- break; +- case FMAN_EX_BMI_LIST_RAM_ECC: +- tmp = ioread32be(&fman->bmi_regs->fmbm_ier); +- if (enable) +- tmp |= BMI_ERR_INTR_EN_LIST_RAM_ECC; +- else +- tmp &= ~BMI_ERR_INTR_EN_LIST_RAM_ECC; +- iowrite32be(tmp, &fman->bmi_regs->fmbm_ier); +- break; +- case FMAN_EX_BMI_STORAGE_PROFILE_ECC: +- tmp = ioread32be(&fman->bmi_regs->fmbm_ier); +- if (enable) +- tmp |= BMI_ERR_INTR_EN_STORAGE_PROFILE_ECC; +- else +- tmp &= ~BMI_ERR_INTR_EN_STORAGE_PROFILE_ECC; +- iowrite32be(tmp, &fman->bmi_regs->fmbm_ier); +- break; +- case FMAN_EX_BMI_STATISTICS_RAM_ECC: +- tmp = ioread32be(&fman->bmi_regs->fmbm_ier); +- if (enable) +- tmp |= BMI_ERR_INTR_EN_STATISTICS_RAM_ECC; +- else +- tmp &= ~BMI_ERR_INTR_EN_STATISTICS_RAM_ECC; +- iowrite32be(tmp, &fman->bmi_regs->fmbm_ier); +- break; +- case FMAN_EX_BMI_DISPATCH_RAM_ECC: +- tmp = ioread32be(&fman->bmi_regs->fmbm_ier); +- if (enable) +- tmp |= BMI_ERR_INTR_EN_DISPATCH_RAM_ECC; +- else +- tmp &= ~BMI_ERR_INTR_EN_DISPATCH_RAM_ECC; +- iowrite32be(tmp, &fman->bmi_regs->fmbm_ier); +- break; +- case FMAN_EX_IRAM_ECC: +- tmp = ioread32be(&fman->fpm_regs->fm_rie); +- if (enable) { +- /* enable ECC if not enabled */ +- enable_rams_ecc(fman->fpm_regs); +- /* enable ECC interrupts */ +- tmp |= FPM_IRAM_ECC_ERR_EX_EN; +- } else { +- /* ECC mechanism may be disabled, +- * depending on driver status +- */ +- disable_rams_ecc(fman->fpm_regs); +- tmp &= ~FPM_IRAM_ECC_ERR_EX_EN; +- } +- iowrite32be(tmp, &fman->fpm_regs->fm_rie); +- break; +- case FMAN_EX_MURAM_ECC: +- tmp = ioread32be(&fman->fpm_regs->fm_rie); +- if (enable) { +- /* enable ECC if not enabled */ +- enable_rams_ecc(fman->fpm_regs); +- /* enable ECC interrupts */ +- tmp |= FPM_MURAM_ECC_ERR_EX_EN; +- } else { +- /* ECC mechanism may be disabled, +- * depending on driver status +- */ +- disable_rams_ecc(fman->fpm_regs); +- tmp &= ~FPM_MURAM_ECC_ERR_EX_EN; +- } +- iowrite32be(tmp, &fman->fpm_regs->fm_rie); +- break; +- default: +- return -EINVAL; +- } +- return 0; +-} +- +-static void resume(struct fman_fpm_regs __iomem *fpm_rg) +-{ +- u32 tmp; +- +- tmp = ioread32be(&fpm_rg->fmfp_ee); +- /* clear tmp_reg event bits in order not to clear standing events */ +- tmp &= ~(FPM_EV_MASK_DOUBLE_ECC | +- FPM_EV_MASK_STALL | FPM_EV_MASK_SINGLE_ECC); +- tmp |= FPM_EV_MASK_RELEASE_FM; +- +- iowrite32be(tmp, &fpm_rg->fmfp_ee); +-} +- +-static int fill_soc_specific_params(struct fman_state_struct *state) +-{ +- u8 minor = state->rev_info.minor; +- /* P4080 - Major 2 +- * P2041/P3041/P5020/P5040 - Major 3 +- * Tx/Bx - Major 6 +- */ +- switch (state->rev_info.major) { +- case 3: +- state->bmi_max_fifo_size = 160 * 1024; +- state->fm_iram_size = 64 * 1024; +- state->dma_thresh_max_commq = 31; +- state->dma_thresh_max_buf = 127; +- state->qmi_max_num_of_tnums = 64; +- state->qmi_def_tnums_thresh = 48; +- state->bmi_max_num_of_tasks = 128; +- state->max_num_of_open_dmas = 32; +- state->fm_port_num_of_cg = 256; +- state->num_of_rx_ports = 6; +- state->total_fifo_size = 122 * 1024; +- break; +- +- case 2: +- state->bmi_max_fifo_size = 160 * 1024; +- state->fm_iram_size = 64 * 1024; +- state->dma_thresh_max_commq = 31; +- state->dma_thresh_max_buf = 127; +- state->qmi_max_num_of_tnums = 64; +- state->qmi_def_tnums_thresh = 48; +- state->bmi_max_num_of_tasks = 128; +- state->max_num_of_open_dmas = 32; +- state->fm_port_num_of_cg = 256; +- state->num_of_rx_ports = 5; +- state->total_fifo_size = 100 * 1024; +- break; +- +- case 6: +- state->dma_thresh_max_commq = 83; +- state->dma_thresh_max_buf = 127; +- state->qmi_max_num_of_tnums = 64; +- state->qmi_def_tnums_thresh = 32; +- state->fm_port_num_of_cg = 256; +- +- /* FManV3L */ +- if (minor == 1 || minor == 4) { +- state->bmi_max_fifo_size = 192 * 1024; +- state->bmi_max_num_of_tasks = 64; +- state->max_num_of_open_dmas = 32; +- state->num_of_rx_ports = 5; +- if (minor == 1) +- state->fm_iram_size = 32 * 1024; +- else +- state->fm_iram_size = 64 * 1024; +- state->total_fifo_size = 156 * 1024; +- } +- /* FManV3H */ +- else if (minor == 0 || minor == 2 || minor == 3) { +- state->bmi_max_fifo_size = 384 * 1024; +- state->fm_iram_size = 64 * 1024; +- state->bmi_max_num_of_tasks = 128; +- state->max_num_of_open_dmas = 84; +- state->num_of_rx_ports = 8; +- state->total_fifo_size = 295 * 1024; +- } else { +- pr_err("Unsupported FManv3 version\n"); +- return -EINVAL; +- } +- +- break; +- default: +- pr_err("Unsupported FMan version\n"); +- return -EINVAL; +- } +- +- return 0; +-} +- +-static bool is_init_done(struct fman_cfg *cfg) +-{ +- /* Checks if FMan driver parameters were initialized */ +- if (!cfg) +- return true; +- +- return false; +-} +- +-static void free_init_resources(struct fman *fman) +-{ +- if (fman->cam_offset) +- fman_muram_free_mem(fman->muram, fman->cam_offset, +- fman->cam_size); +- if (fman->fifo_offset) +- fman_muram_free_mem(fman->muram, fman->fifo_offset, +- fman->fifo_size); +-} +- +-static irqreturn_t bmi_err_event(struct fman *fman) +-{ +- u32 event, mask, force; +- struct fman_bmi_regs __iomem *bmi_rg = fman->bmi_regs; +- irqreturn_t ret = IRQ_NONE; +- +- event = ioread32be(&bmi_rg->fmbm_ievr); +- mask = ioread32be(&bmi_rg->fmbm_ier); +- event &= mask; +- /* clear the forced events */ +- force = ioread32be(&bmi_rg->fmbm_ifr); +- if (force & event) +- iowrite32be(force & ~event, &bmi_rg->fmbm_ifr); +- /* clear the acknowledged events */ +- iowrite32be(event, &bmi_rg->fmbm_ievr); +- +- if (event & BMI_ERR_INTR_EN_STORAGE_PROFILE_ECC) +- ret = fman->exception_cb(fman, FMAN_EX_BMI_STORAGE_PROFILE_ECC); +- if (event & BMI_ERR_INTR_EN_LIST_RAM_ECC) +- ret = fman->exception_cb(fman, FMAN_EX_BMI_LIST_RAM_ECC); +- if (event & BMI_ERR_INTR_EN_STATISTICS_RAM_ECC) +- ret = fman->exception_cb(fman, FMAN_EX_BMI_STATISTICS_RAM_ECC); +- if (event & BMI_ERR_INTR_EN_DISPATCH_RAM_ECC) +- ret = fman->exception_cb(fman, FMAN_EX_BMI_DISPATCH_RAM_ECC); +- +- return ret; +-} +- +-static irqreturn_t qmi_err_event(struct fman *fman) +-{ +- u32 event, mask, force; +- struct fman_qmi_regs __iomem *qmi_rg = fman->qmi_regs; +- irqreturn_t ret = IRQ_NONE; +- +- event = ioread32be(&qmi_rg->fmqm_eie); +- mask = ioread32be(&qmi_rg->fmqm_eien); +- event &= mask; +- +- /* clear the forced events */ +- force = ioread32be(&qmi_rg->fmqm_eif); +- if (force & event) +- iowrite32be(force & ~event, &qmi_rg->fmqm_eif); +- /* clear the acknowledged events */ +- iowrite32be(event, &qmi_rg->fmqm_eie); +- +- if (event & QMI_ERR_INTR_EN_DOUBLE_ECC) +- ret = fman->exception_cb(fman, FMAN_EX_QMI_DOUBLE_ECC); +- if (event & QMI_ERR_INTR_EN_DEQ_FROM_DEF) +- ret = fman->exception_cb(fman, +- FMAN_EX_QMI_DEQ_FROM_UNKNOWN_PORTID); +- +- return ret; +-} +- +-static irqreturn_t dma_err_event(struct fman *fman) +-{ +- u32 status, mask, com_id; +- u8 tnum, port_id, relative_port_id; +- u16 liodn; +- struct fman_dma_regs __iomem *dma_rg = fman->dma_regs; +- irqreturn_t ret = IRQ_NONE; +- +- status = ioread32be(&dma_rg->fmdmsr); +- mask = ioread32be(&dma_rg->fmdmmr); +- +- /* clear DMA_STATUS_BUS_ERR if mask has no DMA_MODE_BER */ +- if ((mask & DMA_MODE_BER) != DMA_MODE_BER) +- status &= ~DMA_STATUS_BUS_ERR; +- +- /* clear relevant bits if mask has no DMA_MODE_ECC */ +- if ((mask & DMA_MODE_ECC) != DMA_MODE_ECC) +- status &= ~(DMA_STATUS_FM_SPDAT_ECC | +- DMA_STATUS_READ_ECC | +- DMA_STATUS_SYSTEM_WRITE_ECC | +- DMA_STATUS_FM_WRITE_ECC); +- +- /* clear set events */ +- iowrite32be(status, &dma_rg->fmdmsr); +- +- if (status & DMA_STATUS_BUS_ERR) { +- u64 addr; +- +- addr = (u64)ioread32be(&dma_rg->fmdmtal); +- addr |= ((u64)(ioread32be(&dma_rg->fmdmtah)) << 32); +- +- com_id = ioread32be(&dma_rg->fmdmtcid); +- port_id = (u8)(((com_id & DMA_TRANSFER_PORTID_MASK) >> +- DMA_TRANSFER_PORTID_SHIFT)); +- relative_port_id = +- hw_port_id_to_sw_port_id(fman->state->rev_info.major, port_id); +- tnum = (u8)((com_id & DMA_TRANSFER_TNUM_MASK) >> +- DMA_TRANSFER_TNUM_SHIFT); +- liodn = (u16)(com_id & DMA_TRANSFER_LIODN_MASK); +- ret = fman->bus_error_cb(fman, relative_port_id, addr, tnum, +- liodn); +- } +- if (status & DMA_STATUS_FM_SPDAT_ECC) +- ret = fman->exception_cb(fman, FMAN_EX_DMA_SINGLE_PORT_ECC); +- if (status & DMA_STATUS_READ_ECC) +- ret = fman->exception_cb(fman, FMAN_EX_DMA_READ_ECC); +- if (status & DMA_STATUS_SYSTEM_WRITE_ECC) +- ret = fman->exception_cb(fman, FMAN_EX_DMA_SYSTEM_WRITE_ECC); +- if (status & DMA_STATUS_FM_WRITE_ECC) +- ret = fman->exception_cb(fman, FMAN_EX_DMA_FM_WRITE_ECC); +- +- return ret; +-} +- +-static irqreturn_t fpm_err_event(struct fman *fman) +-{ +- u32 event; +- struct fman_fpm_regs __iomem *fpm_rg = fman->fpm_regs; +- irqreturn_t ret = IRQ_NONE; +- +- event = ioread32be(&fpm_rg->fmfp_ee); +- /* clear the all occurred events */ +- iowrite32be(event, &fpm_rg->fmfp_ee); +- +- if ((event & FPM_EV_MASK_DOUBLE_ECC) && +- (event & FPM_EV_MASK_DOUBLE_ECC_EN)) +- ret = fman->exception_cb(fman, FMAN_EX_FPM_DOUBLE_ECC); +- if ((event & FPM_EV_MASK_STALL) && (event & FPM_EV_MASK_STALL_EN)) +- ret = fman->exception_cb(fman, FMAN_EX_FPM_STALL_ON_TASKS); +- if ((event & FPM_EV_MASK_SINGLE_ECC) && +- (event & FPM_EV_MASK_SINGLE_ECC_EN)) +- ret = fman->exception_cb(fman, FMAN_EX_FPM_SINGLE_ECC); +- +- return ret; +-} +- +-static irqreturn_t muram_err_intr(struct fman *fman) +-{ +- u32 event, mask; +- struct fman_fpm_regs __iomem *fpm_rg = fman->fpm_regs; +- irqreturn_t ret = IRQ_NONE; +- +- event = ioread32be(&fpm_rg->fm_rcr); +- mask = ioread32be(&fpm_rg->fm_rie); +- +- /* clear MURAM event bit (do not clear IRAM event) */ +- iowrite32be(event & ~FPM_RAM_IRAM_ECC, &fpm_rg->fm_rcr); +- +- if ((mask & FPM_MURAM_ECC_ERR_EX_EN) && (event & FPM_RAM_MURAM_ECC)) +- ret = fman->exception_cb(fman, FMAN_EX_MURAM_ECC); +- +- return ret; +-} +- +-static irqreturn_t qmi_event(struct fman *fman) +-{ +- u32 event, mask, force; +- struct fman_qmi_regs __iomem *qmi_rg = fman->qmi_regs; +- irqreturn_t ret = IRQ_NONE; +- +- event = ioread32be(&qmi_rg->fmqm_ie); +- mask = ioread32be(&qmi_rg->fmqm_ien); +- event &= mask; +- /* clear the forced events */ +- force = ioread32be(&qmi_rg->fmqm_if); +- if (force & event) +- iowrite32be(force & ~event, &qmi_rg->fmqm_if); +- /* clear the acknowledged events */ +- iowrite32be(event, &qmi_rg->fmqm_ie); +- +- if (event & QMI_INTR_EN_SINGLE_ECC) +- ret = fman->exception_cb(fman, FMAN_EX_QMI_SINGLE_ECC); +- +- return ret; +-} +- +-static void enable_time_stamp(struct fman *fman) +-{ +- struct fman_fpm_regs __iomem *fpm_rg = fman->fpm_regs; +- u16 fm_clk_freq = fman->state->fm_clk_freq; +- u32 tmp, intgr, ts_freq; +- u64 frac; +- +- ts_freq = (u32)(1 << fman->state->count1_micro_bit); +- /* configure timestamp so that bit 8 will count 1 microsecond +- * Find effective count rate at TIMESTAMP least significant bits: +- * Effective_Count_Rate = 1MHz x 2^8 = 256MHz +- * Find frequency ratio between effective count rate and the clock: +- * Effective_Count_Rate / CLK e.g. for 600 MHz clock: +- * 256/600 = 0.4266666... +- */ +- +- intgr = ts_freq / fm_clk_freq; +- /* we multiply by 2^16 to keep the fraction of the division +- * we do not div back, since we write this value as a fraction +- * see spec +- */ +- +- frac = ((ts_freq << 16) - (intgr << 16) * fm_clk_freq) / fm_clk_freq; +- /* we check remainder of the division in order to round up if not int */ +- if (((ts_freq << 16) - (intgr << 16) * fm_clk_freq) % fm_clk_freq) +- frac++; +- +- tmp = (intgr << FPM_TS_INT_SHIFT) | (u16)frac; +- iowrite32be(tmp, &fpm_rg->fmfp_tsc2); +- +- /* enable timestamp with original clock */ +- iowrite32be(FPM_TS_CTL_EN, &fpm_rg->fmfp_tsc1); +- fman->state->enabled_time_stamp = true; +-} +- +-static int clear_iram(struct fman *fman) +-{ +- struct fman_iram_regs __iomem *iram; +- int i, count; +- +- iram = fman->base_addr + IMEM_OFFSET; +- +- /* Enable the auto-increment */ +- iowrite32be(IRAM_IADD_AIE, &iram->iadd); +- count = 100; +- do { +- udelay(1); +- } while ((ioread32be(&iram->iadd) != IRAM_IADD_AIE) && --count); +- if (count == 0) +- return -EBUSY; +- +- for (i = 0; i < (fman->state->fm_iram_size / 4); i++) +- iowrite32be(0xffffffff, &iram->idata); +- +- iowrite32be(fman->state->fm_iram_size - 4, &iram->iadd); +- count = 100; +- do { +- udelay(1); +- } while ((ioread32be(&iram->idata) != 0xffffffff) && --count); +- if (count == 0) +- return -EBUSY; +- +- return 0; +-} +- +-static u32 get_exception_flag(enum fman_exceptions exception) +-{ +- u32 bit_mask; +- +- switch (exception) { +- case FMAN_EX_DMA_BUS_ERROR: +- bit_mask = EX_DMA_BUS_ERROR; +- break; +- case FMAN_EX_DMA_SINGLE_PORT_ECC: +- bit_mask = EX_DMA_SINGLE_PORT_ECC; +- break; +- case FMAN_EX_DMA_READ_ECC: +- bit_mask = EX_DMA_READ_ECC; +- break; +- case FMAN_EX_DMA_SYSTEM_WRITE_ECC: +- bit_mask = EX_DMA_SYSTEM_WRITE_ECC; +- break; +- case FMAN_EX_DMA_FM_WRITE_ECC: +- bit_mask = EX_DMA_FM_WRITE_ECC; +- break; +- case FMAN_EX_FPM_STALL_ON_TASKS: +- bit_mask = EX_FPM_STALL_ON_TASKS; +- break; +- case FMAN_EX_FPM_SINGLE_ECC: +- bit_mask = EX_FPM_SINGLE_ECC; +- break; +- case FMAN_EX_FPM_DOUBLE_ECC: +- bit_mask = EX_FPM_DOUBLE_ECC; +- break; +- case FMAN_EX_QMI_SINGLE_ECC: +- bit_mask = EX_QMI_SINGLE_ECC; +- break; +- case FMAN_EX_QMI_DOUBLE_ECC: +- bit_mask = EX_QMI_DOUBLE_ECC; +- break; +- case FMAN_EX_QMI_DEQ_FROM_UNKNOWN_PORTID: +- bit_mask = EX_QMI_DEQ_FROM_UNKNOWN_PORTID; +- break; +- case FMAN_EX_BMI_LIST_RAM_ECC: +- bit_mask = EX_BMI_LIST_RAM_ECC; +- break; +- case FMAN_EX_BMI_STORAGE_PROFILE_ECC: +- bit_mask = EX_BMI_STORAGE_PROFILE_ECC; +- break; +- case FMAN_EX_BMI_STATISTICS_RAM_ECC: +- bit_mask = EX_BMI_STATISTICS_RAM_ECC; +- break; +- case FMAN_EX_BMI_DISPATCH_RAM_ECC: +- bit_mask = EX_BMI_DISPATCH_RAM_ECC; +- break; +- case FMAN_EX_MURAM_ECC: +- bit_mask = EX_MURAM_ECC; +- break; +- default: +- bit_mask = 0; +- break; +- } +- +- return bit_mask; +-} +- +-static int get_module_event(enum fman_event_modules module, u8 mod_id, +- enum fman_intr_type intr_type) +-{ +- int event; +- +- switch (module) { +- case FMAN_MOD_MAC: +- if (intr_type == FMAN_INTR_TYPE_ERR) +- event = FMAN_EV_ERR_MAC0 + mod_id; +- else +- event = FMAN_EV_MAC0 + mod_id; +- break; +- case FMAN_MOD_FMAN_CTRL: +- if (intr_type == FMAN_INTR_TYPE_ERR) +- event = FMAN_EV_CNT; +- else +- event = (FMAN_EV_FMAN_CTRL_0 + mod_id); +- break; +- case FMAN_MOD_DUMMY_LAST: +- event = FMAN_EV_CNT; +- break; +- default: +- event = FMAN_EV_CNT; +- break; +- } +- +- return event; +-} +- +-static int set_size_of_fifo(struct fman *fman, u8 port_id, u32 *size_of_fifo, +- u32 *extra_size_of_fifo) +-{ +- struct fman_bmi_regs __iomem *bmi_rg = fman->bmi_regs; +- u32 fifo = *size_of_fifo; +- u32 extra_fifo = *extra_size_of_fifo; +- u32 tmp; +- +- /* if this is the first time a port requires extra_fifo_pool_size, +- * the total extra_fifo_pool_size must be initialized to 1 buffer per +- * port +- */ +- if (extra_fifo && !fman->state->extra_fifo_pool_size) +- fman->state->extra_fifo_pool_size = +- fman->state->num_of_rx_ports * FMAN_BMI_FIFO_UNITS; +- +- fman->state->extra_fifo_pool_size = +- max(fman->state->extra_fifo_pool_size, extra_fifo); +- +- /* check that there are enough uncommitted fifo size */ +- if ((fman->state->accumulated_fifo_size + fifo) > +- (fman->state->total_fifo_size - +- fman->state->extra_fifo_pool_size)) { +- dev_err(fman->dev, "%s: Requested fifo size and extra size exceed total FIFO size.\n", +- __func__); +- return -EAGAIN; +- } +- +- /* Read, modify and write to HW */ +- tmp = (fifo / FMAN_BMI_FIFO_UNITS - 1) | +- ((extra_fifo / FMAN_BMI_FIFO_UNITS) << +- BMI_EXTRA_FIFO_SIZE_SHIFT); +- iowrite32be(tmp, &bmi_rg->fmbm_pfs[port_id - 1]); +- +- /* update accumulated */ +- fman->state->accumulated_fifo_size += fifo; +- +- return 0; +-} +- +-static int set_num_of_tasks(struct fman *fman, u8 port_id, u8 *num_of_tasks, +- u8 *num_of_extra_tasks) +-{ +- struct fman_bmi_regs __iomem *bmi_rg = fman->bmi_regs; +- u8 tasks = *num_of_tasks; +- u8 extra_tasks = *num_of_extra_tasks; +- u32 tmp; +- +- if (extra_tasks) +- fman->state->extra_tasks_pool_size = +- max(fman->state->extra_tasks_pool_size, extra_tasks); +- +- /* check that there are enough uncommitted tasks */ +- if ((fman->state->accumulated_num_of_tasks + tasks) > +- (fman->state->total_num_of_tasks - +- fman->state->extra_tasks_pool_size)) { +- dev_err(fman->dev, "%s: Requested num_of_tasks and extra tasks pool for fm%d exceed total num_of_tasks.\n", +- __func__, fman->state->fm_id); +- return -EAGAIN; +- } +- /* update accumulated */ +- fman->state->accumulated_num_of_tasks += tasks; +- +- /* Write to HW */ +- tmp = ioread32be(&bmi_rg->fmbm_pp[port_id - 1]) & +- ~(BMI_NUM_OF_TASKS_MASK | BMI_NUM_OF_EXTRA_TASKS_MASK); +- tmp |= ((u32)((tasks - 1) << BMI_NUM_OF_TASKS_SHIFT) | +- (u32)(extra_tasks << BMI_EXTRA_NUM_OF_TASKS_SHIFT)); +- iowrite32be(tmp, &bmi_rg->fmbm_pp[port_id - 1]); +- +- return 0; +-} +- +-static int set_num_of_open_dmas(struct fman *fman, u8 port_id, +- u8 *num_of_open_dmas, +- u8 *num_of_extra_open_dmas) +-{ +- struct fman_bmi_regs __iomem *bmi_rg = fman->bmi_regs; +- u8 open_dmas = *num_of_open_dmas; +- u8 extra_open_dmas = *num_of_extra_open_dmas; +- u8 total_num_dmas = 0, current_val = 0, current_extra_val = 0; +- u32 tmp; +- +- if (!open_dmas) { +- /* Configuration according to values in the HW. +- * read the current number of open Dma's +- */ +- tmp = ioread32be(&bmi_rg->fmbm_pp[port_id - 1]); +- current_extra_val = (u8)((tmp & BMI_NUM_OF_EXTRA_DMAS_MASK) >> +- BMI_EXTRA_NUM_OF_DMAS_SHIFT); +- +- tmp = ioread32be(&bmi_rg->fmbm_pp[port_id - 1]); +- current_val = (u8)(((tmp & BMI_NUM_OF_DMAS_MASK) >> +- BMI_NUM_OF_DMAS_SHIFT) + 1); +- +- /* This is the first configuration and user did not +- * specify value (!open_dmas), reset values will be used +- * and we just save these values for resource management +- */ +- fman->state->extra_open_dmas_pool_size = +- (u8)max(fman->state->extra_open_dmas_pool_size, +- current_extra_val); +- fman->state->accumulated_num_of_open_dmas += current_val; +- *num_of_open_dmas = current_val; +- *num_of_extra_open_dmas = current_extra_val; +- return 0; +- } +- +- if (extra_open_dmas > current_extra_val) +- fman->state->extra_open_dmas_pool_size = +- (u8)max(fman->state->extra_open_dmas_pool_size, +- extra_open_dmas); +- +- if ((fman->state->rev_info.major < 6) && +- (fman->state->accumulated_num_of_open_dmas - current_val + +- open_dmas > fman->state->max_num_of_open_dmas)) { +- dev_err(fman->dev, "%s: Requested num_of_open_dmas for fm%d exceeds total num_of_open_dmas.\n", +- __func__, fman->state->fm_id); +- return -EAGAIN; +- } else if ((fman->state->rev_info.major >= 6) && +- !((fman->state->rev_info.major == 6) && +- (fman->state->rev_info.minor == 0)) && +- (fman->state->accumulated_num_of_open_dmas - +- current_val + open_dmas > +- fman->state->dma_thresh_max_commq + 1)) { +- dev_err(fman->dev, "%s: Requested num_of_open_dmas for fm%d exceeds DMA Command queue (%d)\n", +- __func__, fman->state->fm_id, +- fman->state->dma_thresh_max_commq + 1); +- return -EAGAIN; +- } +- +- WARN_ON(fman->state->accumulated_num_of_open_dmas < current_val); +- /* update acummulated */ +- fman->state->accumulated_num_of_open_dmas -= current_val; +- fman->state->accumulated_num_of_open_dmas += open_dmas; +- +- if (fman->state->rev_info.major < 6) +- total_num_dmas = +- (u8)(fman->state->accumulated_num_of_open_dmas + +- fman->state->extra_open_dmas_pool_size); +- +- /* calculate reg */ +- tmp = ioread32be(&bmi_rg->fmbm_pp[port_id - 1]) & +- ~(BMI_NUM_OF_DMAS_MASK | BMI_NUM_OF_EXTRA_DMAS_MASK); +- tmp |= (u32)(((open_dmas - 1) << BMI_NUM_OF_DMAS_SHIFT) | +- (extra_open_dmas << BMI_EXTRA_NUM_OF_DMAS_SHIFT)); +- iowrite32be(tmp, &bmi_rg->fmbm_pp[port_id - 1]); +- +- /* update total num of DMA's with committed number of open DMAS, +- * and max uncommitted pool. +- */ +- if (total_num_dmas) { +- tmp = ioread32be(&bmi_rg->fmbm_cfg2) & ~BMI_CFG2_DMAS_MASK; +- tmp |= (u32)(total_num_dmas - 1) << BMI_CFG2_DMAS_SHIFT; +- iowrite32be(tmp, &bmi_rg->fmbm_cfg2); +- } +- +- return 0; +-} +- +-static int fman_config(struct fman *fman) +-{ +- void __iomem *base_addr; +- int err; +- +- base_addr = fman->dts_params.base_addr; +- +- fman->state = kzalloc(sizeof(*fman->state), GFP_KERNEL); +- if (!fman->state) +- goto err_fm_state; +- +- /* Allocate the FM driver's parameters structure */ +- fman->cfg = kzalloc(sizeof(*fman->cfg), GFP_KERNEL); +- if (!fman->cfg) +- goto err_fm_drv; +- +- /* Initialize MURAM block */ +- fman->muram = +- fman_muram_init(fman->dts_params.muram_res.start, +- resource_size(&fman->dts_params.muram_res)); +- if (!fman->muram) +- goto err_fm_soc_specific; +- +- /* Initialize FM parameters which will be kept by the driver */ +- fman->state->fm_id = fman->dts_params.id; +- fman->state->fm_clk_freq = fman->dts_params.clk_freq; +- fman->state->qman_channel_base = fman->dts_params.qman_channel_base; +- fman->state->num_of_qman_channels = +- fman->dts_params.num_of_qman_channels; +- fman->state->res = fman->dts_params.res; +- fman->exception_cb = fman_exceptions; +- fman->bus_error_cb = fman_bus_error; +- fman->fpm_regs = base_addr + FPM_OFFSET; +- fman->bmi_regs = base_addr + BMI_OFFSET; +- fman->qmi_regs = base_addr + QMI_OFFSET; +- fman->dma_regs = base_addr + DMA_OFFSET; +- fman->base_addr = base_addr; +- +- spin_lock_init(&fman->spinlock); +- fman_defconfig(fman->cfg); +- +- fman->state->extra_fifo_pool_size = 0; +- fman->state->exceptions = (EX_DMA_BUS_ERROR | +- EX_DMA_READ_ECC | +- EX_DMA_SYSTEM_WRITE_ECC | +- EX_DMA_FM_WRITE_ECC | +- EX_FPM_STALL_ON_TASKS | +- EX_FPM_SINGLE_ECC | +- EX_FPM_DOUBLE_ECC | +- EX_QMI_DEQ_FROM_UNKNOWN_PORTID | +- EX_BMI_LIST_RAM_ECC | +- EX_BMI_STORAGE_PROFILE_ECC | +- EX_BMI_STATISTICS_RAM_ECC | +- EX_MURAM_ECC | +- EX_BMI_DISPATCH_RAM_ECC | +- EX_QMI_DOUBLE_ECC | +- EX_QMI_SINGLE_ECC); +- +- /* Read FMan revision for future use*/ +- fman_get_revision(fman, &fman->state->rev_info); +- +- err = fill_soc_specific_params(fman->state); +- if (err) +- goto err_fm_soc_specific; +- +- /* FM_AID_MODE_NO_TNUM_SW005 Errata workaround */ +- if (fman->state->rev_info.major >= 6) +- fman->cfg->dma_aid_mode = FMAN_DMA_AID_OUT_PORT_ID; +- +- fman->cfg->qmi_def_tnums_thresh = fman->state->qmi_def_tnums_thresh; +- +- fman->state->total_num_of_tasks = +- (u8)DFLT_TOTAL_NUM_OF_TASKS(fman->state->rev_info.major, +- fman->state->rev_info.minor, +- fman->state->bmi_max_num_of_tasks); +- +- if (fman->state->rev_info.major < 6) { +- fman->cfg->dma_comm_qtsh_clr_emer = +- (u8)DFLT_DMA_COMM_Q_LOW(fman->state->rev_info.major, +- fman->state->dma_thresh_max_commq); +- +- fman->cfg->dma_comm_qtsh_asrt_emer = +- (u8)DFLT_DMA_COMM_Q_HIGH(fman->state->rev_info.major, +- fman->state->dma_thresh_max_commq); +- +- fman->cfg->dma_cam_num_of_entries = +- DFLT_DMA_CAM_NUM_OF_ENTRIES(fman->state->rev_info.major); +- +- fman->cfg->dma_read_buf_tsh_clr_emer = +- DFLT_DMA_READ_INT_BUF_LOW(fman->state->dma_thresh_max_buf); +- +- fman->cfg->dma_read_buf_tsh_asrt_emer = +- DFLT_DMA_READ_INT_BUF_HIGH(fman->state->dma_thresh_max_buf); +- +- fman->cfg->dma_write_buf_tsh_clr_emer = +- DFLT_DMA_WRITE_INT_BUF_LOW(fman->state->dma_thresh_max_buf); +- +- fman->cfg->dma_write_buf_tsh_asrt_emer = +- DFLT_DMA_WRITE_INT_BUF_HIGH(fman->state->dma_thresh_max_buf); +- +- fman->cfg->dma_axi_dbg_num_of_beats = +- DFLT_AXI_DBG_NUM_OF_BEATS; +- } +- +- return 0; +- +-err_fm_soc_specific: +- kfree(fman->cfg); +-err_fm_drv: +- kfree(fman->state); +-err_fm_state: +- kfree(fman); +- return -EINVAL; +-} +- +-static int fman_reset(struct fman *fman) +-{ +- u32 count; +- int err = 0; +- +- if (fman->state->rev_info.major < 6) { +- iowrite32be(FPM_RSTC_FM_RESET, &fman->fpm_regs->fm_rstc); +- /* Wait for reset completion */ +- count = 100; +- do { +- udelay(1); +- } while (((ioread32be(&fman->fpm_regs->fm_rstc)) & +- FPM_RSTC_FM_RESET) && --count); +- if (count == 0) +- err = -EBUSY; +- +- goto _return; +- } else { +- struct device_node *guts_node; +- struct ccsr_guts __iomem *guts_regs; +- u32 devdisr2, reg; +- +- /* Errata A007273 */ +- guts_node = +- of_find_compatible_node(NULL, NULL, +- "fsl,qoriq-device-config-2.0"); +- if (!guts_node) { +- dev_err(fman->dev, "%s: Couldn't find guts node\n", +- __func__); +- goto guts_node; +- } +- +- guts_regs = of_iomap(guts_node, 0); +- if (!guts_regs) { +- dev_err(fman->dev, "%s: Couldn't map %s regs\n", +- __func__, guts_node->full_name); +- goto guts_regs; +- } +-#define FMAN1_ALL_MACS_MASK 0xFCC00000 +-#define FMAN2_ALL_MACS_MASK 0x000FCC00 +- /* Read current state */ +- devdisr2 = ioread32be(&guts_regs->devdisr2); +- if (fman->dts_params.id == 0) +- reg = devdisr2 & ~FMAN1_ALL_MACS_MASK; +- else +- reg = devdisr2 & ~FMAN2_ALL_MACS_MASK; +- +- /* Enable all MACs */ +- iowrite32be(reg, &guts_regs->devdisr2); +- +- /* Perform FMan reset */ +- iowrite32be(FPM_RSTC_FM_RESET, &fman->fpm_regs->fm_rstc); +- +- /* Wait for reset completion */ +- count = 100; +- do { +- udelay(1); +- } while (((ioread32be(&fman->fpm_regs->fm_rstc)) & +- FPM_RSTC_FM_RESET) && --count); +- if (count == 0) { +- iounmap(guts_regs); +- of_node_put(guts_node); +- err = -EBUSY; +- goto _return; +- } +- +- /* Restore devdisr2 value */ +- iowrite32be(devdisr2, &guts_regs->devdisr2); +- +- iounmap(guts_regs); +- of_node_put(guts_node); +- +- goto _return; +- +-guts_regs: +- of_node_put(guts_node); +-guts_node: +- dev_dbg(fman->dev, "%s: Didn't perform FManV3 reset due to Errata A007273!\n", +- __func__); +- } +-_return: +- return err; +-} +- +-static int fman_init(struct fman *fman) +-{ +- struct fman_cfg *cfg = NULL; +- int err = 0, i, count; +- +- if (is_init_done(fman->cfg)) +- return -EINVAL; +- +- fman->state->count1_micro_bit = FM_TIMESTAMP_1_USEC_BIT; +- +- cfg = fman->cfg; +- +- /* clear revision-dependent non existing exception */ +- if (fman->state->rev_info.major < 6) +- fman->state->exceptions &= ~FMAN_EX_BMI_DISPATCH_RAM_ECC; +- +- if (fman->state->rev_info.major >= 6) +- fman->state->exceptions &= ~FMAN_EX_QMI_SINGLE_ECC; +- +- /* clear CPG */ +- memset_io((void __iomem *)(fman->base_addr + CGP_OFFSET), 0, +- fman->state->fm_port_num_of_cg); +- +- /* Save LIODN info before FMan reset +- * Skipping non-existent port 0 (i = 1) +- */ +- for (i = 1; i < FMAN_LIODN_TBL; i++) { +- u32 liodn_base; +- +- fman->liodn_offset[i] = +- ioread32be(&fman->bmi_regs->fmbm_spliodn[i - 1]); +- liodn_base = ioread32be(&fman->dma_regs->fmdmplr[i / 2]); +- if (i % 2) { +- /* FMDM_PLR LSB holds LIODN base for odd ports */ +- liodn_base &= DMA_LIODN_BASE_MASK; +- } else { +- /* FMDM_PLR MSB holds LIODN base for even ports */ +- liodn_base >>= DMA_LIODN_SHIFT; +- liodn_base &= DMA_LIODN_BASE_MASK; +- } +- fman->liodn_base[i] = liodn_base; +- } +- +- err = fman_reset(fman); +- if (err) +- return err; +- +- if (ioread32be(&fman->qmi_regs->fmqm_gs) & QMI_GS_HALT_NOT_BUSY) { +- resume(fman->fpm_regs); +- /* Wait until QMI is not in halt not busy state */ +- count = 100; +- do { +- udelay(1); +- } while (((ioread32be(&fman->qmi_regs->fmqm_gs)) & +- QMI_GS_HALT_NOT_BUSY) && --count); +- if (count == 0) +- dev_warn(fman->dev, "%s: QMI is in halt not busy state\n", +- __func__); +- } +- +- if (clear_iram(fman) != 0) +- return -EINVAL; +- +- cfg->exceptions = fman->state->exceptions; +- +- /* Init DMA Registers */ +- +- err = dma_init(fman); +- if (err != 0) { +- free_init_resources(fman); +- return err; +- } +- +- /* Init FPM Registers */ +- fpm_init(fman->fpm_regs, fman->cfg); +- +- /* define common resources */ +- /* allocate MURAM for FIFO according to total size */ +- fman->fifo_offset = fman_muram_alloc(fman->muram, +- fman->state->total_fifo_size); +- if (IS_ERR_VALUE(fman->fifo_offset)) { +- free_init_resources(fman); +- dev_err(fman->dev, "%s: MURAM alloc for BMI FIFO failed\n", +- __func__); +- return -ENOMEM; +- } +- +- cfg->fifo_base_addr = fman->fifo_offset; +- cfg->total_fifo_size = fman->state->total_fifo_size; +- cfg->total_num_of_tasks = fman->state->total_num_of_tasks; +- cfg->clk_freq = fman->state->fm_clk_freq; +- +- /* Init BMI Registers */ +- bmi_init(fman->bmi_regs, fman->cfg); +- +- /* Init QMI Registers */ +- qmi_init(fman->qmi_regs, fman->cfg); +- +- err = enable(fman, cfg); +- if (err != 0) +- return err; +- +- enable_time_stamp(fman); +- +- kfree(fman->cfg); +- fman->cfg = NULL; +- +- return 0; +-} +- +-static int fman_set_exception(struct fman *fman, +- enum fman_exceptions exception, bool enable) +-{ +- u32 bit_mask = 0; +- +- if (!is_init_done(fman->cfg)) +- return -EINVAL; +- +- bit_mask = get_exception_flag(exception); +- if (bit_mask) { +- if (enable) +- fman->state->exceptions |= bit_mask; +- else +- fman->state->exceptions &= ~bit_mask; +- } else { +- dev_err(fman->dev, "%s: Undefined exception (%d)\n", +- __func__, exception); +- return -EINVAL; +- } +- +- return set_exception(fman, exception, enable); +-} +- +-/** +- * fman_register_intr +- * @fman: A Pointer to FMan device +- * @mod: Calling module +- * @mod_id: Module id (if more than 1 exists, '0' if not) +- * @intr_type: Interrupt type (error/normal) selection. +- * @f_isr: The interrupt service routine. +- * @h_src_arg: Argument to be passed to f_isr. +- * +- * Used to register an event handler to be processed by FMan +- * +- * Return: 0 on success; Error code otherwise. +- */ +-void fman_register_intr(struct fman *fman, enum fman_event_modules module, +- u8 mod_id, enum fman_intr_type intr_type, +- void (*isr_cb)(void *src_arg), void *src_arg) +-{ +- int event = 0; +- +- event = get_module_event(module, mod_id, intr_type); +- WARN_ON(event >= FMAN_EV_CNT); +- +- /* register in local FM structure */ +- fman->intr_mng[event].isr_cb = isr_cb; +- fman->intr_mng[event].src_handle = src_arg; +-} +-EXPORT_SYMBOL(fman_register_intr); +- +-/** +- * fman_unregister_intr +- * @fman: A Pointer to FMan device +- * @mod: Calling module +- * @mod_id: Module id (if more than 1 exists, '0' if not) +- * @intr_type: Interrupt type (error/normal) selection. +- * +- * Used to unregister an event handler to be processed by FMan +- * +- * Return: 0 on success; Error code otherwise. +- */ +-void fman_unregister_intr(struct fman *fman, enum fman_event_modules module, +- u8 mod_id, enum fman_intr_type intr_type) +-{ +- int event = 0; +- +- event = get_module_event(module, mod_id, intr_type); +- WARN_ON(event >= FMAN_EV_CNT); +- +- fman->intr_mng[event].isr_cb = NULL; +- fman->intr_mng[event].src_handle = NULL; +-} +-EXPORT_SYMBOL(fman_unregister_intr); +- +-/** +- * fman_set_port_params +- * @fman: A Pointer to FMan device +- * @port_params: Port parameters +- * +- * Used by FMan Port to pass parameters to the FMan +- * +- * Return: 0 on success; Error code otherwise. +- */ +-int fman_set_port_params(struct fman *fman, +- struct fman_port_init_params *port_params) +-{ +- int err; +- unsigned long flags; +- u8 port_id = port_params->port_id, mac_id; +- +- spin_lock_irqsave(&fman->spinlock, flags); +- +- err = set_num_of_tasks(fman, port_params->port_id, +- &port_params->num_of_tasks, +- &port_params->num_of_extra_tasks); +- if (err) +- goto return_err; +- +- /* TX Ports */ +- if (port_params->port_type != FMAN_PORT_TYPE_RX) { +- u32 enq_th, deq_th, reg; +- +- /* update qmi ENQ/DEQ threshold */ +- fman->state->accumulated_num_of_deq_tnums += +- port_params->deq_pipeline_depth; +- enq_th = (ioread32be(&fman->qmi_regs->fmqm_gc) & +- QMI_CFG_ENQ_MASK) >> QMI_CFG_ENQ_SHIFT; +- /* if enq_th is too big, we reduce it to the max value +- * that is still 0 +- */ +- if (enq_th >= (fman->state->qmi_max_num_of_tnums - +- fman->state->accumulated_num_of_deq_tnums)) { +- enq_th = +- fman->state->qmi_max_num_of_tnums - +- fman->state->accumulated_num_of_deq_tnums - 1; +- +- reg = ioread32be(&fman->qmi_regs->fmqm_gc); +- reg &= ~QMI_CFG_ENQ_MASK; +- reg |= (enq_th << QMI_CFG_ENQ_SHIFT); +- iowrite32be(reg, &fman->qmi_regs->fmqm_gc); +- } +- +- deq_th = ioread32be(&fman->qmi_regs->fmqm_gc) & +- QMI_CFG_DEQ_MASK; +- /* if deq_th is too small, we enlarge it to the min +- * value that is still 0. +- * depTh may not be larger than 63 +- * (fman->state->qmi_max_num_of_tnums-1). +- */ +- if ((deq_th <= fman->state->accumulated_num_of_deq_tnums) && +- (deq_th < fman->state->qmi_max_num_of_tnums - 1)) { +- deq_th = fman->state->accumulated_num_of_deq_tnums + 1; +- reg = ioread32be(&fman->qmi_regs->fmqm_gc); +- reg &= ~QMI_CFG_DEQ_MASK; +- reg |= deq_th; +- iowrite32be(reg, &fman->qmi_regs->fmqm_gc); +- } +- } +- +- err = set_size_of_fifo(fman, port_params->port_id, +- &port_params->size_of_fifo, +- &port_params->extra_size_of_fifo); +- if (err) +- goto return_err; +- +- err = set_num_of_open_dmas(fman, port_params->port_id, +- &port_params->num_of_open_dmas, +- &port_params->num_of_extra_open_dmas); +- if (err) +- goto return_err; +- +- set_port_liodn(fman, port_id, fman->liodn_base[port_id], +- fman->liodn_offset[port_id]); +- +- if (fman->state->rev_info.major < 6) +- set_port_order_restoration(fman->fpm_regs, port_id); +- +- mac_id = hw_port_id_to_sw_port_id(fman->state->rev_info.major, port_id); +- +- if (port_params->max_frame_length >= fman->state->mac_mfl[mac_id]) { +- fman->state->port_mfl[mac_id] = port_params->max_frame_length; +- } else { +- dev_warn(fman->dev, "%s: Port (%d) max_frame_length is smaller than MAC (%d) current MTU\n", +- __func__, port_id, mac_id); +- err = -EINVAL; +- goto return_err; +- } +- +- spin_unlock_irqrestore(&fman->spinlock, flags); +- +- return 0; +- +-return_err: +- spin_unlock_irqrestore(&fman->spinlock, flags); +- return err; +-} +-EXPORT_SYMBOL(fman_set_port_params); +- +-/** +- * fman_reset_mac +- * @fman: A Pointer to FMan device +- * @mac_id: MAC id to be reset +- * +- * Reset a specific MAC +- * +- * Return: 0 on success; Error code otherwise. +- */ +-int fman_reset_mac(struct fman *fman, u8 mac_id) +-{ +- struct fman_fpm_regs __iomem *fpm_rg = fman->fpm_regs; +- u32 msk, timeout = 100; +- +- if (fman->state->rev_info.major >= 6) { +- dev_err(fman->dev, "%s: FMan MAC reset no available for FMan V3!\n", +- __func__); +- return -EINVAL; +- } +- +- /* Get the relevant bit mask */ +- switch (mac_id) { +- case 0: +- msk = FPM_RSTC_MAC0_RESET; +- break; +- case 1: +- msk = FPM_RSTC_MAC1_RESET; +- break; +- case 2: +- msk = FPM_RSTC_MAC2_RESET; +- break; +- case 3: +- msk = FPM_RSTC_MAC3_RESET; +- break; +- case 4: +- msk = FPM_RSTC_MAC4_RESET; +- break; +- case 5: +- msk = FPM_RSTC_MAC5_RESET; +- break; +- case 6: +- msk = FPM_RSTC_MAC6_RESET; +- break; +- case 7: +- msk = FPM_RSTC_MAC7_RESET; +- break; +- case 8: +- msk = FPM_RSTC_MAC8_RESET; +- break; +- case 9: +- msk = FPM_RSTC_MAC9_RESET; +- break; +- default: +- dev_warn(fman->dev, "%s: Illegal MAC Id [%d]\n", +- __func__, mac_id); +- return -EINVAL; +- } +- +- /* reset */ +- iowrite32be(msk, &fpm_rg->fm_rstc); +- while ((ioread32be(&fpm_rg->fm_rstc) & msk) && --timeout) +- udelay(10); +- +- if (!timeout) +- return -EIO; +- +- return 0; +-} +-EXPORT_SYMBOL(fman_reset_mac); +- +-/** +- * fman_set_mac_max_frame +- * @fman: A Pointer to FMan device +- * @mac_id: MAC id +- * @mfl: Maximum frame length +- * +- * Set maximum frame length of specific MAC in FMan driver +- * +- * Return: 0 on success; Error code otherwise. +- */ +-int fman_set_mac_max_frame(struct fman *fman, u8 mac_id, u16 mfl) +-{ +- /* if port is already initialized, check that MaxFrameLength is smaller +- * or equal to the port's max +- */ +- if ((!fman->state->port_mfl[mac_id]) || +- (mfl <= fman->state->port_mfl[mac_id])) { +- fman->state->mac_mfl[mac_id] = mfl; +- } else { +- dev_warn(fman->dev, "%s: MAC max_frame_length is larger than Port max_frame_length\n", +- __func__); +- return -EINVAL; +- } +- return 0; +-} +-EXPORT_SYMBOL(fman_set_mac_max_frame); +- +-/** +- * fman_get_clock_freq +- * @fman: A Pointer to FMan device +- * +- * Get FMan clock frequency +- * +- * Return: FMan clock frequency +- */ +-u16 fman_get_clock_freq(struct fman *fman) +-{ +- return fman->state->fm_clk_freq; +-} +- +-/** +- * fman_get_bmi_max_fifo_size +- * @fman: A Pointer to FMan device +- * +- * Get FMan maximum FIFO size +- * +- * Return: FMan Maximum FIFO size +- */ +-u32 fman_get_bmi_max_fifo_size(struct fman *fman) +-{ +- return fman->state->bmi_max_fifo_size; +-} +-EXPORT_SYMBOL(fman_get_bmi_max_fifo_size); +- +-/** +- * fman_get_revision +- * @fman - Pointer to the FMan module +- * @rev_info - A structure of revision information parameters. +- * +- * Returns the FM revision +- * +- * Allowed only following fman_init(). +- * +- * Return: 0 on success; Error code otherwise. +- */ +-void fman_get_revision(struct fman *fman, struct fman_rev_info *rev_info) +-{ +- u32 tmp; +- +- tmp = ioread32be(&fman->fpm_regs->fm_ip_rev_1); +- rev_info->major = (u8)((tmp & FPM_REV1_MAJOR_MASK) >> +- FPM_REV1_MAJOR_SHIFT); +- rev_info->minor = tmp & FPM_REV1_MINOR_MASK; +-} +-EXPORT_SYMBOL(fman_get_revision); +- +-/** +- * fman_get_qman_channel_id +- * @fman: A Pointer to FMan device +- * @port_id: Port id +- * +- * Get QMan channel ID associated to the Port id +- * +- * Return: QMan channel ID +- */ +-u32 fman_get_qman_channel_id(struct fman *fman, u32 port_id) +-{ +- int i; +- +- if (fman->state->rev_info.major >= 6) { +- u32 port_ids[] = {0x30, 0x31, 0x28, 0x29, 0x2a, 0x2b, +- 0x2c, 0x2d, 0x2, 0x3, 0x4, 0x5, 0x7, 0x7}; +- for (i = 0; i < fman->state->num_of_qman_channels; i++) { +- if (port_ids[i] == port_id) +- break; +- } +- } else { +- u32 port_ids[] = {0x30, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x1, +- 0x2, 0x3, 0x4, 0x5, 0x7, 0x7}; +- for (i = 0; i < fman->state->num_of_qman_channels; i++) { +- if (port_ids[i] == port_id) +- break; +- } +- } +- +- if (i == fman->state->num_of_qman_channels) +- return 0; +- +- return fman->state->qman_channel_base + i; +-} +-EXPORT_SYMBOL(fman_get_qman_channel_id); +- +-/** +- * fman_get_mem_region +- * @fman: A Pointer to FMan device +- * +- * Get FMan memory region +- * +- * Return: A structure with FMan memory region information +- */ +-struct resource *fman_get_mem_region(struct fman *fman) +-{ +- return fman->state->res; +-} +-EXPORT_SYMBOL(fman_get_mem_region); +- +-/* Bootargs defines */ +-/* Extra headroom for RX buffers - Default, min and max */ +-#define FSL_FM_RX_EXTRA_HEADROOM 64 +-#define FSL_FM_RX_EXTRA_HEADROOM_MIN 16 +-#define FSL_FM_RX_EXTRA_HEADROOM_MAX 384 +- +-/* Maximum frame length */ +-#define FSL_FM_MAX_FRAME_SIZE 1522 +-#define FSL_FM_MAX_POSSIBLE_FRAME_SIZE 9600 +-#define FSL_FM_MIN_POSSIBLE_FRAME_SIZE 64 +- +-/* Extra headroom for Rx buffers. +- * FMan is instructed to allocate, on the Rx path, this amount of +- * space at the beginning of a data buffer, beside the DPA private +- * data area and the IC fields. +- * Does not impact Tx buffer layout. +- * Configurable from bootargs. 64 by default, it's needed on +- * particular forwarding scenarios that add extra headers to the +- * forwarded frame. +- */ +-static int fsl_fm_rx_extra_headroom = FSL_FM_RX_EXTRA_HEADROOM; +-module_param(fsl_fm_rx_extra_headroom, int, 0); +-MODULE_PARM_DESC(fsl_fm_rx_extra_headroom, "Extra headroom for Rx buffers"); +- +-/* Max frame size, across all interfaces. +- * Configurable from bootargs, to avoid allocating oversized (socket) +- * buffers when not using jumbo frames. +- * Must be large enough to accommodate the network MTU, but small enough +- * to avoid wasting skb memory. +- * +- * Could be overridden once, at boot-time, via the +- * fm_set_max_frm() callback. +- */ +-static int fsl_fm_max_frm = FSL_FM_MAX_FRAME_SIZE; +-module_param(fsl_fm_max_frm, int, 0); +-MODULE_PARM_DESC(fsl_fm_max_frm, "Maximum frame size, across all interfaces"); +- +-/** +- * fman_get_max_frm +- * +- * Return: Max frame length configured in the FM driver +- */ +-u16 fman_get_max_frm(void) +-{ +- static bool fm_check_mfl; +- +- if (!fm_check_mfl) { +- if (fsl_fm_max_frm > FSL_FM_MAX_POSSIBLE_FRAME_SIZE || +- fsl_fm_max_frm < FSL_FM_MIN_POSSIBLE_FRAME_SIZE) { +- pr_warn("Invalid fsl_fm_max_frm value (%d) in bootargs, valid range is %d-%d. Falling back to the default (%d)\n", +- fsl_fm_max_frm, +- FSL_FM_MIN_POSSIBLE_FRAME_SIZE, +- FSL_FM_MAX_POSSIBLE_FRAME_SIZE, +- FSL_FM_MAX_FRAME_SIZE); +- fsl_fm_max_frm = FSL_FM_MAX_FRAME_SIZE; +- } +- fm_check_mfl = true; +- } +- +- return fsl_fm_max_frm; +-} +-EXPORT_SYMBOL(fman_get_max_frm); +- +-/** +- * fman_get_rx_extra_headroom +- * +- * Return: Extra headroom size configured in the FM driver +- */ +-int fman_get_rx_extra_headroom(void) +-{ +- static bool fm_check_rx_extra_headroom; +- +- if (!fm_check_rx_extra_headroom) { +- if (fsl_fm_rx_extra_headroom > FSL_FM_RX_EXTRA_HEADROOM_MAX || +- fsl_fm_rx_extra_headroom < FSL_FM_RX_EXTRA_HEADROOM_MIN) { +- pr_warn("Invalid fsl_fm_rx_extra_headroom value (%d) in bootargs, valid range is %d-%d. Falling back to the default (%d)\n", +- fsl_fm_rx_extra_headroom, +- FSL_FM_RX_EXTRA_HEADROOM_MIN, +- FSL_FM_RX_EXTRA_HEADROOM_MAX, +- FSL_FM_RX_EXTRA_HEADROOM); +- fsl_fm_rx_extra_headroom = FSL_FM_RX_EXTRA_HEADROOM; +- } +- +- fm_check_rx_extra_headroom = true; +- fsl_fm_rx_extra_headroom = ALIGN(fsl_fm_rx_extra_headroom, 16); +- } +- +- return fsl_fm_rx_extra_headroom; +-} +-EXPORT_SYMBOL(fman_get_rx_extra_headroom); +- +-/** +- * fman_bind +- * @dev: FMan OF device pointer +- * +- * Bind to a specific FMan device. +- * +- * Allowed only after the port was created. +- * +- * Return: A pointer to the FMan device +- */ +-struct fman *fman_bind(struct device *fm_dev) +-{ +- return (struct fman *)(dev_get_drvdata(get_device(fm_dev))); +-} +-EXPORT_SYMBOL(fman_bind); +- +-static irqreturn_t fman_err_irq(int irq, void *handle) +-{ +- struct fman *fman = (struct fman *)handle; +- u32 pending; +- struct fman_fpm_regs __iomem *fpm_rg; +- irqreturn_t single_ret, ret = IRQ_NONE; +- +- if (!is_init_done(fman->cfg)) +- return IRQ_NONE; +- +- fpm_rg = fman->fpm_regs; +- +- /* error interrupts */ +- pending = ioread32be(&fpm_rg->fm_epi); +- if (!pending) +- return IRQ_NONE; +- +- if (pending & ERR_INTR_EN_BMI) { +- single_ret = bmi_err_event(fman); +- if (single_ret == IRQ_HANDLED) +- ret = IRQ_HANDLED; +- } +- if (pending & ERR_INTR_EN_QMI) { +- single_ret = qmi_err_event(fman); +- if (single_ret == IRQ_HANDLED) +- ret = IRQ_HANDLED; +- } +- if (pending & ERR_INTR_EN_FPM) { +- single_ret = fpm_err_event(fman); +- if (single_ret == IRQ_HANDLED) +- ret = IRQ_HANDLED; +- } +- if (pending & ERR_INTR_EN_DMA) { +- single_ret = dma_err_event(fman); +- if (single_ret == IRQ_HANDLED) +- ret = IRQ_HANDLED; +- } +- if (pending & ERR_INTR_EN_MURAM) { +- single_ret = muram_err_intr(fman); +- if (single_ret == IRQ_HANDLED) +- ret = IRQ_HANDLED; +- } +- +- /* MAC error interrupts */ +- if (pending & ERR_INTR_EN_MAC0) { +- single_ret = call_mac_isr(fman, FMAN_EV_ERR_MAC0 + 0); +- if (single_ret == IRQ_HANDLED) +- ret = IRQ_HANDLED; +- } +- if (pending & ERR_INTR_EN_MAC1) { +- single_ret = call_mac_isr(fman, FMAN_EV_ERR_MAC0 + 1); +- if (single_ret == IRQ_HANDLED) +- ret = IRQ_HANDLED; +- } +- if (pending & ERR_INTR_EN_MAC2) { +- single_ret = call_mac_isr(fman, FMAN_EV_ERR_MAC0 + 2); +- if (single_ret == IRQ_HANDLED) +- ret = IRQ_HANDLED; +- } +- if (pending & ERR_INTR_EN_MAC3) { +- single_ret = call_mac_isr(fman, FMAN_EV_ERR_MAC0 + 3); +- if (single_ret == IRQ_HANDLED) +- ret = IRQ_HANDLED; +- } +- if (pending & ERR_INTR_EN_MAC4) { +- single_ret = call_mac_isr(fman, FMAN_EV_ERR_MAC0 + 4); +- if (single_ret == IRQ_HANDLED) +- ret = IRQ_HANDLED; +- } +- if (pending & ERR_INTR_EN_MAC5) { +- single_ret = call_mac_isr(fman, FMAN_EV_ERR_MAC0 + 5); +- if (single_ret == IRQ_HANDLED) +- ret = IRQ_HANDLED; +- } +- if (pending & ERR_INTR_EN_MAC6) { +- single_ret = call_mac_isr(fman, FMAN_EV_ERR_MAC0 + 6); +- if (single_ret == IRQ_HANDLED) +- ret = IRQ_HANDLED; +- } +- if (pending & ERR_INTR_EN_MAC7) { +- single_ret = call_mac_isr(fman, FMAN_EV_ERR_MAC0 + 7); +- if (single_ret == IRQ_HANDLED) +- ret = IRQ_HANDLED; +- } +- if (pending & ERR_INTR_EN_MAC8) { +- single_ret = call_mac_isr(fman, FMAN_EV_ERR_MAC0 + 8); +- if (single_ret == IRQ_HANDLED) +- ret = IRQ_HANDLED; +- } +- if (pending & ERR_INTR_EN_MAC9) { +- single_ret = call_mac_isr(fman, FMAN_EV_ERR_MAC0 + 9); +- if (single_ret == IRQ_HANDLED) +- ret = IRQ_HANDLED; +- } +- +- return ret; +-} +- +-static irqreturn_t fman_irq(int irq, void *handle) +-{ +- struct fman *fman = (struct fman *)handle; +- u32 pending; +- struct fman_fpm_regs __iomem *fpm_rg; +- irqreturn_t single_ret, ret = IRQ_NONE; +- +- if (!is_init_done(fman->cfg)) +- return IRQ_NONE; +- +- fpm_rg = fman->fpm_regs; +- +- /* normal interrupts */ +- pending = ioread32be(&fpm_rg->fm_npi); +- if (!pending) +- return IRQ_NONE; +- +- if (pending & INTR_EN_QMI) { +- single_ret = qmi_event(fman); +- if (single_ret == IRQ_HANDLED) +- ret = IRQ_HANDLED; +- } +- +- /* MAC interrupts */ +- if (pending & INTR_EN_MAC0) { +- single_ret = call_mac_isr(fman, FMAN_EV_MAC0 + 0); +- if (single_ret == IRQ_HANDLED) +- ret = IRQ_HANDLED; +- } +- if (pending & INTR_EN_MAC1) { +- single_ret = call_mac_isr(fman, FMAN_EV_MAC0 + 1); +- if (single_ret == IRQ_HANDLED) +- ret = IRQ_HANDLED; +- } +- if (pending & INTR_EN_MAC2) { +- single_ret = call_mac_isr(fman, FMAN_EV_MAC0 + 2); +- if (single_ret == IRQ_HANDLED) +- ret = IRQ_HANDLED; +- } +- if (pending & INTR_EN_MAC3) { +- single_ret = call_mac_isr(fman, FMAN_EV_MAC0 + 3); +- if (single_ret == IRQ_HANDLED) +- ret = IRQ_HANDLED; +- } +- if (pending & INTR_EN_MAC4) { +- single_ret = call_mac_isr(fman, FMAN_EV_MAC0 + 4); +- if (single_ret == IRQ_HANDLED) +- ret = IRQ_HANDLED; +- } +- if (pending & INTR_EN_MAC5) { +- single_ret = call_mac_isr(fman, FMAN_EV_MAC0 + 5); +- if (single_ret == IRQ_HANDLED) +- ret = IRQ_HANDLED; +- } +- if (pending & INTR_EN_MAC6) { +- single_ret = call_mac_isr(fman, FMAN_EV_MAC0 + 6); +- if (single_ret == IRQ_HANDLED) +- ret = IRQ_HANDLED; +- } +- if (pending & INTR_EN_MAC7) { +- single_ret = call_mac_isr(fman, FMAN_EV_MAC0 + 7); +- if (single_ret == IRQ_HANDLED) +- ret = IRQ_HANDLED; +- } +- if (pending & INTR_EN_MAC8) { +- single_ret = call_mac_isr(fman, FMAN_EV_MAC0 + 8); +- if (single_ret == IRQ_HANDLED) +- ret = IRQ_HANDLED; +- } +- if (pending & INTR_EN_MAC9) { +- single_ret = call_mac_isr(fman, FMAN_EV_MAC0 + 9); +- if (single_ret == IRQ_HANDLED) +- ret = IRQ_HANDLED; +- } +- +- return ret; +-} +- +-static const struct of_device_id fman_muram_match[] = { +- { +- .compatible = "fsl,fman-muram"}, +- {} +-}; +-MODULE_DEVICE_TABLE(of, fman_muram_match); +- +-static struct fman *read_dts_node(struct platform_device *of_dev) +-{ +- struct fman *fman; +- struct device_node *fm_node, *muram_node; +- struct resource *res; +- u32 val, range[2]; +- int err, irq; +- struct clk *clk; +- u32 clk_rate; +- phys_addr_t phys_base_addr; +- resource_size_t mem_size; +- +- fman = kzalloc(sizeof(*fman), GFP_KERNEL); +- if (!fman) +- return NULL; +- +- fm_node = of_node_get(of_dev->dev.of_node); +- +- err = of_property_read_u32(fm_node, "cell-index", &val); +- if (err) { +- dev_err(&of_dev->dev, "%s: failed to read cell-index for %s\n", +- __func__, fm_node->full_name); +- goto fman_node_put; +- } +- fman->dts_params.id = (u8)val; +- +- /* Get the FM interrupt */ +- res = platform_get_resource(of_dev, IORESOURCE_IRQ, 0); +- if (!res) { +- dev_err(&of_dev->dev, "%s: Can't get FMan IRQ resource\n", +- __func__); +- goto fman_node_put; +- } +- irq = res->start; +- +- /* Get the FM error interrupt */ +- res = platform_get_resource(of_dev, IORESOURCE_IRQ, 1); +- if (!res) { +- dev_err(&of_dev->dev, "%s: Can't get FMan Error IRQ resource\n", +- __func__); +- goto fman_node_put; +- } +- fman->dts_params.err_irq = res->start; +- +- /* Get the FM address */ +- res = platform_get_resource(of_dev, IORESOURCE_MEM, 0); +- if (!res) { +- dev_err(&of_dev->dev, "%s: Can't get FMan memory resource\n", +- __func__); +- goto fman_node_put; +- } +- +- phys_base_addr = res->start; +- mem_size = resource_size(res); +- +- clk = of_clk_get(fm_node, 0); +- if (IS_ERR(clk)) { +- dev_err(&of_dev->dev, "%s: Failed to get FM%d clock structure\n", +- __func__, fman->dts_params.id); +- goto fman_node_put; +- } +- +- clk_rate = clk_get_rate(clk); +- if (!clk_rate) { +- dev_err(&of_dev->dev, "%s: Failed to determine FM%d clock rate\n", +- __func__, fman->dts_params.id); +- goto fman_node_put; +- } +- /* Rounding to MHz */ +- fman->dts_params.clk_freq = DIV_ROUND_UP(clk_rate, 1000000); +- +- err = of_property_read_u32_array(fm_node, "fsl,qman-channel-range", +- &range[0], 2); +- if (err) { +- dev_err(&of_dev->dev, "%s: failed to read fsl,qman-channel-range for %s\n", +- __func__, fm_node->full_name); +- goto fman_node_put; +- } +- fman->dts_params.qman_channel_base = range[0]; +- fman->dts_params.num_of_qman_channels = range[1]; +- +- /* Get the MURAM base address and size */ +- muram_node = of_find_matching_node(fm_node, fman_muram_match); +- if (!muram_node) { +- dev_err(&of_dev->dev, "%s: could not find MURAM node\n", +- __func__); +- goto fman_node_put; +- } +- +- err = of_address_to_resource(muram_node, 0, +- &fman->dts_params.muram_res); +- if (err) { +- of_node_put(muram_node); +- dev_err(&of_dev->dev, "%s: of_address_to_resource() = %d\n", +- __func__, err); +- goto fman_node_put; +- } +- +- of_node_put(muram_node); +- of_node_put(fm_node); +- +- err = devm_request_irq(&of_dev->dev, irq, fman_irq, 0, "fman", fman); +- if (err < 0) { +- dev_err(&of_dev->dev, "%s: irq %d allocation failed (error = %d)\n", +- __func__, irq, err); +- goto fman_free; +- } +- +- if (fman->dts_params.err_irq != 0) { +- err = devm_request_irq(&of_dev->dev, fman->dts_params.err_irq, +- fman_err_irq, IRQF_SHARED, +- "fman-err", fman); +- if (err < 0) { +- dev_err(&of_dev->dev, "%s: irq %d allocation failed (error = %d)\n", +- __func__, fman->dts_params.err_irq, err); +- goto fman_free; +- } +- } +- +- fman->dts_params.res = +- devm_request_mem_region(&of_dev->dev, phys_base_addr, +- mem_size, "fman"); +- if (!fman->dts_params.res) { +- dev_err(&of_dev->dev, "%s: request_mem_region() failed\n", +- __func__); +- goto fman_free; +- } +- +- fman->dts_params.base_addr = +- devm_ioremap(&of_dev->dev, phys_base_addr, mem_size); +- if (!fman->dts_params.base_addr) { +- dev_err(&of_dev->dev, "%s: devm_ioremap() failed\n", __func__); +- goto fman_free; +- } +- +- fman->dev = &of_dev->dev; +- +- return fman; +- +-fman_node_put: +- of_node_put(fm_node); +-fman_free: +- kfree(fman); +- return NULL; +-} +- +-static int fman_probe(struct platform_device *of_dev) +-{ +- struct fman *fman; +- struct device *dev; +- int err; +- +- dev = &of_dev->dev; +- +- fman = read_dts_node(of_dev); +- if (!fman) +- return -EIO; +- +- err = fman_config(fman); +- if (err) { +- dev_err(dev, "%s: FMan config failed\n", __func__); +- return -EINVAL; +- } +- +- if (fman_init(fman) != 0) { +- dev_err(dev, "%s: FMan init failed\n", __func__); +- return -EINVAL; +- } +- +- if (fman->dts_params.err_irq == 0) { +- fman_set_exception(fman, FMAN_EX_DMA_BUS_ERROR, false); +- fman_set_exception(fman, FMAN_EX_DMA_READ_ECC, false); +- fman_set_exception(fman, FMAN_EX_DMA_SYSTEM_WRITE_ECC, false); +- fman_set_exception(fman, FMAN_EX_DMA_FM_WRITE_ECC, false); +- fman_set_exception(fman, FMAN_EX_DMA_SINGLE_PORT_ECC, false); +- fman_set_exception(fman, FMAN_EX_FPM_STALL_ON_TASKS, false); +- fman_set_exception(fman, FMAN_EX_FPM_SINGLE_ECC, false); +- fman_set_exception(fman, FMAN_EX_FPM_DOUBLE_ECC, false); +- fman_set_exception(fman, FMAN_EX_QMI_SINGLE_ECC, false); +- fman_set_exception(fman, FMAN_EX_QMI_DOUBLE_ECC, false); +- fman_set_exception(fman, +- FMAN_EX_QMI_DEQ_FROM_UNKNOWN_PORTID, false); +- fman_set_exception(fman, FMAN_EX_BMI_LIST_RAM_ECC, false); +- fman_set_exception(fman, FMAN_EX_BMI_STORAGE_PROFILE_ECC, +- false); +- fman_set_exception(fman, FMAN_EX_BMI_STATISTICS_RAM_ECC, false); +- fman_set_exception(fman, FMAN_EX_BMI_DISPATCH_RAM_ECC, false); +- } +- +- dev_set_drvdata(dev, fman); +- +- dev_dbg(dev, "FMan%d probed\n", fman->dts_params.id); +- +- return 0; +-} +- +-static const struct of_device_id fman_match[] = { +- { +- .compatible = "fsl,fman"}, +- {} +-}; +- +-MODULE_DEVICE_TABLE(of, fman_match); +- +-static struct platform_driver fman_driver = { +- .driver = { +- .name = "fsl-fman", +- .of_match_table = fman_match, +- }, +- .probe = fman_probe, +-}; +- +-static int __init fman_load(void) +-{ +- int err; +- +- pr_debug("FSL DPAA FMan driver\n"); +- +- err = platform_driver_register(&fman_driver); +- if (err < 0) +- pr_err("Error, platform_driver_register() = %d\n", err); +- +- return err; +-} +-module_init(fman_load); +- +-static void __exit fman_unload(void) +-{ +- platform_driver_unregister(&fman_driver); +-} +-module_exit(fman_unload); +- +-MODULE_LICENSE("Dual BSD/GPL"); +-MODULE_DESCRIPTION("Freescale DPAA Frame Manager driver"); +diff --git a/drivers/net/ethernet/freescale/fman/fman.h b/drivers/net/ethernet/freescale/fman/fman.h +deleted file mode 100644 +index 57aae8d..0000000 +--- a/drivers/net/ethernet/freescale/fman/fman.h ++++ /dev/null +@@ -1,325 +0,0 @@ +-/* +- * Copyright 2008-2015 Freescale Semiconductor Inc. +- * +- * Redistribution and use in source and binary forms, with or without +- * modification, are permitted provided that the following conditions are met: +- * * Redistributions of source code must retain the above copyright +- * notice, this list of conditions and the following disclaimer. +- * * Redistributions in binary form must reproduce the above copyright +- * notice, this list of conditions and the following disclaimer in the +- * documentation and/or other materials provided with the distribution. +- * * Neither the name of Freescale Semiconductor nor the +- * names of its contributors may be used to endorse or promote products +- * derived from this software without specific prior written permission. +- * +- * +- * ALTERNATIVELY, this software may be distributed under the terms of the +- * GNU General Public License ("GPL") as published by the Free Software +- * Foundation, either version 2 of that License or (at your option) any +- * later version. +- * +- * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY +- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +- * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY +- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +- */ +- +-#ifndef __FM_H +-#define __FM_H +- +-#include +- +-/* FM Frame descriptor macros */ +-/* Frame queue Context Override */ +-#define FM_FD_CMD_FCO 0x80000000 +-#define FM_FD_CMD_RPD 0x40000000 /* Read Prepended Data */ +-#define FM_FD_CMD_DTC 0x10000000 /* Do L4 Checksum */ +- +-/* TX-Port: Unsupported Format */ +-#define FM_FD_ERR_UNSUPPORTED_FORMAT 0x04000000 +-/* TX Port: Length Error */ +-#define FM_FD_ERR_LENGTH 0x02000000 +-#define FM_FD_ERR_DMA 0x01000000 /* DMA Data error */ +- +-/* IPR frame (not error) */ +-#define FM_FD_IPR 0x00000001 +-/* IPR non-consistent-sp */ +-#define FM_FD_ERR_IPR_NCSP (0x00100000 | FM_FD_IPR) +-/* IPR error */ +-#define FM_FD_ERR_IPR (0x00200000 | FM_FD_IPR) +-/* IPR timeout */ +-#define FM_FD_ERR_IPR_TO (0x00300000 | FM_FD_IPR) +-/* TX Port: Length Error */ +-#define FM_FD_ERR_IPRE (FM_FD_ERR_IPR & ~FM_FD_IPR) +- +-/* Rx FIFO overflow, FCS error, code error, running disparity error +- * (SGMII and TBI modes), FIFO parity error. PHY Sequence error, +- * PHY error control character detected. +- */ +-#define FM_FD_ERR_PHYSICAL 0x00080000 +-/* Frame too long OR Frame size exceeds max_length_frame */ +-#define FM_FD_ERR_SIZE 0x00040000 +-/* classification discard */ +-#define FM_FD_ERR_CLS_DISCARD 0x00020000 +-/* Extract Out of Frame */ +-#define FM_FD_ERR_EXTRACTION 0x00008000 +-/* No Scheme Selected */ +-#define FM_FD_ERR_NO_SCHEME 0x00004000 +-/* Keysize Overflow */ +-#define FM_FD_ERR_KEYSIZE_OVERFLOW 0x00002000 +-/* Frame color is red */ +-#define FM_FD_ERR_COLOR_RED 0x00000800 +-/* Frame color is yellow */ +-#define FM_FD_ERR_COLOR_YELLOW 0x00000400 +-/* Parser Time out Exceed */ +-#define FM_FD_ERR_PRS_TIMEOUT 0x00000080 +-/* Invalid Soft Parser instruction */ +-#define FM_FD_ERR_PRS_ILL_INSTRUCT 0x00000040 +-/* Header error was identified during parsing */ +-#define FM_FD_ERR_PRS_HDR_ERR 0x00000020 +-/* Frame parsed beyind 256 first bytes */ +-#define FM_FD_ERR_BLOCK_LIMIT_EXCEEDED 0x00000008 +- +-/* non Frame-Manager error */ +-#define FM_FD_RX_STATUS_ERR_NON_FM 0x00400000 +- +-/* FMan driver defines */ +-#define FMAN_BMI_FIFO_UNITS 0x100 +-#define OFFSET_UNITS 16 +- +-/* BMan defines */ +-#define BM_MAX_NUM_OF_POOLS 64 /* Buffers pools */ +-#define FMAN_PORT_MAX_EXT_POOLS_NUM 8 /* External BM pools per Rx port */ +- +-struct fman; /* FMan data */ +- +-/* Enum for defining port types */ +-enum fman_port_type { +- FMAN_PORT_TYPE_TX = 0, /* TX Port */ +- FMAN_PORT_TYPE_RX, /* RX Port */ +-}; +- +-struct fman_rev_info { +- u8 major; /* Major revision */ +- u8 minor; /* Minor revision */ +-}; +- +-enum fman_exceptions { +- FMAN_EX_DMA_BUS_ERROR = 0, /* DMA bus error. */ +- FMAN_EX_DMA_READ_ECC, /* Read Buffer ECC error */ +- FMAN_EX_DMA_SYSTEM_WRITE_ECC, /* Write Buffer ECC err on sys side */ +- FMAN_EX_DMA_FM_WRITE_ECC, /* Write Buffer ECC error on FM side */ +- FMAN_EX_DMA_SINGLE_PORT_ECC, /* Single Port ECC error on FM side */ +- FMAN_EX_FPM_STALL_ON_TASKS, /* Stall of tasks on FPM */ +- FMAN_EX_FPM_SINGLE_ECC, /* Single ECC on FPM. */ +- FMAN_EX_FPM_DOUBLE_ECC, /* Double ECC error on FPM ram access */ +- FMAN_EX_QMI_SINGLE_ECC, /* Single ECC on QMI. */ +- FMAN_EX_QMI_DOUBLE_ECC, /* Double bit ECC occurred on QMI */ +- FMAN_EX_QMI_DEQ_FROM_UNKNOWN_PORTID,/* DeQ from unknown port id */ +- FMAN_EX_BMI_LIST_RAM_ECC, /* Linked List RAM ECC error */ +- FMAN_EX_BMI_STORAGE_PROFILE_ECC,/* storage profile */ +- FMAN_EX_BMI_STATISTICS_RAM_ECC,/* Statistics RAM ECC Err Enable */ +- FMAN_EX_BMI_DISPATCH_RAM_ECC, /* Dispatch RAM ECC Error Enable */ +- FMAN_EX_IRAM_ECC, /* Double bit ECC occurred on IRAM */ +- FMAN_EX_MURAM_ECC /* Double bit ECC occurred on MURAM */ +-}; +- +-/* Parse results memory layout */ +-struct fman_prs_result { +- u8 lpid; /* Logical port id */ +- u8 shimr; /* Shim header result */ +- u16 l2r; /* Layer 2 result */ +- u16 l3r; /* Layer 3 result */ +- u8 l4r; /* Layer 4 result */ +- u8 cplan; /* Classification plan id */ +- u16 nxthdr; /* Next Header */ +- u16 cksum; /* Running-sum */ +- /* Flags&fragment-offset field of the last IP-header */ +- u16 flags_frag_off; +- /* Routing type field of a IPV6 routing extension header */ +- u8 route_type; +- /* Routing Extension Header Present; last bit is IP valid */ +- u8 rhp_ip_valid; +- u8 shim_off[2]; /* Shim offset */ +- u8 ip_pid_off; /* IP PID (last IP-proto) offset */ +- u8 eth_off; /* ETH offset */ +- u8 llc_snap_off; /* LLC_SNAP offset */ +- u8 vlan_off[2]; /* VLAN offset */ +- u8 etype_off; /* ETYPE offset */ +- u8 pppoe_off; /* PPP offset */ +- u8 mpls_off[2]; /* MPLS offset */ +- u8 ip_off[2]; /* IP offset */ +- u8 gre_off; /* GRE offset */ +- u8 l4_off; /* Layer 4 offset */ +- u8 nxthdr_off; /* Parser end point */ +-}; +- +-/* A structure for defining buffer prefix area content. */ +-struct fman_buffer_prefix_content { +- /* Number of bytes to be left at the beginning of the external +- * buffer; Note that the private-area will start from the base +- * of the buffer address. +- */ +- u16 priv_data_size; +- /* true to pass the parse result to/from the FM; +- * User may use FM_PORT_GetBufferPrsResult() in +- * order to get the parser-result from a buffer. +- */ +- bool pass_prs_result; +- /* true to pass the timeStamp to/from the FM User */ +- bool pass_time_stamp; +- /* true to pass the KG hash result to/from the FM User may +- * use FM_PORT_GetBufferHashResult() in order to get the +- * parser-result from a buffer. +- */ +- bool pass_hash_result; +- /* Add all other Internal-Context information: AD, +- * hash-result, key, etc. +- */ +- u16 data_align; +-}; +- +-/* A structure of information about each of the external +- * buffer pools used by a port or storage-profile. +- */ +-struct fman_ext_pool_params { +- u8 id; /* External buffer pool id */ +- u16 size; /* External buffer pool buffer size */ +-}; +- +-/* A structure for informing the driver about the external +- * buffer pools allocated in the BM and used by a port or a +- * storage-profile. +- */ +-struct fman_ext_pools { +- u8 num_of_pools_used; /* Number of pools use by this port */ +- struct fman_ext_pool_params ext_buf_pool[FMAN_PORT_MAX_EXT_POOLS_NUM]; +- /* Parameters for each port */ +-}; +- +-/* A structure for defining BM pool depletion criteria */ +-struct fman_buf_pool_depletion { +- /* select mode in which pause frames will be sent after a +- * number of pools (all together!) are depleted +- */ +- bool pools_grp_mode_enable; +- /* the number of depleted pools that will invoke pause +- * frames transmission. +- */ +- u8 num_of_pools; +- /* For each pool, true if it should be considered for +- * depletion (Note - this pool must be used by this port!). +- */ +- bool pools_to_consider[BM_MAX_NUM_OF_POOLS]; +- /* select mode in which pause frames will be sent +- * after a single-pool is depleted; +- */ +- bool single_pool_mode_enable; +- /* For each pool, true if it should be considered +- * for depletion (Note - this pool must be used by this port!) +- */ +- bool pools_to_consider_for_single_mode[BM_MAX_NUM_OF_POOLS]; +-}; +- +-/* Enum for inter-module interrupts registration */ +-enum fman_event_modules { +- FMAN_MOD_MAC = 0, /* MAC event */ +- FMAN_MOD_FMAN_CTRL, /* FMAN Controller */ +- FMAN_MOD_DUMMY_LAST +-}; +- +-/* Enum for interrupts types */ +-enum fman_intr_type { +- FMAN_INTR_TYPE_ERR, +- FMAN_INTR_TYPE_NORMAL +-}; +- +-/* Enum for inter-module interrupts registration */ +-enum fman_inter_module_event { +- FMAN_EV_ERR_MAC0 = 0, /* MAC 0 error event */ +- FMAN_EV_ERR_MAC1, /* MAC 1 error event */ +- FMAN_EV_ERR_MAC2, /* MAC 2 error event */ +- FMAN_EV_ERR_MAC3, /* MAC 3 error event */ +- FMAN_EV_ERR_MAC4, /* MAC 4 error event */ +- FMAN_EV_ERR_MAC5, /* MAC 5 error event */ +- FMAN_EV_ERR_MAC6, /* MAC 6 error event */ +- FMAN_EV_ERR_MAC7, /* MAC 7 error event */ +- FMAN_EV_ERR_MAC8, /* MAC 8 error event */ +- FMAN_EV_ERR_MAC9, /* MAC 9 error event */ +- FMAN_EV_MAC0, /* MAC 0 event (Magic packet detection) */ +- FMAN_EV_MAC1, /* MAC 1 event (Magic packet detection) */ +- FMAN_EV_MAC2, /* MAC 2 (Magic packet detection) */ +- FMAN_EV_MAC3, /* MAC 3 (Magic packet detection) */ +- FMAN_EV_MAC4, /* MAC 4 (Magic packet detection) */ +- FMAN_EV_MAC5, /* MAC 5 (Magic packet detection) */ +- FMAN_EV_MAC6, /* MAC 6 (Magic packet detection) */ +- FMAN_EV_MAC7, /* MAC 7 (Magic packet detection) */ +- FMAN_EV_MAC8, /* MAC 8 event (Magic packet detection) */ +- FMAN_EV_MAC9, /* MAC 9 event (Magic packet detection) */ +- FMAN_EV_FMAN_CTRL_0, /* Fman controller event 0 */ +- FMAN_EV_FMAN_CTRL_1, /* Fman controller event 1 */ +- FMAN_EV_FMAN_CTRL_2, /* Fman controller event 2 */ +- FMAN_EV_FMAN_CTRL_3, /* Fman controller event 3 */ +- FMAN_EV_CNT +-}; +- +-struct fman_intr_src { +- void (*isr_cb)(void *src_arg); +- void *src_handle; +-}; +- +-/* Structure for port-FM communication during fman_port_init. */ +-struct fman_port_init_params { +- u8 port_id; /* port Id */ +- enum fman_port_type port_type; /* Port type */ +- u16 port_speed; /* Port speed */ +- u16 liodn_offset; /* Port's requested resource */ +- u8 num_of_tasks; /* Port's requested resource */ +- u8 num_of_extra_tasks; /* Port's requested resource */ +- u8 num_of_open_dmas; /* Port's requested resource */ +- u8 num_of_extra_open_dmas; /* Port's requested resource */ +- u32 size_of_fifo; /* Port's requested resource */ +- u32 extra_size_of_fifo; /* Port's requested resource */ +- u8 deq_pipeline_depth; /* Port's requested resource */ +- u16 max_frame_length; /* Port's max frame length. */ +- u16 liodn_base; +- /* LIODN base for this port, to be used together with LIODN offset. */ +-}; +- +-void fman_get_revision(struct fman *fman, struct fman_rev_info *rev_info); +- +-void fman_register_intr(struct fman *fman, enum fman_event_modules mod, +- u8 mod_id, enum fman_intr_type intr_type, +- void (*f_isr)(void *h_src_arg), void *h_src_arg); +- +-void fman_unregister_intr(struct fman *fman, enum fman_event_modules mod, +- u8 mod_id, enum fman_intr_type intr_type); +- +-int fman_set_port_params(struct fman *fman, +- struct fman_port_init_params *port_params); +- +-int fman_reset_mac(struct fman *fman, u8 mac_id); +- +-u16 fman_get_clock_freq(struct fman *fman); +- +-u32 fman_get_bmi_max_fifo_size(struct fman *fman); +- +-int fman_set_mac_max_frame(struct fman *fman, u8 mac_id, u16 mfl); +- +-u32 fman_get_qman_channel_id(struct fman *fman, u32 port_id); +- +-struct resource *fman_get_mem_region(struct fman *fman); +- +-u16 fman_get_max_frm(void); +- +-int fman_get_rx_extra_headroom(void); +- +-struct fman *fman_bind(struct device *dev); +- +-#endif /* __FM_H */ +diff --git a/drivers/net/ethernet/freescale/fman/fman_dtsec.c b/drivers/net/ethernet/freescale/fman/fman_dtsec.c +deleted file mode 100644 +index c88918c..0000000 +--- a/drivers/net/ethernet/freescale/fman/fman_dtsec.c ++++ /dev/null +@@ -1,1451 +0,0 @@ +-/* +- * Copyright 2008-2015 Freescale Semiconductor Inc. +- * +- * Redistribution and use in source and binary forms, with or without +- * modification, are permitted provided that the following conditions are met: +- * * Redistributions of source code must retain the above copyright +- * notice, this list of conditions and the following disclaimer. +- * * Redistributions in binary form must reproduce the above copyright +- * notice, this list of conditions and the following disclaimer in the +- * documentation and/or other materials provided with the distribution. +- * * Neither the name of Freescale Semiconductor nor the +- * names of its contributors may be used to endorse or promote products +- * derived from this software without specific prior written permission. +- * +- * +- * ALTERNATIVELY, this software may be distributed under the terms of the +- * GNU General Public License ("GPL") as published by the Free Software +- * Foundation, either version 2 of that License or (at your option) any +- * later version. +- * +- * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY +- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +- * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY +- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +- */ +- +-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +- +-#include "fman_dtsec.h" +-#include "fman.h" +- +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-/* TBI register addresses */ +-#define MII_TBICON 0x11 +- +-/* TBICON register bit fields */ +-#define TBICON_SOFT_RESET 0x8000 /* Soft reset */ +-#define TBICON_DISABLE_RX_DIS 0x2000 /* Disable receive disparity */ +-#define TBICON_DISABLE_TX_DIS 0x1000 /* Disable transmit disparity */ +-#define TBICON_AN_SENSE 0x0100 /* Auto-negotiation sense enable */ +-#define TBICON_CLK_SELECT 0x0020 /* Clock select */ +-#define TBICON_MI_MODE 0x0010 /* GMII mode (TBI if not set) */ +- +-#define TBIANA_SGMII 0x4001 +-#define TBIANA_1000X 0x01a0 +- +-/* Interrupt Mask Register (IMASK) */ +-#define DTSEC_IMASK_BREN 0x80000000 +-#define DTSEC_IMASK_RXCEN 0x40000000 +-#define DTSEC_IMASK_MSROEN 0x04000000 +-#define DTSEC_IMASK_GTSCEN 0x02000000 +-#define DTSEC_IMASK_BTEN 0x01000000 +-#define DTSEC_IMASK_TXCEN 0x00800000 +-#define DTSEC_IMASK_TXEEN 0x00400000 +-#define DTSEC_IMASK_LCEN 0x00040000 +-#define DTSEC_IMASK_CRLEN 0x00020000 +-#define DTSEC_IMASK_XFUNEN 0x00010000 +-#define DTSEC_IMASK_ABRTEN 0x00008000 +-#define DTSEC_IMASK_IFERREN 0x00004000 +-#define DTSEC_IMASK_MAGEN 0x00000800 +-#define DTSEC_IMASK_MMRDEN 0x00000400 +-#define DTSEC_IMASK_MMWREN 0x00000200 +-#define DTSEC_IMASK_GRSCEN 0x00000100 +-#define DTSEC_IMASK_TDPEEN 0x00000002 +-#define DTSEC_IMASK_RDPEEN 0x00000001 +- +-#define DTSEC_EVENTS_MASK \ +- ((u32)(DTSEC_IMASK_BREN | \ +- DTSEC_IMASK_RXCEN | \ +- DTSEC_IMASK_BTEN | \ +- DTSEC_IMASK_TXCEN | \ +- DTSEC_IMASK_TXEEN | \ +- DTSEC_IMASK_ABRTEN | \ +- DTSEC_IMASK_LCEN | \ +- DTSEC_IMASK_CRLEN | \ +- DTSEC_IMASK_XFUNEN | \ +- DTSEC_IMASK_IFERREN | \ +- DTSEC_IMASK_MAGEN | \ +- DTSEC_IMASK_TDPEEN | \ +- DTSEC_IMASK_RDPEEN)) +- +-/* dtsec timestamp event bits */ +-#define TMR_PEMASK_TSREEN 0x00010000 +-#define TMR_PEVENT_TSRE 0x00010000 +- +-/* Group address bit indication */ +-#define MAC_GROUP_ADDRESS 0x0000010000000000ULL +- +-/* Defaults */ +-#define DEFAULT_HALFDUP_RETRANSMIT 0xf +-#define DEFAULT_HALFDUP_COLL_WINDOW 0x37 +-#define DEFAULT_TX_PAUSE_TIME 0xf000 +-#define DEFAULT_RX_PREPEND 0 +-#define DEFAULT_PREAMBLE_LEN 7 +-#define DEFAULT_TX_PAUSE_TIME_EXTD 0 +-#define DEFAULT_NON_BACK_TO_BACK_IPG1 0x40 +-#define DEFAULT_NON_BACK_TO_BACK_IPG2 0x60 +-#define DEFAULT_MIN_IFG_ENFORCEMENT 0x50 +-#define DEFAULT_BACK_TO_BACK_IPG 0x60 +-#define DEFAULT_MAXIMUM_FRAME 0x600 +- +-/* register related defines (bits, field offsets..) */ +-#define DTSEC_ID2_INT_REDUCED_OFF 0x00010000 +- +-#define DTSEC_ECNTRL_GMIIM 0x00000040 +-#define DTSEC_ECNTRL_TBIM 0x00000020 +-#define DTSEC_ECNTRL_SGMIIM 0x00000002 +-#define DTSEC_ECNTRL_RPM 0x00000010 +-#define DTSEC_ECNTRL_R100M 0x00000008 +-#define DTSEC_ECNTRL_QSGMIIM 0x00000001 +- +-#define DTSEC_TCTRL_GTS 0x00000020 +- +-#define RCTRL_PAL_MASK 0x001f0000 +-#define RCTRL_PAL_SHIFT 16 +-#define RCTRL_GHTX 0x00000400 +-#define RCTRL_GRS 0x00000020 +-#define RCTRL_MPROM 0x00000008 +-#define RCTRL_RSF 0x00000004 +-#define RCTRL_UPROM 0x00000001 +- +-#define MACCFG1_SOFT_RESET 0x80000000 +-#define MACCFG1_RX_FLOW 0x00000020 +-#define MACCFG1_TX_FLOW 0x00000010 +-#define MACCFG1_TX_EN 0x00000001 +-#define MACCFG1_RX_EN 0x00000004 +- +-#define MACCFG2_NIBBLE_MODE 0x00000100 +-#define MACCFG2_BYTE_MODE 0x00000200 +-#define MACCFG2_PAD_CRC_EN 0x00000004 +-#define MACCFG2_FULL_DUPLEX 0x00000001 +-#define MACCFG2_PREAMBLE_LENGTH_MASK 0x0000f000 +-#define MACCFG2_PREAMBLE_LENGTH_SHIFT 12 +- +-#define IPGIFG_NON_BACK_TO_BACK_IPG_1_SHIFT 24 +-#define IPGIFG_NON_BACK_TO_BACK_IPG_2_SHIFT 16 +-#define IPGIFG_MIN_IFG_ENFORCEMENT_SHIFT 8 +- +-#define IPGIFG_NON_BACK_TO_BACK_IPG_1 0x7F000000 +-#define IPGIFG_NON_BACK_TO_BACK_IPG_2 0x007F0000 +-#define IPGIFG_MIN_IFG_ENFORCEMENT 0x0000FF00 +-#define IPGIFG_BACK_TO_BACK_IPG 0x0000007F +- +-#define HAFDUP_EXCESS_DEFER 0x00010000 +-#define HAFDUP_COLLISION_WINDOW 0x000003ff +-#define HAFDUP_RETRANSMISSION_MAX_SHIFT 12 +-#define HAFDUP_RETRANSMISSION_MAX 0x0000f000 +- +-#define NUM_OF_HASH_REGS 8 /* Number of hash table registers */ +- +-#define PTV_PTE_MASK 0xffff0000 +-#define PTV_PT_MASK 0x0000ffff +-#define PTV_PTE_SHIFT 16 +- +-#define MAX_PACKET_ALIGNMENT 31 +-#define MAX_INTER_PACKET_GAP 0x7f +-#define MAX_RETRANSMISSION 0x0f +-#define MAX_COLLISION_WINDOW 0x03ff +- +-/* Hash table size (32 bits*8 regs) */ +-#define DTSEC_HASH_TABLE_SIZE 256 +-/* Extended Hash table size (32 bits*16 regs) */ +-#define EXTENDED_HASH_TABLE_SIZE 512 +- +-/* dTSEC Memory Map registers */ +-struct dtsec_regs { +- /* dTSEC General Control and Status Registers */ +- u32 tsec_id; /* 0x000 ETSEC_ID register */ +- u32 tsec_id2; /* 0x004 ETSEC_ID2 register */ +- u32 ievent; /* 0x008 Interrupt event register */ +- u32 imask; /* 0x00C Interrupt mask register */ +- u32 reserved0010[1]; +- u32 ecntrl; /* 0x014 E control register */ +- u32 ptv; /* 0x018 Pause time value register */ +- u32 tbipa; /* 0x01C TBI PHY address register */ +- u32 tmr_ctrl; /* 0x020 Time-stamp Control register */ +- u32 tmr_pevent; /* 0x024 Time-stamp event register */ +- u32 tmr_pemask; /* 0x028 Timer event mask register */ +- u32 reserved002c[5]; +- u32 tctrl; /* 0x040 Transmit control register */ +- u32 reserved0044[3]; +- u32 rctrl; /* 0x050 Receive control register */ +- u32 reserved0054[11]; +- u32 igaddr[8]; /* 0x080-0x09C Individual/group address */ +- u32 gaddr[8]; /* 0x0A0-0x0BC Group address registers 0-7 */ +- u32 reserved00c0[16]; +- u32 maccfg1; /* 0x100 MAC configuration #1 */ +- u32 maccfg2; /* 0x104 MAC configuration #2 */ +- u32 ipgifg; /* 0x108 IPG/IFG */ +- u32 hafdup; /* 0x10C Half-duplex */ +- u32 maxfrm; /* 0x110 Maximum frame */ +- u32 reserved0114[10]; +- u32 ifstat; /* 0x13C Interface status */ +- u32 macstnaddr1; /* 0x140 Station Address,part 1 */ +- u32 macstnaddr2; /* 0x144 Station Address,part 2 */ +- struct { +- u32 exact_match1; /* octets 1-4 */ +- u32 exact_match2; /* octets 5-6 */ +- } macaddr[15]; /* 0x148-0x1BC mac exact match addresses 1-15 */ +- u32 reserved01c0[16]; +- u32 tr64; /* 0x200 Tx and Rx 64 byte frame counter */ +- u32 tr127; /* 0x204 Tx and Rx 65 to 127 byte frame counter */ +- u32 tr255; /* 0x208 Tx and Rx 128 to 255 byte frame counter */ +- u32 tr511; /* 0x20C Tx and Rx 256 to 511 byte frame counter */ +- u32 tr1k; /* 0x210 Tx and Rx 512 to 1023 byte frame counter */ +- u32 trmax; /* 0x214 Tx and Rx 1024 to 1518 byte frame counter */ +- u32 trmgv; +- /* 0x218 Tx and Rx 1519 to 1522 byte good VLAN frame count */ +- u32 rbyt; /* 0x21C receive byte counter */ +- u32 rpkt; /* 0x220 receive packet counter */ +- u32 rfcs; /* 0x224 receive FCS error counter */ +- u32 rmca; /* 0x228 RMCA Rx multicast packet counter */ +- u32 rbca; /* 0x22C Rx broadcast packet counter */ +- u32 rxcf; /* 0x230 Rx control frame packet counter */ +- u32 rxpf; /* 0x234 Rx pause frame packet counter */ +- u32 rxuo; /* 0x238 Rx unknown OP code counter */ +- u32 raln; /* 0x23C Rx alignment error counter */ +- u32 rflr; /* 0x240 Rx frame length error counter */ +- u32 rcde; /* 0x244 Rx code error counter */ +- u32 rcse; /* 0x248 Rx carrier sense error counter */ +- u32 rund; /* 0x24C Rx undersize packet counter */ +- u32 rovr; /* 0x250 Rx oversize packet counter */ +- u32 rfrg; /* 0x254 Rx fragments counter */ +- u32 rjbr; /* 0x258 Rx jabber counter */ +- u32 rdrp; /* 0x25C Rx drop */ +- u32 tbyt; /* 0x260 Tx byte counter */ +- u32 tpkt; /* 0x264 Tx packet counter */ +- u32 tmca; /* 0x268 Tx multicast packet counter */ +- u32 tbca; /* 0x26C Tx broadcast packet counter */ +- u32 txpf; /* 0x270 Tx pause control frame counter */ +- u32 tdfr; /* 0x274 Tx deferral packet counter */ +- u32 tedf; /* 0x278 Tx excessive deferral packet counter */ +- u32 tscl; /* 0x27C Tx single collision packet counter */ +- u32 tmcl; /* 0x280 Tx multiple collision packet counter */ +- u32 tlcl; /* 0x284 Tx late collision packet counter */ +- u32 txcl; /* 0x288 Tx excessive collision packet counter */ +- u32 tncl; /* 0x28C Tx total collision counter */ +- u32 reserved0290[1]; +- u32 tdrp; /* 0x294 Tx drop frame counter */ +- u32 tjbr; /* 0x298 Tx jabber frame counter */ +- u32 tfcs; /* 0x29C Tx FCS error counter */ +- u32 txcf; /* 0x2A0 Tx control frame counter */ +- u32 tovr; /* 0x2A4 Tx oversize frame counter */ +- u32 tund; /* 0x2A8 Tx undersize frame counter */ +- u32 tfrg; /* 0x2AC Tx fragments frame counter */ +- u32 car1; /* 0x2B0 carry register one register* */ +- u32 car2; /* 0x2B4 carry register two register* */ +- u32 cam1; /* 0x2B8 carry register one mask register */ +- u32 cam2; /* 0x2BC carry register two mask register */ +- u32 reserved02c0[848]; +-}; +- +-/* struct dtsec_cfg - dTSEC configuration +- * Transmit half-duplex flow control, under software control for 10/100-Mbps +- * half-duplex media. If set, back pressure is applied to media by raising +- * carrier. +- * halfdup_retransmit: +- * Number of retransmission attempts following a collision. +- * If this is exceeded dTSEC aborts transmission due to excessive collisions. +- * The standard specifies the attempt limit to be 15. +- * halfdup_coll_window: +- * The number of bytes of the frame during which collisions may occur. +- * The default value of 55 corresponds to the frame byte at the end of the +- * standard 512-bit slot time window. If collisions are detected after this +- * byte, the late collision event is asserted and transmission of current +- * frame is aborted. +- * tx_pad_crc: +- * Pad and append CRC. If set, the MAC pads all ransmitted short frames and +- * appends a CRC to every frame regardless of padding requirement. +- * tx_pause_time: +- * Transmit pause time value. This pause value is used as part of the pause +- * frame to be sent when a transmit pause frame is initiated. +- * If set to 0 this disables transmission of pause frames. +- * preamble_len: +- * Length, in bytes, of the preamble field preceding each Ethernet +- * start-of-frame delimiter byte. The default value of 0x7 should be used in +- * order to guarantee reliable operation with IEEE 802.3 compliant hardware. +- * rx_prepend: +- * Packet alignment padding length. The specified number of bytes (1-31) +- * of zero padding are inserted before the start of each received frame. +- * For Ethernet, where optional preamble extraction is enabled, the padding +- * appears before the preamble, otherwise the padding precedes the +- * layer 2 header. +- * +- * This structure contains basic dTSEC configuration and must be passed to +- * init() function. A default set of configuration values can be +- * obtained by calling set_dflts(). +- */ +-struct dtsec_cfg { +- u16 halfdup_retransmit; +- u16 halfdup_coll_window; +- bool tx_pad_crc; +- u16 tx_pause_time; +- bool ptp_tsu_en; +- bool ptp_exception_en; +- u32 preamble_len; +- u32 rx_prepend; +- u16 tx_pause_time_extd; +- u16 maximum_frame; +- u32 non_back_to_back_ipg1; +- u32 non_back_to_back_ipg2; +- u32 min_ifg_enforcement; +- u32 back_to_back_ipg; +-}; +- +-struct fman_mac { +- /* pointer to dTSEC memory mapped registers */ +- struct dtsec_regs __iomem *regs; +- /* MAC address of device */ +- u64 addr; +- /* Ethernet physical interface */ +- phy_interface_t phy_if; +- u16 max_speed; +- void *dev_id; /* device cookie used by the exception cbs */ +- fman_mac_exception_cb *exception_cb; +- fman_mac_exception_cb *event_cb; +- /* Number of individual addresses in registers for this station */ +- u8 num_of_ind_addr_in_regs; +- /* pointer to driver's global address hash table */ +- struct eth_hash_t *multicast_addr_hash; +- /* pointer to driver's individual address hash table */ +- struct eth_hash_t *unicast_addr_hash; +- u8 mac_id; +- u32 exceptions; +- bool ptp_tsu_enabled; +- bool en_tsu_err_exeption; +- struct dtsec_cfg *dtsec_drv_param; +- void *fm; +- struct fman_rev_info fm_rev_info; +- bool basex_if; +- struct phy_device *tbiphy; +-}; +- +-static void set_dflts(struct dtsec_cfg *cfg) +-{ +- cfg->halfdup_retransmit = DEFAULT_HALFDUP_RETRANSMIT; +- cfg->halfdup_coll_window = DEFAULT_HALFDUP_COLL_WINDOW; +- cfg->tx_pad_crc = true; +- cfg->tx_pause_time = DEFAULT_TX_PAUSE_TIME; +- /* PHY address 0 is reserved (DPAA RM) */ +- cfg->rx_prepend = DEFAULT_RX_PREPEND; +- cfg->ptp_tsu_en = true; +- cfg->ptp_exception_en = true; +- cfg->preamble_len = DEFAULT_PREAMBLE_LEN; +- cfg->tx_pause_time_extd = DEFAULT_TX_PAUSE_TIME_EXTD; +- cfg->non_back_to_back_ipg1 = DEFAULT_NON_BACK_TO_BACK_IPG1; +- cfg->non_back_to_back_ipg2 = DEFAULT_NON_BACK_TO_BACK_IPG2; +- cfg->min_ifg_enforcement = DEFAULT_MIN_IFG_ENFORCEMENT; +- cfg->back_to_back_ipg = DEFAULT_BACK_TO_BACK_IPG; +- cfg->maximum_frame = DEFAULT_MAXIMUM_FRAME; +-} +- +-static int init(struct dtsec_regs __iomem *regs, struct dtsec_cfg *cfg, +- phy_interface_t iface, u16 iface_speed, u8 *macaddr, +- u32 exception_mask, u8 tbi_addr) +-{ +- bool is_rgmii, is_sgmii, is_qsgmii; +- int i; +- u32 tmp; +- +- /* Soft reset */ +- iowrite32be(MACCFG1_SOFT_RESET, ®s->maccfg1); +- iowrite32be(0, ®s->maccfg1); +- +- /* dtsec_id2 */ +- tmp = ioread32be(®s->tsec_id2); +- +- /* check RGMII support */ +- if (iface == PHY_INTERFACE_MODE_RGMII || +- iface == PHY_INTERFACE_MODE_RMII) +- if (tmp & DTSEC_ID2_INT_REDUCED_OFF) +- return -EINVAL; +- +- if (iface == PHY_INTERFACE_MODE_SGMII || +- iface == PHY_INTERFACE_MODE_MII) +- if (tmp & DTSEC_ID2_INT_REDUCED_OFF) +- return -EINVAL; +- +- is_rgmii = iface == PHY_INTERFACE_MODE_RGMII; +- is_sgmii = iface == PHY_INTERFACE_MODE_SGMII; +- is_qsgmii = iface == PHY_INTERFACE_MODE_QSGMII; +- +- tmp = 0; +- if (is_rgmii || iface == PHY_INTERFACE_MODE_GMII) +- tmp |= DTSEC_ECNTRL_GMIIM; +- if (is_sgmii) +- tmp |= (DTSEC_ECNTRL_SGMIIM | DTSEC_ECNTRL_TBIM); +- if (is_qsgmii) +- tmp |= (DTSEC_ECNTRL_SGMIIM | DTSEC_ECNTRL_TBIM | +- DTSEC_ECNTRL_QSGMIIM); +- if (is_rgmii) +- tmp |= DTSEC_ECNTRL_RPM; +- if (iface_speed == SPEED_100) +- tmp |= DTSEC_ECNTRL_R100M; +- +- iowrite32be(tmp, ®s->ecntrl); +- +- tmp = 0; +- +- if (cfg->tx_pause_time) +- tmp |= cfg->tx_pause_time; +- if (cfg->tx_pause_time_extd) +- tmp |= cfg->tx_pause_time_extd << PTV_PTE_SHIFT; +- iowrite32be(tmp, ®s->ptv); +- +- tmp = 0; +- tmp |= (cfg->rx_prepend << RCTRL_PAL_SHIFT) & RCTRL_PAL_MASK; +- /* Accept short frames */ +- tmp |= RCTRL_RSF; +- +- iowrite32be(tmp, ®s->rctrl); +- +- /* Assign a Phy Address to the TBI (TBIPA). +- * Done also in cases where TBI is not selected to avoid conflict with +- * the external PHY's Physical address +- */ +- iowrite32be(tbi_addr, ®s->tbipa); +- +- iowrite32be(0, ®s->tmr_ctrl); +- +- if (cfg->ptp_tsu_en) { +- tmp = 0; +- tmp |= TMR_PEVENT_TSRE; +- iowrite32be(tmp, ®s->tmr_pevent); +- +- if (cfg->ptp_exception_en) { +- tmp = 0; +- tmp |= TMR_PEMASK_TSREEN; +- iowrite32be(tmp, ®s->tmr_pemask); +- } +- } +- +- tmp = 0; +- tmp |= MACCFG1_RX_FLOW; +- tmp |= MACCFG1_TX_FLOW; +- iowrite32be(tmp, ®s->maccfg1); +- +- tmp = 0; +- +- if (iface_speed < SPEED_1000) +- tmp |= MACCFG2_NIBBLE_MODE; +- else if (iface_speed == SPEED_1000) +- tmp |= MACCFG2_BYTE_MODE; +- +- tmp |= (cfg->preamble_len << MACCFG2_PREAMBLE_LENGTH_SHIFT) & +- MACCFG2_PREAMBLE_LENGTH_MASK; +- if (cfg->tx_pad_crc) +- tmp |= MACCFG2_PAD_CRC_EN; +- /* Full Duplex */ +- tmp |= MACCFG2_FULL_DUPLEX; +- iowrite32be(tmp, ®s->maccfg2); +- +- tmp = (((cfg->non_back_to_back_ipg1 << +- IPGIFG_NON_BACK_TO_BACK_IPG_1_SHIFT) +- & IPGIFG_NON_BACK_TO_BACK_IPG_1) +- | ((cfg->non_back_to_back_ipg2 << +- IPGIFG_NON_BACK_TO_BACK_IPG_2_SHIFT) +- & IPGIFG_NON_BACK_TO_BACK_IPG_2) +- | ((cfg->min_ifg_enforcement << IPGIFG_MIN_IFG_ENFORCEMENT_SHIFT) +- & IPGIFG_MIN_IFG_ENFORCEMENT) +- | (cfg->back_to_back_ipg & IPGIFG_BACK_TO_BACK_IPG)); +- iowrite32be(tmp, ®s->ipgifg); +- +- tmp = 0; +- tmp |= HAFDUP_EXCESS_DEFER; +- tmp |= ((cfg->halfdup_retransmit << HAFDUP_RETRANSMISSION_MAX_SHIFT) +- & HAFDUP_RETRANSMISSION_MAX); +- tmp |= (cfg->halfdup_coll_window & HAFDUP_COLLISION_WINDOW); +- +- iowrite32be(tmp, ®s->hafdup); +- +- /* Initialize Maximum frame length */ +- iowrite32be(cfg->maximum_frame, ®s->maxfrm); +- +- iowrite32be(0xffffffff, ®s->cam1); +- iowrite32be(0xffffffff, ®s->cam2); +- +- iowrite32be(exception_mask, ®s->imask); +- +- iowrite32be(0xffffffff, ®s->ievent); +- +- tmp = (u32)((macaddr[5] << 24) | +- (macaddr[4] << 16) | (macaddr[3] << 8) | macaddr[2]); +- iowrite32be(tmp, ®s->macstnaddr1); +- +- tmp = (u32)((macaddr[1] << 24) | (macaddr[0] << 16)); +- iowrite32be(tmp, ®s->macstnaddr2); +- +- /* HASH */ +- for (i = 0; i < NUM_OF_HASH_REGS; i++) { +- /* Initialize IADDRx */ +- iowrite32be(0, ®s->igaddr[i]); +- /* Initialize GADDRx */ +- iowrite32be(0, ®s->gaddr[i]); +- } +- +- return 0; +-} +- +-static void set_mac_address(struct dtsec_regs __iomem *regs, u8 *adr) +-{ +- u32 tmp; +- +- tmp = (u32)((adr[5] << 24) | +- (adr[4] << 16) | (adr[3] << 8) | adr[2]); +- iowrite32be(tmp, ®s->macstnaddr1); +- +- tmp = (u32)((adr[1] << 24) | (adr[0] << 16)); +- iowrite32be(tmp, ®s->macstnaddr2); +-} +- +-static void set_bucket(struct dtsec_regs __iomem *regs, int bucket, +- bool enable) +-{ +- int reg_idx = (bucket >> 5) & 0xf; +- int bit_idx = bucket & 0x1f; +- u32 bit_mask = 0x80000000 >> bit_idx; +- u32 __iomem *reg; +- +- if (reg_idx > 7) +- reg = ®s->gaddr[reg_idx - 8]; +- else +- reg = ®s->igaddr[reg_idx]; +- +- if (enable) +- iowrite32be(ioread32be(reg) | bit_mask, reg); +- else +- iowrite32be(ioread32be(reg) & (~bit_mask), reg); +-} +- +-static int check_init_parameters(struct fman_mac *dtsec) +-{ +- if (dtsec->max_speed >= SPEED_10000) { +- pr_err("1G MAC driver supports 1G or lower speeds\n"); +- return -EINVAL; +- } +- if (dtsec->addr == 0) { +- pr_err("Ethernet MAC Must have a valid MAC Address\n"); +- return -EINVAL; +- } +- if ((dtsec->dtsec_drv_param)->rx_prepend > +- MAX_PACKET_ALIGNMENT) { +- pr_err("packetAlignmentPadding can't be > than %d\n", +- MAX_PACKET_ALIGNMENT); +- return -EINVAL; +- } +- if (((dtsec->dtsec_drv_param)->non_back_to_back_ipg1 > +- MAX_INTER_PACKET_GAP) || +- ((dtsec->dtsec_drv_param)->non_back_to_back_ipg2 > +- MAX_INTER_PACKET_GAP) || +- ((dtsec->dtsec_drv_param)->back_to_back_ipg > +- MAX_INTER_PACKET_GAP)) { +- pr_err("Inter packet gap can't be greater than %d\n", +- MAX_INTER_PACKET_GAP); +- return -EINVAL; +- } +- if ((dtsec->dtsec_drv_param)->halfdup_retransmit > +- MAX_RETRANSMISSION) { +- pr_err("maxRetransmission can't be greater than %d\n", +- MAX_RETRANSMISSION); +- return -EINVAL; +- } +- if ((dtsec->dtsec_drv_param)->halfdup_coll_window > +- MAX_COLLISION_WINDOW) { +- pr_err("collisionWindow can't be greater than %d\n", +- MAX_COLLISION_WINDOW); +- return -EINVAL; +- /* If Auto negotiation process is disabled, need to set up the PHY +- * using the MII Management Interface +- */ +- } +- if (!dtsec->exception_cb) { +- pr_err("uninitialized exception_cb\n"); +- return -EINVAL; +- } +- if (!dtsec->event_cb) { +- pr_err("uninitialized event_cb\n"); +- return -EINVAL; +- } +- +- return 0; +-} +- +-static int get_exception_flag(enum fman_mac_exceptions exception) +-{ +- u32 bit_mask; +- +- switch (exception) { +- case FM_MAC_EX_1G_BAB_RX: +- bit_mask = DTSEC_IMASK_BREN; +- break; +- case FM_MAC_EX_1G_RX_CTL: +- bit_mask = DTSEC_IMASK_RXCEN; +- break; +- case FM_MAC_EX_1G_GRATEFUL_TX_STP_COMPLET: +- bit_mask = DTSEC_IMASK_GTSCEN; +- break; +- case FM_MAC_EX_1G_BAB_TX: +- bit_mask = DTSEC_IMASK_BTEN; +- break; +- case FM_MAC_EX_1G_TX_CTL: +- bit_mask = DTSEC_IMASK_TXCEN; +- break; +- case FM_MAC_EX_1G_TX_ERR: +- bit_mask = DTSEC_IMASK_TXEEN; +- break; +- case FM_MAC_EX_1G_LATE_COL: +- bit_mask = DTSEC_IMASK_LCEN; +- break; +- case FM_MAC_EX_1G_COL_RET_LMT: +- bit_mask = DTSEC_IMASK_CRLEN; +- break; +- case FM_MAC_EX_1G_TX_FIFO_UNDRN: +- bit_mask = DTSEC_IMASK_XFUNEN; +- break; +- case FM_MAC_EX_1G_MAG_PCKT: +- bit_mask = DTSEC_IMASK_MAGEN; +- break; +- case FM_MAC_EX_1G_MII_MNG_RD_COMPLET: +- bit_mask = DTSEC_IMASK_MMRDEN; +- break; +- case FM_MAC_EX_1G_MII_MNG_WR_COMPLET: +- bit_mask = DTSEC_IMASK_MMWREN; +- break; +- case FM_MAC_EX_1G_GRATEFUL_RX_STP_COMPLET: +- bit_mask = DTSEC_IMASK_GRSCEN; +- break; +- case FM_MAC_EX_1G_DATA_ERR: +- bit_mask = DTSEC_IMASK_TDPEEN; +- break; +- case FM_MAC_EX_1G_RX_MIB_CNT_OVFL: +- bit_mask = DTSEC_IMASK_MSROEN; +- break; +- default: +- bit_mask = 0; +- break; +- } +- +- return bit_mask; +-} +- +-static bool is_init_done(struct dtsec_cfg *dtsec_drv_params) +-{ +- /* Checks if dTSEC driver parameters were initialized */ +- if (!dtsec_drv_params) +- return true; +- +- return false; +-} +- +-static u16 dtsec_get_max_frame_length(struct fman_mac *dtsec) +-{ +- struct dtsec_regs __iomem *regs = dtsec->regs; +- +- if (is_init_done(dtsec->dtsec_drv_param)) +- return 0; +- +- return (u16)ioread32be(®s->maxfrm); +-} +- +-static void dtsec_isr(void *handle) +-{ +- struct fman_mac *dtsec = (struct fman_mac *)handle; +- struct dtsec_regs __iomem *regs = dtsec->regs; +- u32 event; +- +- /* do not handle MDIO events */ +- event = ioread32be(®s->ievent) & +- (u32)(~(DTSEC_IMASK_MMRDEN | DTSEC_IMASK_MMWREN)); +- +- event &= ioread32be(®s->imask); +- +- iowrite32be(event, ®s->ievent); +- +- if (event & DTSEC_IMASK_BREN) +- dtsec->exception_cb(dtsec->dev_id, FM_MAC_EX_1G_BAB_RX); +- if (event & DTSEC_IMASK_RXCEN) +- dtsec->exception_cb(dtsec->dev_id, FM_MAC_EX_1G_RX_CTL); +- if (event & DTSEC_IMASK_GTSCEN) +- dtsec->exception_cb(dtsec->dev_id, +- FM_MAC_EX_1G_GRATEFUL_TX_STP_COMPLET); +- if (event & DTSEC_IMASK_BTEN) +- dtsec->exception_cb(dtsec->dev_id, FM_MAC_EX_1G_BAB_TX); +- if (event & DTSEC_IMASK_TXCEN) +- dtsec->exception_cb(dtsec->dev_id, FM_MAC_EX_1G_TX_CTL); +- if (event & DTSEC_IMASK_TXEEN) +- dtsec->exception_cb(dtsec->dev_id, FM_MAC_EX_1G_TX_ERR); +- if (event & DTSEC_IMASK_LCEN) +- dtsec->exception_cb(dtsec->dev_id, FM_MAC_EX_1G_LATE_COL); +- if (event & DTSEC_IMASK_CRLEN) +- dtsec->exception_cb(dtsec->dev_id, FM_MAC_EX_1G_COL_RET_LMT); +- if (event & DTSEC_IMASK_XFUNEN) { +- /* FM_TX_LOCKUP_ERRATA_DTSEC6 Errata workaround */ +- if (dtsec->fm_rev_info.major == 2) { +- u32 tpkt1, tmp_reg1, tpkt2, tmp_reg2, i; +- /* a. Write 0x00E0_0C00 to DTSEC_ID +- * This is a read only register +- * b. Read and save the value of TPKT +- */ +- tpkt1 = ioread32be(®s->tpkt); +- +- /* c. Read the register at dTSEC address offset 0x32C */ +- tmp_reg1 = ioread32be(®s->reserved02c0[27]); +- +- /* d. Compare bits [9:15] to bits [25:31] of the +- * register at address offset 0x32C. +- */ +- if ((tmp_reg1 & 0x007F0000) != +- (tmp_reg1 & 0x0000007F)) { +- /* If they are not equal, save the value of +- * this register and wait for at least +- * MAXFRM*16 ns +- */ +- usleep_range((u32)(min +- (dtsec_get_max_frame_length(dtsec) * +- 16 / 1000, 1)), (u32) +- (min(dtsec_get_max_frame_length +- (dtsec) * 16 / 1000, 1) + 1)); +- } +- +- /* e. Read and save TPKT again and read the register +- * at dTSEC address offset 0x32C again +- */ +- tpkt2 = ioread32be(®s->tpkt); +- tmp_reg2 = ioread32be(®s->reserved02c0[27]); +- +- /* f. Compare the value of TPKT saved in step b to +- * value read in step e. Also compare bits [9:15] of +- * the register at offset 0x32C saved in step d to the +- * value of bits [9:15] saved in step e. If the two +- * registers values are unchanged, then the transmit +- * portion of the dTSEC controller is locked up and +- * the user should proceed to the recover sequence. +- */ +- if ((tpkt1 == tpkt2) && ((tmp_reg1 & 0x007F0000) == +- (tmp_reg2 & 0x007F0000))) { +- /* recover sequence */ +- +- /* a.Write a 1 to RCTRL[GRS] */ +- +- iowrite32be(ioread32be(®s->rctrl) | +- RCTRL_GRS, ®s->rctrl); +- +- /* b.Wait until IEVENT[GRSC]=1, or at least +- * 100 us has elapsed. +- */ +- for (i = 0; i < 100; i++) { +- if (ioread32be(®s->ievent) & +- DTSEC_IMASK_GRSCEN) +- break; +- udelay(1); +- } +- if (ioread32be(®s->ievent) & +- DTSEC_IMASK_GRSCEN) +- iowrite32be(DTSEC_IMASK_GRSCEN, +- ®s->ievent); +- else +- pr_debug("Rx lockup due to Tx lockup\n"); +- +- /* c.Write a 1 to bit n of FM_RSTC +- * (offset 0x0CC of FPM) +- */ +- fman_reset_mac(dtsec->fm, dtsec->mac_id); +- +- /* d.Wait 4 Tx clocks (32 ns) */ +- udelay(1); +- +- /* e.Write a 0 to bit n of FM_RSTC. */ +- /* cleared by FMAN +- */ +- } +- } +- +- dtsec->exception_cb(dtsec->dev_id, FM_MAC_EX_1G_TX_FIFO_UNDRN); +- } +- if (event & DTSEC_IMASK_MAGEN) +- dtsec->exception_cb(dtsec->dev_id, FM_MAC_EX_1G_MAG_PCKT); +- if (event & DTSEC_IMASK_GRSCEN) +- dtsec->exception_cb(dtsec->dev_id, +- FM_MAC_EX_1G_GRATEFUL_RX_STP_COMPLET); +- if (event & DTSEC_IMASK_TDPEEN) +- dtsec->exception_cb(dtsec->dev_id, FM_MAC_EX_1G_DATA_ERR); +- if (event & DTSEC_IMASK_RDPEEN) +- dtsec->exception_cb(dtsec->dev_id, FM_MAC_1G_RX_DATA_ERR); +- +- /* masked interrupts */ +- WARN_ON(event & DTSEC_IMASK_ABRTEN); +- WARN_ON(event & DTSEC_IMASK_IFERREN); +-} +- +-static void dtsec_1588_isr(void *handle) +-{ +- struct fman_mac *dtsec = (struct fman_mac *)handle; +- struct dtsec_regs __iomem *regs = dtsec->regs; +- u32 event; +- +- if (dtsec->ptp_tsu_enabled) { +- event = ioread32be(®s->tmr_pevent); +- event &= ioread32be(®s->tmr_pemask); +- +- if (event) { +- iowrite32be(event, ®s->tmr_pevent); +- WARN_ON(event & TMR_PEVENT_TSRE); +- dtsec->exception_cb(dtsec->dev_id, +- FM_MAC_EX_1G_1588_TS_RX_ERR); +- } +- } +-} +- +-static void free_init_resources(struct fman_mac *dtsec) +-{ +- fman_unregister_intr(dtsec->fm, FMAN_MOD_MAC, dtsec->mac_id, +- FMAN_INTR_TYPE_ERR); +- fman_unregister_intr(dtsec->fm, FMAN_MOD_MAC, dtsec->mac_id, +- FMAN_INTR_TYPE_NORMAL); +- +- /* release the driver's group hash table */ +- free_hash_table(dtsec->multicast_addr_hash); +- dtsec->multicast_addr_hash = NULL; +- +- /* release the driver's individual hash table */ +- free_hash_table(dtsec->unicast_addr_hash); +- dtsec->unicast_addr_hash = NULL; +-} +- +-int dtsec_cfg_max_frame_len(struct fman_mac *dtsec, u16 new_val) +-{ +- if (is_init_done(dtsec->dtsec_drv_param)) +- return -EINVAL; +- +- dtsec->dtsec_drv_param->maximum_frame = new_val; +- +- return 0; +-} +- +-int dtsec_cfg_pad_and_crc(struct fman_mac *dtsec, bool new_val) +-{ +- if (is_init_done(dtsec->dtsec_drv_param)) +- return -EINVAL; +- +- dtsec->dtsec_drv_param->tx_pad_crc = new_val; +- +- return 0; +-} +- +-int dtsec_enable(struct fman_mac *dtsec, enum comm_mode mode) +-{ +- struct dtsec_regs __iomem *regs = dtsec->regs; +- u32 tmp; +- +- if (!is_init_done(dtsec->dtsec_drv_param)) +- return -EINVAL; +- +- /* Enable */ +- tmp = ioread32be(®s->maccfg1); +- if (mode & COMM_MODE_RX) +- tmp |= MACCFG1_RX_EN; +- if (mode & COMM_MODE_TX) +- tmp |= MACCFG1_TX_EN; +- +- iowrite32be(tmp, ®s->maccfg1); +- +- /* Graceful start - clear the graceful receive stop bit */ +- if (mode & COMM_MODE_TX) +- iowrite32be(ioread32be(®s->tctrl) & ~DTSEC_TCTRL_GTS, +- ®s->tctrl); +- if (mode & COMM_MODE_RX) +- iowrite32be(ioread32be(®s->rctrl) & ~RCTRL_GRS, +- ®s->rctrl); +- +- return 0; +-} +- +-int dtsec_disable(struct fman_mac *dtsec, enum comm_mode mode) +-{ +- struct dtsec_regs __iomem *regs = dtsec->regs; +- u32 tmp; +- +- if (!is_init_done(dtsec->dtsec_drv_param)) +- return -EINVAL; +- +- /* Gracefull stop - Assert the graceful transmit stop bit */ +- if (mode & COMM_MODE_RX) { +- tmp = ioread32be(®s->rctrl) | RCTRL_GRS; +- iowrite32be(tmp, ®s->rctrl); +- +- if (dtsec->fm_rev_info.major == 2) +- usleep_range(100, 200); +- else +- udelay(10); +- } +- +- if (mode & COMM_MODE_TX) { +- if (dtsec->fm_rev_info.major == 2) +- pr_debug("GTS not supported due to DTSEC_A004 errata.\n"); +- else +- pr_debug("GTS not supported due to DTSEC_A0014 errata.\n"); +- } +- +- tmp = ioread32be(®s->maccfg1); +- if (mode & COMM_MODE_RX) +- tmp &= ~MACCFG1_RX_EN; +- if (mode & COMM_MODE_TX) +- tmp &= ~MACCFG1_TX_EN; +- +- iowrite32be(tmp, ®s->maccfg1); +- +- return 0; +-} +- +-int dtsec_set_tx_pause_frames(struct fman_mac *dtsec, +- u8 __maybe_unused priority, +- u16 pause_time, u16 __maybe_unused thresh_time) +-{ +- struct dtsec_regs __iomem *regs = dtsec->regs; +- u32 ptv = 0; +- +- if (!is_init_done(dtsec->dtsec_drv_param)) +- return -EINVAL; +- +- if (pause_time) { +- /* FM_BAD_TX_TS_IN_B_2_B_ERRATA_DTSEC_A003 Errata workaround */ +- if (dtsec->fm_rev_info.major == 2 && pause_time <= 320) { +- pr_warn("pause-time: %d illegal.Should be > 320\n", +- pause_time); +- return -EINVAL; +- } +- +- ptv = ioread32be(®s->ptv); +- ptv &= PTV_PTE_MASK; +- ptv |= pause_time & PTV_PT_MASK; +- iowrite32be(ptv, ®s->ptv); +- +- /* trigger the transmission of a flow-control pause frame */ +- iowrite32be(ioread32be(®s->maccfg1) | MACCFG1_TX_FLOW, +- ®s->maccfg1); +- } else +- iowrite32be(ioread32be(®s->maccfg1) & ~MACCFG1_TX_FLOW, +- ®s->maccfg1); +- +- return 0; +-} +- +-int dtsec_accept_rx_pause_frames(struct fman_mac *dtsec, bool en) +-{ +- struct dtsec_regs __iomem *regs = dtsec->regs; +- u32 tmp; +- +- if (!is_init_done(dtsec->dtsec_drv_param)) +- return -EINVAL; +- +- tmp = ioread32be(®s->maccfg1); +- if (en) +- tmp |= MACCFG1_RX_FLOW; +- else +- tmp &= ~MACCFG1_RX_FLOW; +- iowrite32be(tmp, ®s->maccfg1); +- +- return 0; +-} +- +-int dtsec_modify_mac_address(struct fman_mac *dtsec, enet_addr_t *enet_addr) +-{ +- if (!is_init_done(dtsec->dtsec_drv_param)) +- return -EINVAL; +- +- /* Initialize MAC Station Address registers (1 & 2) +- * Station address have to be swapped (big endian to little endian +- */ +- dtsec->addr = ENET_ADDR_TO_UINT64(*enet_addr); +- set_mac_address(dtsec->regs, (u8 *)(*enet_addr)); +- +- return 0; +-} +- +-int dtsec_add_hash_mac_address(struct fman_mac *dtsec, enet_addr_t *eth_addr) +-{ +- struct dtsec_regs __iomem *regs = dtsec->regs; +- struct eth_hash_entry *hash_entry; +- u64 addr; +- s32 bucket; +- u32 crc = 0xFFFFFFFF; +- bool mcast, ghtx; +- +- if (!is_init_done(dtsec->dtsec_drv_param)) +- return -EINVAL; +- +- addr = ENET_ADDR_TO_UINT64(*eth_addr); +- +- ghtx = (bool)((ioread32be(®s->rctrl) & RCTRL_GHTX) ? true : false); +- mcast = (bool)((addr & MAC_GROUP_ADDRESS) ? true : false); +- +- /* Cannot handle unicast mac addr when GHTX is on */ +- if (ghtx && !mcast) { +- pr_err("Could not compute hash bucket\n"); +- return -EINVAL; +- } +- crc = crc32_le(crc, (u8 *)eth_addr, ETH_ALEN); +- crc = bitrev32(crc); +- +- /* considering the 9 highest order bits in crc H[8:0]: +- *if ghtx = 0 H[8:6] (highest order 3 bits) identify the hash register +- *and H[5:1] (next 5 bits) identify the hash bit +- *if ghts = 1 H[8:5] (highest order 4 bits) identify the hash register +- *and H[4:0] (next 5 bits) identify the hash bit. +- * +- *In bucket index output the low 5 bits identify the hash register +- *bit, while the higher 4 bits identify the hash register +- */ +- +- if (ghtx) { +- bucket = (s32)((crc >> 23) & 0x1ff); +- } else { +- bucket = (s32)((crc >> 24) & 0xff); +- /* if !ghtx and mcast the bit must be set in gaddr instead of +- *igaddr. +- */ +- if (mcast) +- bucket += 0x100; +- } +- +- set_bucket(dtsec->regs, bucket, true); +- +- /* Create element to be added to the driver hash table */ +- hash_entry = kmalloc(sizeof(*hash_entry), GFP_KERNEL); +- if (!hash_entry) +- return -ENOMEM; +- hash_entry->addr = addr; +- INIT_LIST_HEAD(&hash_entry->node); +- +- if (addr & MAC_GROUP_ADDRESS) +- /* Group Address */ +- list_add_tail(&hash_entry->node, +- &dtsec->multicast_addr_hash->lsts[bucket]); +- else +- list_add_tail(&hash_entry->node, +- &dtsec->unicast_addr_hash->lsts[bucket]); +- +- return 0; +-} +- +-int dtsec_del_hash_mac_address(struct fman_mac *dtsec, enet_addr_t *eth_addr) +-{ +- struct dtsec_regs __iomem *regs = dtsec->regs; +- struct list_head *pos; +- struct eth_hash_entry *hash_entry = NULL; +- u64 addr; +- s32 bucket; +- u32 crc = 0xFFFFFFFF; +- bool mcast, ghtx; +- +- if (!is_init_done(dtsec->dtsec_drv_param)) +- return -EINVAL; +- +- addr = ENET_ADDR_TO_UINT64(*eth_addr); +- +- ghtx = (bool)((ioread32be(®s->rctrl) & RCTRL_GHTX) ? true : false); +- mcast = (bool)((addr & MAC_GROUP_ADDRESS) ? true : false); +- +- /* Cannot handle unicast mac addr when GHTX is on */ +- if (ghtx && !mcast) { +- pr_err("Could not compute hash bucket\n"); +- return -EINVAL; +- } +- crc = crc32_le(crc, (u8 *)eth_addr, ETH_ALEN); +- crc = bitrev32(crc); +- +- if (ghtx) { +- bucket = (s32)((crc >> 23) & 0x1ff); +- } else { +- bucket = (s32)((crc >> 24) & 0xff); +- /* if !ghtx and mcast the bit must be set +- * in gaddr instead of igaddr. +- */ +- if (mcast) +- bucket += 0x100; +- } +- +- if (addr & MAC_GROUP_ADDRESS) { +- /* Group Address */ +- list_for_each(pos, +- &dtsec->multicast_addr_hash->lsts[bucket]) { +- hash_entry = ETH_HASH_ENTRY_OBJ(pos); +- if (hash_entry->addr == addr) { +- list_del_init(&hash_entry->node); +- kfree(hash_entry); +- break; +- } +- } +- if (list_empty(&dtsec->multicast_addr_hash->lsts[bucket])) +- set_bucket(dtsec->regs, bucket, false); +- } else { +- /* Individual Address */ +- list_for_each(pos, +- &dtsec->unicast_addr_hash->lsts[bucket]) { +- hash_entry = ETH_HASH_ENTRY_OBJ(pos); +- if (hash_entry->addr == addr) { +- list_del_init(&hash_entry->node); +- kfree(hash_entry); +- break; +- } +- } +- if (list_empty(&dtsec->unicast_addr_hash->lsts[bucket])) +- set_bucket(dtsec->regs, bucket, false); +- } +- +- /* address does not exist */ +- WARN_ON(!hash_entry); +- +- return 0; +-} +- +-int dtsec_set_promiscuous(struct fman_mac *dtsec, bool new_val) +-{ +- struct dtsec_regs __iomem *regs = dtsec->regs; +- u32 tmp; +- +- if (!is_init_done(dtsec->dtsec_drv_param)) +- return -EINVAL; +- +- /* Set unicast promiscuous */ +- tmp = ioread32be(®s->rctrl); +- if (new_val) +- tmp |= RCTRL_UPROM; +- else +- tmp &= ~RCTRL_UPROM; +- +- iowrite32be(tmp, ®s->rctrl); +- +- /* Set multicast promiscuous */ +- tmp = ioread32be(®s->rctrl); +- if (new_val) +- tmp |= RCTRL_MPROM; +- else +- tmp &= ~RCTRL_MPROM; +- +- iowrite32be(tmp, ®s->rctrl); +- +- return 0; +-} +- +-int dtsec_adjust_link(struct fman_mac *dtsec, u16 speed) +-{ +- struct dtsec_regs __iomem *regs = dtsec->regs; +- u32 tmp; +- +- if (!is_init_done(dtsec->dtsec_drv_param)) +- return -EINVAL; +- +- tmp = ioread32be(®s->maccfg2); +- +- /* Full Duplex */ +- tmp |= MACCFG2_FULL_DUPLEX; +- +- tmp &= ~(MACCFG2_NIBBLE_MODE | MACCFG2_BYTE_MODE); +- if (speed < SPEED_1000) +- tmp |= MACCFG2_NIBBLE_MODE; +- else if (speed == SPEED_1000) +- tmp |= MACCFG2_BYTE_MODE; +- iowrite32be(tmp, ®s->maccfg2); +- +- tmp = ioread32be(®s->ecntrl); +- if (speed == SPEED_100) +- tmp |= DTSEC_ECNTRL_R100M; +- else +- tmp &= ~DTSEC_ECNTRL_R100M; +- iowrite32be(tmp, ®s->ecntrl); +- +- return 0; +-} +- +-int dtsec_restart_autoneg(struct fman_mac *dtsec) +-{ +- u16 tmp_reg16; +- +- if (!is_init_done(dtsec->dtsec_drv_param)) +- return -EINVAL; +- +- tmp_reg16 = phy_read(dtsec->tbiphy, MII_BMCR); +- +- tmp_reg16 &= ~(BMCR_SPEED100 | BMCR_SPEED1000); +- tmp_reg16 |= (BMCR_ANENABLE | BMCR_ANRESTART | +- BMCR_FULLDPLX | BMCR_SPEED1000); +- +- phy_write(dtsec->tbiphy, MII_BMCR, tmp_reg16); +- +- return 0; +-} +- +-int dtsec_get_version(struct fman_mac *dtsec, u32 *mac_version) +-{ +- struct dtsec_regs __iomem *regs = dtsec->regs; +- +- if (!is_init_done(dtsec->dtsec_drv_param)) +- return -EINVAL; +- +- *mac_version = ioread32be(®s->tsec_id); +- +- return 0; +-} +- +-int dtsec_set_exception(struct fman_mac *dtsec, +- enum fman_mac_exceptions exception, bool enable) +-{ +- struct dtsec_regs __iomem *regs = dtsec->regs; +- u32 bit_mask = 0; +- +- if (!is_init_done(dtsec->dtsec_drv_param)) +- return -EINVAL; +- +- if (exception != FM_MAC_EX_1G_1588_TS_RX_ERR) { +- bit_mask = get_exception_flag(exception); +- if (bit_mask) { +- if (enable) +- dtsec->exceptions |= bit_mask; +- else +- dtsec->exceptions &= ~bit_mask; +- } else { +- pr_err("Undefined exception\n"); +- return -EINVAL; +- } +- if (enable) +- iowrite32be(ioread32be(®s->imask) | bit_mask, +- ®s->imask); +- else +- iowrite32be(ioread32be(®s->imask) & ~bit_mask, +- ®s->imask); +- } else { +- if (!dtsec->ptp_tsu_enabled) { +- pr_err("Exception valid for 1588 only\n"); +- return -EINVAL; +- } +- switch (exception) { +- case FM_MAC_EX_1G_1588_TS_RX_ERR: +- if (enable) { +- dtsec->en_tsu_err_exeption = true; +- iowrite32be(ioread32be(®s->tmr_pemask) | +- TMR_PEMASK_TSREEN, +- ®s->tmr_pemask); +- } else { +- dtsec->en_tsu_err_exeption = false; +- iowrite32be(ioread32be(®s->tmr_pemask) & +- ~TMR_PEMASK_TSREEN, +- ®s->tmr_pemask); +- } +- break; +- default: +- pr_err("Undefined exception\n"); +- return -EINVAL; +- } +- } +- +- return 0; +-} +- +-int dtsec_init(struct fman_mac *dtsec) +-{ +- struct dtsec_regs __iomem *regs = dtsec->regs; +- struct dtsec_cfg *dtsec_drv_param; +- int err; +- u16 max_frm_ln; +- enet_addr_t eth_addr; +- +- if (is_init_done(dtsec->dtsec_drv_param)) +- return -EINVAL; +- +- if (DEFAULT_RESET_ON_INIT && +- (fman_reset_mac(dtsec->fm, dtsec->mac_id) != 0)) { +- pr_err("Can't reset MAC!\n"); +- return -EINVAL; +- } +- +- err = check_init_parameters(dtsec); +- if (err) +- return err; +- +- dtsec_drv_param = dtsec->dtsec_drv_param; +- +- MAKE_ENET_ADDR_FROM_UINT64(dtsec->addr, eth_addr); +- +- err = init(dtsec->regs, dtsec_drv_param, dtsec->phy_if, +- dtsec->max_speed, (u8 *)eth_addr, dtsec->exceptions, +- dtsec->tbiphy->mdio.addr); +- if (err) { +- free_init_resources(dtsec); +- pr_err("DTSEC version doesn't support this i/f mode\n"); +- return err; +- } +- +- if (dtsec->phy_if == PHY_INTERFACE_MODE_SGMII) { +- u16 tmp_reg16; +- +- /* Configure the TBI PHY Control Register */ +- tmp_reg16 = TBICON_CLK_SELECT | TBICON_SOFT_RESET; +- phy_write(dtsec->tbiphy, MII_TBICON, tmp_reg16); +- +- tmp_reg16 = TBICON_CLK_SELECT; +- phy_write(dtsec->tbiphy, MII_TBICON, tmp_reg16); +- +- tmp_reg16 = (BMCR_RESET | BMCR_ANENABLE | +- BMCR_FULLDPLX | BMCR_SPEED1000); +- phy_write(dtsec->tbiphy, MII_BMCR, tmp_reg16); +- +- if (dtsec->basex_if) +- tmp_reg16 = TBIANA_1000X; +- else +- tmp_reg16 = TBIANA_SGMII; +- phy_write(dtsec->tbiphy, MII_ADVERTISE, tmp_reg16); +- +- tmp_reg16 = (BMCR_ANENABLE | BMCR_ANRESTART | +- BMCR_FULLDPLX | BMCR_SPEED1000); +- +- phy_write(dtsec->tbiphy, MII_BMCR, tmp_reg16); +- } +- +- /* Max Frame Length */ +- max_frm_ln = (u16)ioread32be(®s->maxfrm); +- err = fman_set_mac_max_frame(dtsec->fm, dtsec->mac_id, max_frm_ln); +- if (err) { +- pr_err("Setting max frame length failed\n"); +- free_init_resources(dtsec); +- return -EINVAL; +- } +- +- dtsec->multicast_addr_hash = +- alloc_hash_table(EXTENDED_HASH_TABLE_SIZE); +- if (!dtsec->multicast_addr_hash) { +- free_init_resources(dtsec); +- pr_err("MC hash table is failed\n"); +- return -ENOMEM; +- } +- +- dtsec->unicast_addr_hash = alloc_hash_table(DTSEC_HASH_TABLE_SIZE); +- if (!dtsec->unicast_addr_hash) { +- free_init_resources(dtsec); +- pr_err("UC hash table is failed\n"); +- return -ENOMEM; +- } +- +- /* register err intr handler for dtsec to FPM (err) */ +- fman_register_intr(dtsec->fm, FMAN_MOD_MAC, dtsec->mac_id, +- FMAN_INTR_TYPE_ERR, dtsec_isr, dtsec); +- /* register 1588 intr handler for TMR to FPM (normal) */ +- fman_register_intr(dtsec->fm, FMAN_MOD_MAC, dtsec->mac_id, +- FMAN_INTR_TYPE_NORMAL, dtsec_1588_isr, dtsec); +- +- kfree(dtsec_drv_param); +- dtsec->dtsec_drv_param = NULL; +- +- return 0; +-} +- +-int dtsec_free(struct fman_mac *dtsec) +-{ +- free_init_resources(dtsec); +- +- kfree(dtsec->dtsec_drv_param); +- dtsec->dtsec_drv_param = NULL; +- kfree(dtsec); +- +- return 0; +-} +- +-struct fman_mac *dtsec_config(struct fman_mac_params *params) +-{ +- struct fman_mac *dtsec; +- struct dtsec_cfg *dtsec_drv_param; +- void __iomem *base_addr; +- +- base_addr = params->base_addr; +- +- /* allocate memory for the UCC GETH data structure. */ +- dtsec = kzalloc(sizeof(*dtsec), GFP_KERNEL); +- if (!dtsec) +- return NULL; +- +- /* allocate memory for the d_tsec driver parameters data structure. */ +- dtsec_drv_param = kzalloc(sizeof(*dtsec_drv_param), GFP_KERNEL); +- if (!dtsec_drv_param) +- goto err_dtsec; +- +- /* Plant parameter structure pointer */ +- dtsec->dtsec_drv_param = dtsec_drv_param; +- +- set_dflts(dtsec_drv_param); +- +- dtsec->regs = base_addr; +- dtsec->addr = ENET_ADDR_TO_UINT64(params->addr); +- dtsec->max_speed = params->max_speed; +- dtsec->phy_if = params->phy_if; +- dtsec->mac_id = params->mac_id; +- dtsec->exceptions = (DTSEC_IMASK_BREN | +- DTSEC_IMASK_RXCEN | +- DTSEC_IMASK_BTEN | +- DTSEC_IMASK_TXCEN | +- DTSEC_IMASK_TXEEN | +- DTSEC_IMASK_ABRTEN | +- DTSEC_IMASK_LCEN | +- DTSEC_IMASK_CRLEN | +- DTSEC_IMASK_XFUNEN | +- DTSEC_IMASK_IFERREN | +- DTSEC_IMASK_MAGEN | +- DTSEC_IMASK_TDPEEN | +- DTSEC_IMASK_RDPEEN); +- dtsec->exception_cb = params->exception_cb; +- dtsec->event_cb = params->event_cb; +- dtsec->dev_id = params->dev_id; +- dtsec->ptp_tsu_enabled = dtsec->dtsec_drv_param->ptp_tsu_en; +- dtsec->en_tsu_err_exeption = dtsec->dtsec_drv_param->ptp_exception_en; +- +- dtsec->fm = params->fm; +- dtsec->basex_if = params->basex_if; +- +- if (!params->internal_phy_node) { +- pr_err("TBI PHY node is not available\n"); +- goto err_dtsec_drv_param; +- } +- +- dtsec->tbiphy = of_phy_find_device(params->internal_phy_node); +- if (!dtsec->tbiphy) { +- pr_err("of_phy_find_device (TBI PHY) failed\n"); +- goto err_dtsec_drv_param; +- } +- +- put_device(&dtsec->tbiphy->mdio.dev); +- +- /* Save FMan revision */ +- fman_get_revision(dtsec->fm, &dtsec->fm_rev_info); +- +- return dtsec; +- +-err_dtsec_drv_param: +- kfree(dtsec_drv_param); +-err_dtsec: +- kfree(dtsec); +- return NULL; +-} +diff --git a/drivers/net/ethernet/freescale/fman/fman_dtsec.h b/drivers/net/ethernet/freescale/fman/fman_dtsec.h +deleted file mode 100644 +index c4467c0..0000000 +--- a/drivers/net/ethernet/freescale/fman/fman_dtsec.h ++++ /dev/null +@@ -1,59 +0,0 @@ +-/* +- * Copyright 2008-2015 Freescale Semiconductor Inc. +- * +- * Redistribution and use in source and binary forms, with or without +- * modification, are permitted provided that the following conditions are met: +- * * Redistributions of source code must retain the above copyright +- * notice, this list of conditions and the following disclaimer. +- * * Redistributions in binary form must reproduce the above copyright +- * notice, this list of conditions and the following disclaimer in the +- * documentation and/or other materials provided with the distribution. +- * * Neither the name of Freescale Semiconductor nor the +- * names of its contributors may be used to endorse or promote products +- * derived from this software without specific prior written permission. +- * +- * +- * ALTERNATIVELY, this software may be distributed under the terms of the +- * GNU General Public License ("GPL") as published by the Free Software +- * Foundation, either version 2 of that License or (at your option) any +- * later version. +- * +- * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY +- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +- * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY +- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +- */ +- +-#ifndef __DTSEC_H +-#define __DTSEC_H +- +-#include "fman_mac.h" +- +-struct fman_mac *dtsec_config(struct fman_mac_params *params); +-int dtsec_set_promiscuous(struct fman_mac *dtsec, bool new_val); +-int dtsec_modify_mac_address(struct fman_mac *dtsec, enet_addr_t *enet_addr); +-int dtsec_adjust_link(struct fman_mac *dtsec, +- u16 speed); +-int dtsec_restart_autoneg(struct fman_mac *dtsec); +-int dtsec_cfg_max_frame_len(struct fman_mac *dtsec, u16 new_val); +-int dtsec_cfg_pad_and_crc(struct fman_mac *dtsec, bool new_val); +-int dtsec_enable(struct fman_mac *dtsec, enum comm_mode mode); +-int dtsec_disable(struct fman_mac *dtsec, enum comm_mode mode); +-int dtsec_init(struct fman_mac *dtsec); +-int dtsec_free(struct fman_mac *dtsec); +-int dtsec_accept_rx_pause_frames(struct fman_mac *dtsec, bool en); +-int dtsec_set_tx_pause_frames(struct fman_mac *dtsec, u8 priority, +- u16 pause_time, u16 thresh_time); +-int dtsec_set_exception(struct fman_mac *dtsec, +- enum fman_mac_exceptions exception, bool enable); +-int dtsec_add_hash_mac_address(struct fman_mac *dtsec, enet_addr_t *eth_addr); +-int dtsec_del_hash_mac_address(struct fman_mac *dtsec, enet_addr_t *eth_addr); +-int dtsec_get_version(struct fman_mac *dtsec, u32 *mac_version); +- +-#endif /* __DTSEC_H */ +diff --git a/drivers/net/ethernet/freescale/fman/fman_mac.h b/drivers/net/ethernet/freescale/fman/fman_mac.h +deleted file mode 100644 +index dd6d052..0000000 +--- a/drivers/net/ethernet/freescale/fman/fman_mac.h ++++ /dev/null +@@ -1,274 +0,0 @@ +-/* +- * Copyright 2008-2015 Freescale Semiconductor Inc. +- * +- * Redistribution and use in source and binary forms, with or without +- * modification, are permitted provided that the following conditions are met: +- * * Redistributions of source code must retain the above copyright +- * notice, this list of conditions and the following disclaimer. +- * * Redistributions in binary form must reproduce the above copyright +- * notice, this list of conditions and the following disclaimer in the +- * documentation and/or other materials provided with the distribution. +- * * Neither the name of Freescale Semiconductor nor the +- * names of its contributors may be used to endorse or promote products +- * derived from this software without specific prior written permission. +- * +- * +- * ALTERNATIVELY, this software may be distributed under the terms of the +- * GNU General Public License ("GPL") as published by the Free Software +- * Foundation, either version 2 of that License or (at your option) any +- * later version. +- * +- * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY +- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +- * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY +- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +- */ +- +-/* FM MAC ... */ +-#ifndef __FM_MAC_H +-#define __FM_MAC_H +- +-#include "fman.h" +- +-#include +-#include +-#include +- +-struct fman_mac; +- +-/* Ethernet Address */ +-typedef u8 enet_addr_t[ETH_ALEN]; +- +-#define ENET_ADDR_TO_UINT64(_enet_addr) \ +- (u64)(((u64)(_enet_addr)[0] << 40) | \ +- ((u64)(_enet_addr)[1] << 32) | \ +- ((u64)(_enet_addr)[2] << 24) | \ +- ((u64)(_enet_addr)[3] << 16) | \ +- ((u64)(_enet_addr)[4] << 8) | \ +- ((u64)(_enet_addr)[5])) +- +-#define MAKE_ENET_ADDR_FROM_UINT64(_addr64, _enet_addr) \ +- do { \ +- int i; \ +- for (i = 0; i < ETH_ALEN; i++) \ +- (_enet_addr)[i] = \ +- (u8)((_addr64) >> ((5 - i) * 8)); \ +- } while (0) +- +-/* defaults */ +-#define DEFAULT_RESET_ON_INIT false +- +-/* PFC defines */ +-#define FSL_FM_PAUSE_TIME_ENABLE 0xf000 +-#define FSL_FM_PAUSE_TIME_DISABLE 0 +-#define FSL_FM_PAUSE_THRESH_DEFAULT 0 +- +-#define FM_MAC_NO_PFC 0xff +- +-/* HASH defines */ +-#define ETH_HASH_ENTRY_OBJ(ptr) \ +- hlist_entry_safe(ptr, struct eth_hash_entry, node) +- +-/* Enumeration (bit flags) of communication modes (Transmit, +- * receive or both). +- */ +-enum comm_mode { +- COMM_MODE_NONE = 0, /* No transmit/receive communication */ +- COMM_MODE_RX = 1, /* Only receive communication */ +- COMM_MODE_TX = 2, /* Only transmit communication */ +- COMM_MODE_RX_AND_TX = 3 /* Both transmit and receive communication */ +-}; +- +-/* FM MAC Exceptions */ +-enum fman_mac_exceptions { +- FM_MAC_EX_10G_MDIO_SCAN_EVENT = 0 +- /* 10GEC MDIO scan event interrupt */ +- , FM_MAC_EX_10G_MDIO_CMD_CMPL +- /* 10GEC MDIO command completion interrupt */ +- , FM_MAC_EX_10G_REM_FAULT +- /* 10GEC, mEMAC Remote fault interrupt */ +- , FM_MAC_EX_10G_LOC_FAULT +- /* 10GEC, mEMAC Local fault interrupt */ +- , FM_MAC_EX_10G_TX_ECC_ER +- /* 10GEC, mEMAC Transmit frame ECC error interrupt */ +- , FM_MAC_EX_10G_TX_FIFO_UNFL +- /* 10GEC, mEMAC Transmit FIFO underflow interrupt */ +- , FM_MAC_EX_10G_TX_FIFO_OVFL +- /* 10GEC, mEMAC Transmit FIFO overflow interrupt */ +- , FM_MAC_EX_10G_TX_ER +- /* 10GEC Transmit frame error interrupt */ +- , FM_MAC_EX_10G_RX_FIFO_OVFL +- /* 10GEC, mEMAC Receive FIFO overflow interrupt */ +- , FM_MAC_EX_10G_RX_ECC_ER +- /* 10GEC, mEMAC Receive frame ECC error interrupt */ +- , FM_MAC_EX_10G_RX_JAB_FRM +- /* 10GEC Receive jabber frame interrupt */ +- , FM_MAC_EX_10G_RX_OVRSZ_FRM +- /* 10GEC Receive oversized frame interrupt */ +- , FM_MAC_EX_10G_RX_RUNT_FRM +- /* 10GEC Receive runt frame interrupt */ +- , FM_MAC_EX_10G_RX_FRAG_FRM +- /* 10GEC Receive fragment frame interrupt */ +- , FM_MAC_EX_10G_RX_LEN_ER +- /* 10GEC Receive payload length error interrupt */ +- , FM_MAC_EX_10G_RX_CRC_ER +- /* 10GEC Receive CRC error interrupt */ +- , FM_MAC_EX_10G_RX_ALIGN_ER +- /* 10GEC Receive alignment error interrupt */ +- , FM_MAC_EX_1G_BAB_RX +- /* dTSEC Babbling receive error */ +- , FM_MAC_EX_1G_RX_CTL +- /* dTSEC Receive control (pause frame) interrupt */ +- , FM_MAC_EX_1G_GRATEFUL_TX_STP_COMPLET +- /* dTSEC Graceful transmit stop complete */ +- , FM_MAC_EX_1G_BAB_TX +- /* dTSEC Babbling transmit error */ +- , FM_MAC_EX_1G_TX_CTL +- /* dTSEC Transmit control (pause frame) interrupt */ +- , FM_MAC_EX_1G_TX_ERR +- /* dTSEC Transmit error */ +- , FM_MAC_EX_1G_LATE_COL +- /* dTSEC Late collision */ +- , FM_MAC_EX_1G_COL_RET_LMT +- /* dTSEC Collision retry limit */ +- , FM_MAC_EX_1G_TX_FIFO_UNDRN +- /* dTSEC Transmit FIFO underrun */ +- , FM_MAC_EX_1G_MAG_PCKT +- /* dTSEC Magic Packet detection */ +- , FM_MAC_EX_1G_MII_MNG_RD_COMPLET +- /* dTSEC MII management read completion */ +- , FM_MAC_EX_1G_MII_MNG_WR_COMPLET +- /* dTSEC MII management write completion */ +- , FM_MAC_EX_1G_GRATEFUL_RX_STP_COMPLET +- /* dTSEC Graceful receive stop complete */ +- , FM_MAC_EX_1G_DATA_ERR +- /* dTSEC Internal data error on transmit */ +- , FM_MAC_1G_RX_DATA_ERR +- /* dTSEC Internal data error on receive */ +- , FM_MAC_EX_1G_1588_TS_RX_ERR +- /* dTSEC Time-Stamp Receive Error */ +- , FM_MAC_EX_1G_RX_MIB_CNT_OVFL +- /* dTSEC MIB counter overflow */ +- , FM_MAC_EX_TS_FIFO_ECC_ERR +- /* mEMAC Time-stamp FIFO ECC error interrupt; +- * not supported on T4240/B4860 rev1 chips +- */ +- , FM_MAC_EX_MAGIC_PACKET_INDICATION = FM_MAC_EX_1G_MAG_PCKT +- /* mEMAC Magic Packet Indication Interrupt */ +-}; +- +-struct eth_hash_entry { +- u64 addr; /* Ethernet Address */ +- struct list_head node; +-}; +- +-typedef void (fman_mac_exception_cb)(void *dev_id, +- enum fman_mac_exceptions exceptions); +- +-/* FMan MAC config input */ +-struct fman_mac_params { +- /* Base of memory mapped FM MAC registers */ +- void __iomem *base_addr; +- /* MAC address of device; First octet is sent first */ +- enet_addr_t addr; +- /* MAC ID; numbering of dTSEC and 1G-mEMAC: +- * 0 - FM_MAX_NUM_OF_1G_MACS; +- * numbering of 10G-MAC (TGEC) and 10G-mEMAC: +- * 0 - FM_MAX_NUM_OF_10G_MACS +- */ +- u8 mac_id; +- /* PHY interface */ +- phy_interface_t phy_if; +- /* Note that the speed should indicate the maximum rate that +- * this MAC should support rather than the actual speed; +- */ +- u16 max_speed; +- /* A handle to the FM object this port related to */ +- void *fm; +- void *dev_id; /* device cookie used by the exception cbs */ +- fman_mac_exception_cb *event_cb; /* MDIO Events Callback Routine */ +- fman_mac_exception_cb *exception_cb;/* Exception Callback Routine */ +- /* SGMII/QSGII interface with 1000BaseX auto-negotiation between MAC +- * and phy or backplane; Note: 1000BaseX auto-negotiation relates only +- * to interface between MAC and phy/backplane, SGMII phy can still +- * synchronize with far-end phy at 10Mbps, 100Mbps or 1000Mbps +- */ +- bool basex_if; +- /* Pointer to TBI/PCS PHY node, used for TBI/PCS PHY access */ +- struct device_node *internal_phy_node; +-}; +- +-struct eth_hash_t { +- u16 size; +- struct list_head *lsts; +-}; +- +-static inline struct eth_hash_entry +-*dequeue_addr_from_hash_entry(struct list_head *addr_lst) +-{ +- struct eth_hash_entry *hash_entry = NULL; +- +- if (!list_empty(addr_lst)) { +- hash_entry = ETH_HASH_ENTRY_OBJ(addr_lst->next); +- list_del_init(&hash_entry->node); +- } +- return hash_entry; +-} +- +-static inline void free_hash_table(struct eth_hash_t *hash) +-{ +- struct eth_hash_entry *hash_entry; +- int i = 0; +- +- if (hash) { +- if (hash->lsts) { +- for (i = 0; i < hash->size; i++) { +- hash_entry = +- dequeue_addr_from_hash_entry(&hash->lsts[i]); +- while (hash_entry) { +- kfree(hash_entry); +- hash_entry = +- dequeue_addr_from_hash_entry(&hash-> +- lsts[i]); +- } +- } +- +- kfree(hash->lsts); +- } +- +- kfree(hash); +- } +-} +- +-static inline struct eth_hash_t *alloc_hash_table(u16 size) +-{ +- u32 i; +- struct eth_hash_t *hash; +- +- /* Allocate address hash table */ +- hash = kmalloc_array(size, sizeof(struct eth_hash_t *), GFP_KERNEL); +- if (!hash) +- return NULL; +- +- hash->size = size; +- +- hash->lsts = kmalloc_array(hash->size, sizeof(struct list_head), +- GFP_KERNEL); +- if (!hash->lsts) { +- kfree(hash); +- return NULL; +- } +- +- for (i = 0; i < hash->size; i++) +- INIT_LIST_HEAD(&hash->lsts[i]); +- +- return hash; +-} +- +-#endif /* __FM_MAC_H */ +diff --git a/drivers/net/ethernet/freescale/fman/fman_memac.c b/drivers/net/ethernet/freescale/fman/fman_memac.c +deleted file mode 100644 +index 71a5ded..0000000 +--- a/drivers/net/ethernet/freescale/fman/fman_memac.c ++++ /dev/null +@@ -1,1177 +0,0 @@ +-/* +- * Copyright 2008-2015 Freescale Semiconductor Inc. +- * +- * Redistribution and use in source and binary forms, with or without +- * modification, are permitted provided that the following conditions are met: +- * * Redistributions of source code must retain the above copyright +- * notice, this list of conditions and the following disclaimer. +- * * Redistributions in binary form must reproduce the above copyright +- * notice, this list of conditions and the following disclaimer in the +- * documentation and/or other materials provided with the distribution. +- * * Neither the name of Freescale Semiconductor nor the +- * names of its contributors may be used to endorse or promote products +- * derived from this software without specific prior written permission. +- * +- * +- * ALTERNATIVELY, this software may be distributed under the terms of the +- * GNU General Public License ("GPL") as published by the Free Software +- * Foundation, either version 2 of that License or (at your option) any +- * later version. +- * +- * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY +- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +- * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY +- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +- */ +- +-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +- +-#include "fman_memac.h" +-#include "fman.h" +- +-#include +-#include +-#include +-#include +- +-/* PCS registers */ +-#define MDIO_SGMII_CR 0x00 +-#define MDIO_SGMII_DEV_ABIL_SGMII 0x04 +-#define MDIO_SGMII_LINK_TMR_L 0x12 +-#define MDIO_SGMII_LINK_TMR_H 0x13 +-#define MDIO_SGMII_IF_MODE 0x14 +- +-/* SGMII Control defines */ +-#define SGMII_CR_AN_EN 0x1000 +-#define SGMII_CR_RESTART_AN 0x0200 +-#define SGMII_CR_FD 0x0100 +-#define SGMII_CR_SPEED_SEL1_1G 0x0040 +-#define SGMII_CR_DEF_VAL (SGMII_CR_AN_EN | SGMII_CR_FD | \ +- SGMII_CR_SPEED_SEL1_1G) +- +-/* SGMII Device Ability for SGMII defines */ +-#define MDIO_SGMII_DEV_ABIL_SGMII_MODE 0x4001 +-#define MDIO_SGMII_DEV_ABIL_BASEX_MODE 0x01A0 +- +-/* Link timer define */ +-#define LINK_TMR_L 0xa120 +-#define LINK_TMR_H 0x0007 +-#define LINK_TMR_L_BASEX 0xaf08 +-#define LINK_TMR_H_BASEX 0x002f +- +-/* SGMII IF Mode defines */ +-#define IF_MODE_USE_SGMII_AN 0x0002 +-#define IF_MODE_SGMII_EN 0x0001 +-#define IF_MODE_SGMII_SPEED_100M 0x0004 +-#define IF_MODE_SGMII_SPEED_1G 0x0008 +-#define IF_MODE_SGMII_DUPLEX_HALF 0x0010 +- +-/* Num of additional exact match MAC adr regs */ +-#define MEMAC_NUM_OF_PADDRS 7 +- +-/* Control and Configuration Register (COMMAND_CONFIG) */ +-#define CMD_CFG_REG_LOWP_RXETY 0x01000000 /* 07 Rx low power indication */ +-#define CMD_CFG_TX_LOWP_ENA 0x00800000 /* 08 Tx Low Power Idle Enable */ +-#define CMD_CFG_PFC_MODE 0x00080000 /* 12 Enable PFC */ +-#define CMD_CFG_NO_LEN_CHK 0x00020000 /* 14 Payload length check disable */ +-#define CMD_CFG_SW_RESET 0x00001000 /* 19 S/W Reset, self clearing bit */ +-#define CMD_CFG_TX_PAD_EN 0x00000800 /* 20 Enable Tx padding of frames */ +-#define CMD_CFG_PAUSE_IGNORE 0x00000100 /* 23 Ignore Pause frame quanta */ +-#define CMD_CFG_CRC_FWD 0x00000040 /* 25 Terminate/frwd CRC of frames */ +-#define CMD_CFG_PAD_EN 0x00000020 /* 26 Frame padding removal */ +-#define CMD_CFG_PROMIS_EN 0x00000010 /* 27 Promiscuous operation enable */ +-#define CMD_CFG_RX_EN 0x00000002 /* 30 MAC receive path enable */ +-#define CMD_CFG_TX_EN 0x00000001 /* 31 MAC transmit path enable */ +- +-/* Transmit FIFO Sections Register (TX_FIFO_SECTIONS) */ +-#define TX_FIFO_SECTIONS_TX_EMPTY_MASK 0xFFFF0000 +-#define TX_FIFO_SECTIONS_TX_AVAIL_MASK 0x0000FFFF +-#define TX_FIFO_SECTIONS_TX_EMPTY_DEFAULT_10G 0x00400000 +-#define TX_FIFO_SECTIONS_TX_EMPTY_DEFAULT_1G 0x00100000 +-#define TX_FIFO_SECTIONS_TX_AVAIL_10G 0x00000019 +-#define TX_FIFO_SECTIONS_TX_AVAIL_1G 0x00000020 +-#define TX_FIFO_SECTIONS_TX_AVAIL_SLOW_10G 0x00000060 +- +-#define GET_TX_EMPTY_DEFAULT_VALUE(_val) \ +-do { \ +- _val &= ~TX_FIFO_SECTIONS_TX_EMPTY_MASK; \ +- ((_val == TX_FIFO_SECTIONS_TX_AVAIL_10G) ? \ +- (_val |= TX_FIFO_SECTIONS_TX_EMPTY_DEFAULT_10G) :\ +- (_val |= TX_FIFO_SECTIONS_TX_EMPTY_DEFAULT_1G));\ +-} while (0) +- +-/* Interface Mode Register (IF_MODE) */ +- +-#define IF_MODE_MASK 0x00000003 /* 30-31 Mask on i/f mode bits */ +-#define IF_MODE_XGMII 0x00000000 /* 30-31 XGMII (10G) interface */ +-#define IF_MODE_GMII 0x00000002 /* 30-31 GMII (1G) interface */ +-#define IF_MODE_RGMII 0x00000004 +-#define IF_MODE_RGMII_AUTO 0x00008000 +-#define IF_MODE_RGMII_1000 0x00004000 /* 10 - 1000Mbps RGMII */ +-#define IF_MODE_RGMII_100 0x00000000 /* 00 - 100Mbps RGMII */ +-#define IF_MODE_RGMII_10 0x00002000 /* 01 - 10Mbps RGMII */ +-#define IF_MODE_RGMII_SP_MASK 0x00006000 /* Setsp mask bits */ +-#define IF_MODE_RGMII_FD 0x00001000 /* Full duplex RGMII */ +-#define IF_MODE_HD 0x00000040 /* Half duplex operation */ +- +-/* Hash table Control Register (HASHTABLE_CTRL) */ +-#define HASH_CTRL_MCAST_EN 0x00000100 +-/* 26-31 Hash table address code */ +-#define HASH_CTRL_ADDR_MASK 0x0000003F +-/* MAC mcast indication */ +-#define GROUP_ADDRESS 0x0000010000000000LL +-#define HASH_TABLE_SIZE 64 /* Hash tbl size */ +- +-/* Interrupt Mask Register (IMASK) */ +-#define MEMAC_IMASK_MGI 0x40000000 /* 1 Magic pkt detect indication */ +-#define MEMAC_IMASK_TSECC_ER 0x20000000 /* 2 Timestamp FIFO ECC error evnt */ +-#define MEMAC_IMASK_TECC_ER 0x02000000 /* 6 Transmit frame ECC error evnt */ +-#define MEMAC_IMASK_RECC_ER 0x01000000 /* 7 Receive frame ECC error evnt */ +- +-#define MEMAC_ALL_ERRS_IMASK \ +- ((u32)(MEMAC_IMASK_TSECC_ER | \ +- MEMAC_IMASK_TECC_ER | \ +- MEMAC_IMASK_RECC_ER | \ +- MEMAC_IMASK_MGI)) +- +-#define MEMAC_IEVNT_PCS 0x80000000 /* PCS (XG). Link sync (G) */ +-#define MEMAC_IEVNT_AN 0x40000000 /* Auto-negotiation */ +-#define MEMAC_IEVNT_LT 0x20000000 /* Link Training/New page */ +-#define MEMAC_IEVNT_MGI 0x00004000 /* Magic pkt detection */ +-#define MEMAC_IEVNT_TS_ECC_ER 0x00002000 /* Timestamp FIFO ECC error*/ +-#define MEMAC_IEVNT_RX_FIFO_OVFL 0x00001000 /* Rx FIFO overflow */ +-#define MEMAC_IEVNT_TX_FIFO_UNFL 0x00000800 /* Tx FIFO underflow */ +-#define MEMAC_IEVNT_TX_FIFO_OVFL 0x00000400 /* Tx FIFO overflow */ +-#define MEMAC_IEVNT_TX_ECC_ER 0x00000200 /* Tx frame ECC error */ +-#define MEMAC_IEVNT_RX_ECC_ER 0x00000100 /* Rx frame ECC error */ +-#define MEMAC_IEVNT_LI_FAULT 0x00000080 /* Link Interruption flt */ +-#define MEMAC_IEVNT_RX_EMPTY 0x00000040 /* Rx FIFO empty */ +-#define MEMAC_IEVNT_TX_EMPTY 0x00000020 /* Tx FIFO empty */ +-#define MEMAC_IEVNT_RX_LOWP 0x00000010 /* Low Power Idle */ +-#define MEMAC_IEVNT_PHY_LOS 0x00000004 /* Phy loss of signal */ +-#define MEMAC_IEVNT_REM_FAULT 0x00000002 /* Remote fault (XGMII) */ +-#define MEMAC_IEVNT_LOC_FAULT 0x00000001 /* Local fault (XGMII) */ +- +-#define DEFAULT_PAUSE_QUANTA 0xf000 +-#define DEFAULT_FRAME_LENGTH 0x600 +-#define DEFAULT_TX_IPG_LENGTH 12 +- +-#define CLXY_PAUSE_QUANTA_CLX_PQNT 0x0000FFFF +-#define CLXY_PAUSE_QUANTA_CLY_PQNT 0xFFFF0000 +-#define CLXY_PAUSE_THRESH_CLX_QTH 0x0000FFFF +-#define CLXY_PAUSE_THRESH_CLY_QTH 0xFFFF0000 +- +-struct mac_addr { +- /* Lower 32 bits of 48-bit MAC address */ +- u32 mac_addr_l; +- /* Upper 16 bits of 48-bit MAC address */ +- u32 mac_addr_u; +-}; +- +-/* memory map */ +-struct memac_regs { +- u32 res0000[2]; /* General Control and Status */ +- u32 command_config; /* 0x008 Ctrl and cfg */ +- struct mac_addr mac_addr0; /* 0x00C-0x010 MAC_ADDR_0...1 */ +- u32 maxfrm; /* 0x014 Max frame length */ +- u32 res0018[1]; +- u32 rx_fifo_sections; /* Receive FIFO configuration reg */ +- u32 tx_fifo_sections; /* Transmit FIFO configuration reg */ +- u32 res0024[2]; +- u32 hashtable_ctrl; /* 0x02C Hash table control */ +- u32 res0030[4]; +- u32 ievent; /* 0x040 Interrupt event */ +- u32 tx_ipg_length; /* 0x044 Transmitter inter-packet-gap */ +- u32 res0048; +- u32 imask; /* 0x04C Interrupt mask */ +- u32 res0050; +- u32 pause_quanta[4]; /* 0x054 Pause quanta */ +- u32 pause_thresh[4]; /* 0x064 Pause quanta threshold */ +- u32 rx_pause_status; /* 0x074 Receive pause status */ +- u32 res0078[2]; +- struct mac_addr mac_addr[MEMAC_NUM_OF_PADDRS];/* 0x80-0x0B4 mac padr */ +- u32 lpwake_timer; /* 0x0B8 Low Power Wakeup Timer */ +- u32 sleep_timer; /* 0x0BC Transmit EEE Low Power Timer */ +- u32 res00c0[8]; +- u32 statn_config; /* 0x0E0 Statistics configuration */ +- u32 res00e4[7]; +- /* Rx Statistics Counter */ +- u32 reoct_l; +- u32 reoct_u; +- u32 roct_l; +- u32 roct_u; +- u32 raln_l; +- u32 raln_u; +- u32 rxpf_l; +- u32 rxpf_u; +- u32 rfrm_l; +- u32 rfrm_u; +- u32 rfcs_l; +- u32 rfcs_u; +- u32 rvlan_l; +- u32 rvlan_u; +- u32 rerr_l; +- u32 rerr_u; +- u32 ruca_l; +- u32 ruca_u; +- u32 rmca_l; +- u32 rmca_u; +- u32 rbca_l; +- u32 rbca_u; +- u32 rdrp_l; +- u32 rdrp_u; +- u32 rpkt_l; +- u32 rpkt_u; +- u32 rund_l; +- u32 rund_u; +- u32 r64_l; +- u32 r64_u; +- u32 r127_l; +- u32 r127_u; +- u32 r255_l; +- u32 r255_u; +- u32 r511_l; +- u32 r511_u; +- u32 r1023_l; +- u32 r1023_u; +- u32 r1518_l; +- u32 r1518_u; +- u32 r1519x_l; +- u32 r1519x_u; +- u32 rovr_l; +- u32 rovr_u; +- u32 rjbr_l; +- u32 rjbr_u; +- u32 rfrg_l; +- u32 rfrg_u; +- u32 rcnp_l; +- u32 rcnp_u; +- u32 rdrntp_l; +- u32 rdrntp_u; +- u32 res01d0[12]; +- /* Tx Statistics Counter */ +- u32 teoct_l; +- u32 teoct_u; +- u32 toct_l; +- u32 toct_u; +- u32 res0210[2]; +- u32 txpf_l; +- u32 txpf_u; +- u32 tfrm_l; +- u32 tfrm_u; +- u32 tfcs_l; +- u32 tfcs_u; +- u32 tvlan_l; +- u32 tvlan_u; +- u32 terr_l; +- u32 terr_u; +- u32 tuca_l; +- u32 tuca_u; +- u32 tmca_l; +- u32 tmca_u; +- u32 tbca_l; +- u32 tbca_u; +- u32 res0258[2]; +- u32 tpkt_l; +- u32 tpkt_u; +- u32 tund_l; +- u32 tund_u; +- u32 t64_l; +- u32 t64_u; +- u32 t127_l; +- u32 t127_u; +- u32 t255_l; +- u32 t255_u; +- u32 t511_l; +- u32 t511_u; +- u32 t1023_l; +- u32 t1023_u; +- u32 t1518_l; +- u32 t1518_u; +- u32 t1519x_l; +- u32 t1519x_u; +- u32 res02a8[6]; +- u32 tcnp_l; +- u32 tcnp_u; +- u32 res02c8[14]; +- /* Line Interface Control */ +- u32 if_mode; /* 0x300 Interface Mode Control */ +- u32 if_status; /* 0x304 Interface Status */ +- u32 res0308[14]; +- /* HiGig/2 */ +- u32 hg_config; /* 0x340 Control and cfg */ +- u32 res0344[3]; +- u32 hg_pause_quanta; /* 0x350 Pause quanta */ +- u32 res0354[3]; +- u32 hg_pause_thresh; /* 0x360 Pause quanta threshold */ +- u32 res0364[3]; +- u32 hgrx_pause_status; /* 0x370 Receive pause status */ +- u32 hg_fifos_status; /* 0x374 fifos status */ +- u32 rhm; /* 0x378 rx messages counter */ +- u32 thm; /* 0x37C tx messages counter */ +-}; +- +-struct memac_cfg { +- bool reset_on_init; +- bool pause_ignore; +- bool promiscuous_mode_enable; +- struct fixed_phy_status *fixed_link; +- u16 max_frame_length; +- u16 pause_quanta; +- u32 tx_ipg_length; +-}; +- +-struct fman_mac { +- /* Pointer to MAC memory mapped registers */ +- struct memac_regs __iomem *regs; +- /* MAC address of device */ +- u64 addr; +- /* Ethernet physical interface */ +- phy_interface_t phy_if; +- u16 max_speed; +- void *dev_id; /* device cookie used by the exception cbs */ +- fman_mac_exception_cb *exception_cb; +- fman_mac_exception_cb *event_cb; +- /* Pointer to driver's global address hash table */ +- struct eth_hash_t *multicast_addr_hash; +- /* Pointer to driver's individual address hash table */ +- struct eth_hash_t *unicast_addr_hash; +- u8 mac_id; +- u32 exceptions; +- struct memac_cfg *memac_drv_param; +- void *fm; +- struct fman_rev_info fm_rev_info; +- bool basex_if; +- struct phy_device *pcsphy; +-}; +- +-static void add_addr_in_paddr(struct memac_regs __iomem *regs, u8 *adr, +- u8 paddr_num) +-{ +- u32 tmp0, tmp1; +- +- tmp0 = (u32)(adr[0] | adr[1] << 8 | adr[2] << 16 | adr[3] << 24); +- tmp1 = (u32)(adr[4] | adr[5] << 8); +- +- if (paddr_num == 0) { +- iowrite32be(tmp0, ®s->mac_addr0.mac_addr_l); +- iowrite32be(tmp1, ®s->mac_addr0.mac_addr_u); +- } else { +- iowrite32be(tmp0, ®s->mac_addr[paddr_num - 1].mac_addr_l); +- iowrite32be(tmp1, ®s->mac_addr[paddr_num - 1].mac_addr_u); +- } +-} +- +-static int reset(struct memac_regs __iomem *regs) +-{ +- u32 tmp; +- int count; +- +- tmp = ioread32be(®s->command_config); +- +- tmp |= CMD_CFG_SW_RESET; +- +- iowrite32be(tmp, ®s->command_config); +- +- count = 100; +- do { +- udelay(1); +- } while ((ioread32be(®s->command_config) & CMD_CFG_SW_RESET) && +- --count); +- +- if (count == 0) +- return -EBUSY; +- +- return 0; +-} +- +-static void set_exception(struct memac_regs __iomem *regs, u32 val, +- bool enable) +-{ +- u32 tmp; +- +- tmp = ioread32be(®s->imask); +- if (enable) +- tmp |= val; +- else +- tmp &= ~val; +- +- iowrite32be(tmp, ®s->imask); +-} +- +-static int init(struct memac_regs __iomem *regs, struct memac_cfg *cfg, +- phy_interface_t phy_if, u16 speed, bool slow_10g_if, +- u32 exceptions) +-{ +- u32 tmp; +- +- /* Config */ +- tmp = 0; +- if (cfg->promiscuous_mode_enable) +- tmp |= CMD_CFG_PROMIS_EN; +- if (cfg->pause_ignore) +- tmp |= CMD_CFG_PAUSE_IGNORE; +- +- /* Payload length check disable */ +- tmp |= CMD_CFG_NO_LEN_CHK; +- /* Enable padding of frames in transmit direction */ +- tmp |= CMD_CFG_TX_PAD_EN; +- +- tmp |= CMD_CFG_CRC_FWD; +- +- iowrite32be(tmp, ®s->command_config); +- +- /* Max Frame Length */ +- iowrite32be((u32)cfg->max_frame_length, ®s->maxfrm); +- +- /* Pause Time */ +- iowrite32be((u32)cfg->pause_quanta, ®s->pause_quanta[0]); +- iowrite32be((u32)0, ®s->pause_thresh[0]); +- +- /* IF_MODE */ +- tmp = 0; +- switch (phy_if) { +- case PHY_INTERFACE_MODE_XGMII: +- tmp |= IF_MODE_XGMII; +- break; +- default: +- tmp |= IF_MODE_GMII; +- if (phy_if == PHY_INTERFACE_MODE_RGMII) +- tmp |= IF_MODE_RGMII | IF_MODE_RGMII_AUTO; +- } +- iowrite32be(tmp, ®s->if_mode); +- +- /* TX_FIFO_SECTIONS */ +- tmp = 0; +- if (phy_if == PHY_INTERFACE_MODE_XGMII) { +- if (slow_10g_if) { +- tmp |= (TX_FIFO_SECTIONS_TX_AVAIL_SLOW_10G | +- TX_FIFO_SECTIONS_TX_EMPTY_DEFAULT_10G); +- } else { +- tmp |= (TX_FIFO_SECTIONS_TX_AVAIL_10G | +- TX_FIFO_SECTIONS_TX_EMPTY_DEFAULT_10G); +- } +- } else { +- tmp |= (TX_FIFO_SECTIONS_TX_AVAIL_1G | +- TX_FIFO_SECTIONS_TX_EMPTY_DEFAULT_1G); +- } +- iowrite32be(tmp, ®s->tx_fifo_sections); +- +- /* clear all pending events and set-up interrupts */ +- iowrite32be(0xffffffff, ®s->ievent); +- set_exception(regs, exceptions, true); +- +- return 0; +-} +- +-static void set_dflts(struct memac_cfg *cfg) +-{ +- cfg->reset_on_init = false; +- cfg->promiscuous_mode_enable = false; +- cfg->pause_ignore = false; +- cfg->tx_ipg_length = DEFAULT_TX_IPG_LENGTH; +- cfg->max_frame_length = DEFAULT_FRAME_LENGTH; +- cfg->pause_quanta = DEFAULT_PAUSE_QUANTA; +-} +- +-static u32 get_mac_addr_hash_code(u64 eth_addr) +-{ +- u64 mask1, mask2; +- u32 xor_val = 0; +- u8 i, j; +- +- for (i = 0; i < 6; i++) { +- mask1 = eth_addr & (u64)0x01; +- eth_addr >>= 1; +- +- for (j = 0; j < 7; j++) { +- mask2 = eth_addr & (u64)0x01; +- mask1 ^= mask2; +- eth_addr >>= 1; +- } +- +- xor_val |= (mask1 << (5 - i)); +- } +- +- return xor_val; +-} +- +-static void setup_sgmii_internal_phy(struct fman_mac *memac, +- struct fixed_phy_status *fixed_link) +-{ +- u16 tmp_reg16; +- +- if (WARN_ON(!memac->pcsphy)) +- return; +- +- /* SGMII mode */ +- tmp_reg16 = IF_MODE_SGMII_EN; +- if (!fixed_link) +- /* AN enable */ +- tmp_reg16 |= IF_MODE_USE_SGMII_AN; +- else { +- switch (fixed_link->speed) { +- case 10: +- /* For 10M: IF_MODE[SPEED_10M] = 0 */ +- break; +- case 100: +- tmp_reg16 |= IF_MODE_SGMII_SPEED_100M; +- break; +- case 1000: /* fallthrough */ +- default: +- tmp_reg16 |= IF_MODE_SGMII_SPEED_1G; +- break; +- } +- if (!fixed_link->duplex) +- tmp_reg16 |= IF_MODE_SGMII_DUPLEX_HALF; +- } +- phy_write(memac->pcsphy, MDIO_SGMII_IF_MODE, tmp_reg16); +- +- /* Device ability according to SGMII specification */ +- tmp_reg16 = MDIO_SGMII_DEV_ABIL_SGMII_MODE; +- phy_write(memac->pcsphy, MDIO_SGMII_DEV_ABIL_SGMII, tmp_reg16); +- +- /* Adjust link timer for SGMII - +- * According to Cisco SGMII specification the timer should be 1.6 ms. +- * The link_timer register is configured in units of the clock. +- * - When running as 1G SGMII, Serdes clock is 125 MHz, so +- * unit = 1 / (125*10^6 Hz) = 8 ns. +- * 1.6 ms in units of 8 ns = 1.6ms / 8ns = 2*10^5 = 0x30d40 +- * - When running as 2.5G SGMII, Serdes clock is 312.5 MHz, so +- * unit = 1 / (312.5*10^6 Hz) = 3.2 ns. +- * 1.6 ms in units of 3.2 ns = 1.6ms / 3.2ns = 5*10^5 = 0x7a120. +- * Since link_timer value of 1G SGMII will be too short for 2.5 SGMII, +- * we always set up here a value of 2.5 SGMII. +- */ +- phy_write(memac->pcsphy, MDIO_SGMII_LINK_TMR_H, LINK_TMR_H); +- phy_write(memac->pcsphy, MDIO_SGMII_LINK_TMR_L, LINK_TMR_L); +- +- if (!fixed_link) +- /* Restart AN */ +- tmp_reg16 = SGMII_CR_DEF_VAL | SGMII_CR_RESTART_AN; +- else +- /* AN disabled */ +- tmp_reg16 = SGMII_CR_DEF_VAL & ~SGMII_CR_AN_EN; +- phy_write(memac->pcsphy, 0x0, tmp_reg16); +-} +- +-static void setup_sgmii_internal_phy_base_x(struct fman_mac *memac) +-{ +- u16 tmp_reg16; +- +- /* AN Device capability */ +- tmp_reg16 = MDIO_SGMII_DEV_ABIL_BASEX_MODE; +- phy_write(memac->pcsphy, MDIO_SGMII_DEV_ABIL_SGMII, tmp_reg16); +- +- /* Adjust link timer for SGMII - +- * For Serdes 1000BaseX auto-negotiation the timer should be 10 ms. +- * The link_timer register is configured in units of the clock. +- * - When running as 1G SGMII, Serdes clock is 125 MHz, so +- * unit = 1 / (125*10^6 Hz) = 8 ns. +- * 10 ms in units of 8 ns = 10ms / 8ns = 1250000 = 0x1312d0 +- * - When running as 2.5G SGMII, Serdes clock is 312.5 MHz, so +- * unit = 1 / (312.5*10^6 Hz) = 3.2 ns. +- * 10 ms in units of 3.2 ns = 10ms / 3.2ns = 3125000 = 0x2faf08. +- * Since link_timer value of 1G SGMII will be too short for 2.5 SGMII, +- * we always set up here a value of 2.5 SGMII. +- */ +- phy_write(memac->pcsphy, MDIO_SGMII_LINK_TMR_H, LINK_TMR_H_BASEX); +- phy_write(memac->pcsphy, MDIO_SGMII_LINK_TMR_L, LINK_TMR_L_BASEX); +- +- /* Restart AN */ +- tmp_reg16 = SGMII_CR_DEF_VAL | SGMII_CR_RESTART_AN; +- phy_write(memac->pcsphy, 0x0, tmp_reg16); +-} +- +-static int check_init_parameters(struct fman_mac *memac) +-{ +- if (memac->addr == 0) { +- pr_err("Ethernet MAC must have a valid MAC address\n"); +- return -EINVAL; +- } +- if (!memac->exception_cb) { +- pr_err("Uninitialized exception handler\n"); +- return -EINVAL; +- } +- if (!memac->event_cb) { +- pr_warn("Uninitialize event handler\n"); +- return -EINVAL; +- } +- +- return 0; +-} +- +-static int get_exception_flag(enum fman_mac_exceptions exception) +-{ +- u32 bit_mask; +- +- switch (exception) { +- case FM_MAC_EX_10G_TX_ECC_ER: +- bit_mask = MEMAC_IMASK_TECC_ER; +- break; +- case FM_MAC_EX_10G_RX_ECC_ER: +- bit_mask = MEMAC_IMASK_RECC_ER; +- break; +- case FM_MAC_EX_TS_FIFO_ECC_ERR: +- bit_mask = MEMAC_IMASK_TSECC_ER; +- break; +- case FM_MAC_EX_MAGIC_PACKET_INDICATION: +- bit_mask = MEMAC_IMASK_MGI; +- break; +- default: +- bit_mask = 0; +- break; +- } +- +- return bit_mask; +-} +- +-static void memac_err_exception(void *handle) +-{ +- struct fman_mac *memac = (struct fman_mac *)handle; +- struct memac_regs __iomem *regs = memac->regs; +- u32 event, imask; +- +- event = ioread32be(®s->ievent); +- imask = ioread32be(®s->imask); +- +- /* Imask include both error and notification/event bits. +- * Leaving only error bits enabled by imask. +- * The imask error bits are shifted by 16 bits offset from +- * their corresponding location in the ievent - hence the >> 16 +- */ +- event &= ((imask & MEMAC_ALL_ERRS_IMASK) >> 16); +- +- iowrite32be(event, ®s->ievent); +- +- if (event & MEMAC_IEVNT_TS_ECC_ER) +- memac->exception_cb(memac->dev_id, FM_MAC_EX_TS_FIFO_ECC_ERR); +- if (event & MEMAC_IEVNT_TX_ECC_ER) +- memac->exception_cb(memac->dev_id, FM_MAC_EX_10G_TX_ECC_ER); +- if (event & MEMAC_IEVNT_RX_ECC_ER) +- memac->exception_cb(memac->dev_id, FM_MAC_EX_10G_RX_ECC_ER); +-} +- +-static void memac_exception(void *handle) +-{ +- struct fman_mac *memac = (struct fman_mac *)handle; +- struct memac_regs __iomem *regs = memac->regs; +- u32 event, imask; +- +- event = ioread32be(®s->ievent); +- imask = ioread32be(®s->imask); +- +- /* Imask include both error and notification/event bits. +- * Leaving only error bits enabled by imask. +- * The imask error bits are shifted by 16 bits offset from +- * their corresponding location in the ievent - hence the >> 16 +- */ +- event &= ((imask & MEMAC_ALL_ERRS_IMASK) >> 16); +- +- iowrite32be(event, ®s->ievent); +- +- if (event & MEMAC_IEVNT_MGI) +- memac->exception_cb(memac->dev_id, +- FM_MAC_EX_MAGIC_PACKET_INDICATION); +-} +- +-static void free_init_resources(struct fman_mac *memac) +-{ +- fman_unregister_intr(memac->fm, FMAN_MOD_MAC, memac->mac_id, +- FMAN_INTR_TYPE_ERR); +- +- fman_unregister_intr(memac->fm, FMAN_MOD_MAC, memac->mac_id, +- FMAN_INTR_TYPE_NORMAL); +- +- /* release the driver's group hash table */ +- free_hash_table(memac->multicast_addr_hash); +- memac->multicast_addr_hash = NULL; +- +- /* release the driver's individual hash table */ +- free_hash_table(memac->unicast_addr_hash); +- memac->unicast_addr_hash = NULL; +-} +- +-static bool is_init_done(struct memac_cfg *memac_drv_params) +-{ +- /* Checks if mEMAC driver parameters were initialized */ +- if (!memac_drv_params) +- return true; +- +- return false; +-} +- +-int memac_enable(struct fman_mac *memac, enum comm_mode mode) +-{ +- struct memac_regs __iomem *regs = memac->regs; +- u32 tmp; +- +- if (!is_init_done(memac->memac_drv_param)) +- return -EINVAL; +- +- tmp = ioread32be(®s->command_config); +- if (mode & COMM_MODE_RX) +- tmp |= CMD_CFG_RX_EN; +- if (mode & COMM_MODE_TX) +- tmp |= CMD_CFG_TX_EN; +- +- iowrite32be(tmp, ®s->command_config); +- +- return 0; +-} +- +-int memac_disable(struct fman_mac *memac, enum comm_mode mode) +-{ +- struct memac_regs __iomem *regs = memac->regs; +- u32 tmp; +- +- if (!is_init_done(memac->memac_drv_param)) +- return -EINVAL; +- +- tmp = ioread32be(®s->command_config); +- if (mode & COMM_MODE_RX) +- tmp &= ~CMD_CFG_RX_EN; +- if (mode & COMM_MODE_TX) +- tmp &= ~CMD_CFG_TX_EN; +- +- iowrite32be(tmp, ®s->command_config); +- +- return 0; +-} +- +-int memac_set_promiscuous(struct fman_mac *memac, bool new_val) +-{ +- struct memac_regs __iomem *regs = memac->regs; +- u32 tmp; +- +- if (!is_init_done(memac->memac_drv_param)) +- return -EINVAL; +- +- tmp = ioread32be(®s->command_config); +- if (new_val) +- tmp |= CMD_CFG_PROMIS_EN; +- else +- tmp &= ~CMD_CFG_PROMIS_EN; +- +- iowrite32be(tmp, ®s->command_config); +- +- return 0; +-} +- +-int memac_adjust_link(struct fman_mac *memac, u16 speed) +-{ +- struct memac_regs __iomem *regs = memac->regs; +- u32 tmp; +- +- if (!is_init_done(memac->memac_drv_param)) +- return -EINVAL; +- +- tmp = ioread32be(®s->if_mode); +- +- /* Set full duplex */ +- tmp &= ~IF_MODE_HD; +- +- if (memac->phy_if == PHY_INTERFACE_MODE_RGMII) { +- /* Configure RGMII in manual mode */ +- tmp &= ~IF_MODE_RGMII_AUTO; +- tmp &= ~IF_MODE_RGMII_SP_MASK; +- /* Full duplex */ +- tmp |= IF_MODE_RGMII_FD; +- +- switch (speed) { +- case SPEED_1000: +- tmp |= IF_MODE_RGMII_1000; +- break; +- case SPEED_100: +- tmp |= IF_MODE_RGMII_100; +- break; +- case SPEED_10: +- tmp |= IF_MODE_RGMII_10; +- break; +- default: +- break; +- } +- } +- +- iowrite32be(tmp, ®s->if_mode); +- +- return 0; +-} +- +-int memac_cfg_max_frame_len(struct fman_mac *memac, u16 new_val) +-{ +- if (is_init_done(memac->memac_drv_param)) +- return -EINVAL; +- +- memac->memac_drv_param->max_frame_length = new_val; +- +- return 0; +-} +- +-int memac_cfg_reset_on_init(struct fman_mac *memac, bool enable) +-{ +- if (is_init_done(memac->memac_drv_param)) +- return -EINVAL; +- +- memac->memac_drv_param->reset_on_init = enable; +- +- return 0; +-} +- +-int memac_cfg_fixed_link(struct fman_mac *memac, +- struct fixed_phy_status *fixed_link) +-{ +- if (is_init_done(memac->memac_drv_param)) +- return -EINVAL; +- +- memac->memac_drv_param->fixed_link = fixed_link; +- +- return 0; +-} +- +-int memac_set_tx_pause_frames(struct fman_mac *memac, u8 priority, +- u16 pause_time, u16 thresh_time) +-{ +- struct memac_regs __iomem *regs = memac->regs; +- u32 tmp; +- +- if (!is_init_done(memac->memac_drv_param)) +- return -EINVAL; +- +- tmp = ioread32be(®s->tx_fifo_sections); +- +- GET_TX_EMPTY_DEFAULT_VALUE(tmp); +- iowrite32be(tmp, ®s->tx_fifo_sections); +- +- tmp = ioread32be(®s->command_config); +- tmp &= ~CMD_CFG_PFC_MODE; +- priority = 0; +- +- iowrite32be(tmp, ®s->command_config); +- +- tmp = ioread32be(®s->pause_quanta[priority / 2]); +- if (priority % 2) +- tmp &= CLXY_PAUSE_QUANTA_CLX_PQNT; +- else +- tmp &= CLXY_PAUSE_QUANTA_CLY_PQNT; +- tmp |= ((u32)pause_time << (16 * (priority % 2))); +- iowrite32be(tmp, ®s->pause_quanta[priority / 2]); +- +- tmp = ioread32be(®s->pause_thresh[priority / 2]); +- if (priority % 2) +- tmp &= CLXY_PAUSE_THRESH_CLX_QTH; +- else +- tmp &= CLXY_PAUSE_THRESH_CLY_QTH; +- tmp |= ((u32)thresh_time << (16 * (priority % 2))); +- iowrite32be(tmp, ®s->pause_thresh[priority / 2]); +- +- return 0; +-} +- +-int memac_accept_rx_pause_frames(struct fman_mac *memac, bool en) +-{ +- struct memac_regs __iomem *regs = memac->regs; +- u32 tmp; +- +- if (!is_init_done(memac->memac_drv_param)) +- return -EINVAL; +- +- tmp = ioread32be(®s->command_config); +- if (en) +- tmp &= ~CMD_CFG_PAUSE_IGNORE; +- else +- tmp |= CMD_CFG_PAUSE_IGNORE; +- +- iowrite32be(tmp, ®s->command_config); +- +- return 0; +-} +- +-int memac_modify_mac_address(struct fman_mac *memac, enet_addr_t *enet_addr) +-{ +- if (!is_init_done(memac->memac_drv_param)) +- return -EINVAL; +- +- add_addr_in_paddr(memac->regs, (u8 *)(*enet_addr), 0); +- +- return 0; +-} +- +-int memac_add_hash_mac_address(struct fman_mac *memac, enet_addr_t *eth_addr) +-{ +- struct memac_regs __iomem *regs = memac->regs; +- struct eth_hash_entry *hash_entry; +- u32 hash; +- u64 addr; +- +- if (!is_init_done(memac->memac_drv_param)) +- return -EINVAL; +- +- addr = ENET_ADDR_TO_UINT64(*eth_addr); +- +- if (!(addr & GROUP_ADDRESS)) { +- /* Unicast addresses not supported in hash */ +- pr_err("Unicast Address\n"); +- return -EINVAL; +- } +- hash = get_mac_addr_hash_code(addr) & HASH_CTRL_ADDR_MASK; +- +- /* Create element to be added to the driver hash table */ +- hash_entry = kmalloc(sizeof(*hash_entry), GFP_KERNEL); +- if (!hash_entry) +- return -ENOMEM; +- hash_entry->addr = addr; +- INIT_LIST_HEAD(&hash_entry->node); +- +- list_add_tail(&hash_entry->node, +- &memac->multicast_addr_hash->lsts[hash]); +- iowrite32be(hash | HASH_CTRL_MCAST_EN, ®s->hashtable_ctrl); +- +- return 0; +-} +- +-int memac_del_hash_mac_address(struct fman_mac *memac, enet_addr_t *eth_addr) +-{ +- struct memac_regs __iomem *regs = memac->regs; +- struct eth_hash_entry *hash_entry = NULL; +- struct list_head *pos; +- u32 hash; +- u64 addr; +- +- if (!is_init_done(memac->memac_drv_param)) +- return -EINVAL; +- +- addr = ENET_ADDR_TO_UINT64(*eth_addr); +- +- hash = get_mac_addr_hash_code(addr) & HASH_CTRL_ADDR_MASK; +- +- list_for_each(pos, &memac->multicast_addr_hash->lsts[hash]) { +- hash_entry = ETH_HASH_ENTRY_OBJ(pos); +- if (hash_entry->addr == addr) { +- list_del_init(&hash_entry->node); +- kfree(hash_entry); +- break; +- } +- } +- if (list_empty(&memac->multicast_addr_hash->lsts[hash])) +- iowrite32be(hash & ~HASH_CTRL_MCAST_EN, ®s->hashtable_ctrl); +- +- return 0; +-} +- +-int memac_set_exception(struct fman_mac *memac, +- enum fman_mac_exceptions exception, bool enable) +-{ +- u32 bit_mask = 0; +- +- if (!is_init_done(memac->memac_drv_param)) +- return -EINVAL; +- +- bit_mask = get_exception_flag(exception); +- if (bit_mask) { +- if (enable) +- memac->exceptions |= bit_mask; +- else +- memac->exceptions &= ~bit_mask; +- } else { +- pr_err("Undefined exception\n"); +- return -EINVAL; +- } +- set_exception(memac->regs, bit_mask, enable); +- +- return 0; +-} +- +-int memac_init(struct fman_mac *memac) +-{ +- struct memac_cfg *memac_drv_param; +- u8 i; +- enet_addr_t eth_addr; +- bool slow_10g_if = false; +- struct fixed_phy_status *fixed_link; +- int err; +- u32 reg32 = 0; +- +- if (is_init_done(memac->memac_drv_param)) +- return -EINVAL; +- +- err = check_init_parameters(memac); +- if (err) +- return err; +- +- memac_drv_param = memac->memac_drv_param; +- +- if (memac->fm_rev_info.major == 6 && memac->fm_rev_info.minor == 4) +- slow_10g_if = true; +- +- /* First, reset the MAC if desired. */ +- if (memac_drv_param->reset_on_init) { +- err = reset(memac->regs); +- if (err) { +- pr_err("mEMAC reset failed\n"); +- return err; +- } +- } +- +- /* MAC Address */ +- MAKE_ENET_ADDR_FROM_UINT64(memac->addr, eth_addr); +- add_addr_in_paddr(memac->regs, (u8 *)eth_addr, 0); +- +- fixed_link = memac_drv_param->fixed_link; +- +- init(memac->regs, memac->memac_drv_param, memac->phy_if, +- memac->max_speed, slow_10g_if, memac->exceptions); +- +- /* FM_RX_FIFO_CORRUPT_ERRATA_10GMAC_A006320 errata workaround +- * Exists only in FMan 6.0 and 6.3. +- */ +- if ((memac->fm_rev_info.major == 6) && +- ((memac->fm_rev_info.minor == 0) || +- (memac->fm_rev_info.minor == 3))) { +- /* MAC strips CRC from received frames - this workaround +- * should decrease the likelihood of bug appearance +- */ +- reg32 = ioread32be(&memac->regs->command_config); +- reg32 &= ~CMD_CFG_CRC_FWD; +- iowrite32be(reg32, &memac->regs->command_config); +- } +- +- if (memac->phy_if == PHY_INTERFACE_MODE_SGMII) { +- /* Configure internal SGMII PHY */ +- if (memac->basex_if) +- setup_sgmii_internal_phy_base_x(memac); +- else +- setup_sgmii_internal_phy(memac, fixed_link); +- } else if (memac->phy_if == PHY_INTERFACE_MODE_QSGMII) { +- /* Configure 4 internal SGMII PHYs */ +- for (i = 0; i < 4; i++) { +- u8 qsmgii_phy_addr, phy_addr; +- /* QSGMII PHY address occupies 3 upper bits of 5-bit +- * phy_address; the lower 2 bits are used to extend +- * register address space and access each one of 4 +- * ports inside QSGMII. +- */ +- phy_addr = memac->pcsphy->mdio.addr; +- qsmgii_phy_addr = (u8)((phy_addr << 2) | i); +- memac->pcsphy->mdio.addr = qsmgii_phy_addr; +- if (memac->basex_if) +- setup_sgmii_internal_phy_base_x(memac); +- else +- setup_sgmii_internal_phy(memac, fixed_link); +- +- memac->pcsphy->mdio.addr = phy_addr; +- } +- } +- +- /* Max Frame Length */ +- err = fman_set_mac_max_frame(memac->fm, memac->mac_id, +- memac_drv_param->max_frame_length); +- if (err) { +- pr_err("settings Mac max frame length is FAILED\n"); +- return err; +- } +- +- memac->multicast_addr_hash = alloc_hash_table(HASH_TABLE_SIZE); +- if (!memac->multicast_addr_hash) { +- free_init_resources(memac); +- pr_err("allocation hash table is FAILED\n"); +- return -ENOMEM; +- } +- +- memac->unicast_addr_hash = alloc_hash_table(HASH_TABLE_SIZE); +- if (!memac->unicast_addr_hash) { +- free_init_resources(memac); +- pr_err("allocation hash table is FAILED\n"); +- return -ENOMEM; +- } +- +- fman_register_intr(memac->fm, FMAN_MOD_MAC, memac->mac_id, +- FMAN_INTR_TYPE_ERR, memac_err_exception, memac); +- +- fman_register_intr(memac->fm, FMAN_MOD_MAC, memac->mac_id, +- FMAN_INTR_TYPE_NORMAL, memac_exception, memac); +- +- kfree(memac_drv_param); +- memac->memac_drv_param = NULL; +- +- return 0; +-} +- +-int memac_free(struct fman_mac *memac) +-{ +- free_init_resources(memac); +- +- if (memac->pcsphy) +- put_device(&memac->pcsphy->mdio.dev); +- +- kfree(memac->memac_drv_param); +- kfree(memac); +- +- return 0; +-} +- +-struct fman_mac *memac_config(struct fman_mac_params *params) +-{ +- struct fman_mac *memac; +- struct memac_cfg *memac_drv_param; +- void __iomem *base_addr; +- +- base_addr = params->base_addr; +- /* allocate memory for the m_emac data structure */ +- memac = kzalloc(sizeof(*memac), GFP_KERNEL); +- if (!memac) +- return NULL; +- +- /* allocate memory for the m_emac driver parameters data structure */ +- memac_drv_param = kzalloc(sizeof(*memac_drv_param), GFP_KERNEL); +- if (!memac_drv_param) { +- memac_free(memac); +- return NULL; +- } +- +- /* Plant parameter structure pointer */ +- memac->memac_drv_param = memac_drv_param; +- +- set_dflts(memac_drv_param); +- +- memac->addr = ENET_ADDR_TO_UINT64(params->addr); +- +- memac->regs = base_addr; +- memac->max_speed = params->max_speed; +- memac->phy_if = params->phy_if; +- memac->mac_id = params->mac_id; +- memac->exceptions = (MEMAC_IMASK_TSECC_ER | MEMAC_IMASK_TECC_ER | +- MEMAC_IMASK_RECC_ER | MEMAC_IMASK_MGI); +- memac->exception_cb = params->exception_cb; +- memac->event_cb = params->event_cb; +- memac->dev_id = params->dev_id; +- memac->fm = params->fm; +- memac->basex_if = params->basex_if; +- +- /* Save FMan revision */ +- fman_get_revision(memac->fm, &memac->fm_rev_info); +- +- if (memac->phy_if == PHY_INTERFACE_MODE_SGMII || +- memac->phy_if == PHY_INTERFACE_MODE_QSGMII) { +- if (!params->internal_phy_node) { +- pr_err("PCS PHY node is not available\n"); +- memac_free(memac); +- return NULL; +- } +- +- memac->pcsphy = of_phy_find_device(params->internal_phy_node); +- if (!memac->pcsphy) { +- pr_err("of_phy_find_device (PCS PHY) failed\n"); +- memac_free(memac); +- return NULL; +- } +- } +- +- return memac; +-} +diff --git a/drivers/net/ethernet/freescale/fman/fman_memac.h b/drivers/net/ethernet/freescale/fman/fman_memac.h +deleted file mode 100644 +index 173d8e0..0000000 +--- a/drivers/net/ethernet/freescale/fman/fman_memac.h ++++ /dev/null +@@ -1,60 +0,0 @@ +-/* +- * Copyright 2008-2015 Freescale Semiconductor Inc. +- * +- * Redistribution and use in source and binary forms, with or without +- * modification, are permitted provided that the following conditions are met: +- * * Redistributions of source code must retain the above copyright +- * notice, this list of conditions and the following disclaimer. +- * * Redistributions in binary form must reproduce the above copyright +- * notice, this list of conditions and the following disclaimer in the +- * documentation and/or other materials provided with the distribution. +- * * Neither the name of Freescale Semiconductor nor the +- * names of its contributors may be used to endorse or promote products +- * derived from this software without specific prior written permission. +- * +- * +- * ALTERNATIVELY, this software may be distributed under the terms of the +- * GNU General Public License ("GPL") as published by the Free Software +- * Foundation, either version 2 of that License or (at your option) any +- * later version. +- * +- * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY +- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +- * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY +- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +- */ +- +-#ifndef __MEMAC_H +-#define __MEMAC_H +- +-#include "fman_mac.h" +- +-#include +- +-struct fman_mac *memac_config(struct fman_mac_params *params); +-int memac_set_promiscuous(struct fman_mac *memac, bool new_val); +-int memac_modify_mac_address(struct fman_mac *memac, enet_addr_t *enet_addr); +-int memac_adjust_link(struct fman_mac *memac, u16 speed); +-int memac_cfg_max_frame_len(struct fman_mac *memac, u16 new_val); +-int memac_cfg_reset_on_init(struct fman_mac *memac, bool enable); +-int memac_cfg_fixed_link(struct fman_mac *memac, +- struct fixed_phy_status *fixed_link); +-int memac_enable(struct fman_mac *memac, enum comm_mode mode); +-int memac_disable(struct fman_mac *memac, enum comm_mode mode); +-int memac_init(struct fman_mac *memac); +-int memac_free(struct fman_mac *memac); +-int memac_accept_rx_pause_frames(struct fman_mac *memac, bool en); +-int memac_set_tx_pause_frames(struct fman_mac *memac, u8 priority, +- u16 pause_time, u16 thresh_time); +-int memac_set_exception(struct fman_mac *memac, +- enum fman_mac_exceptions exception, bool enable); +-int memac_add_hash_mac_address(struct fman_mac *memac, enet_addr_t *eth_addr); +-int memac_del_hash_mac_address(struct fman_mac *memac, enet_addr_t *eth_addr); +- +-#endif /* __MEMAC_H */ +diff --git a/drivers/net/ethernet/freescale/fman/fman_muram.c b/drivers/net/ethernet/freescale/fman/fman_muram.c +deleted file mode 100644 +index 5ec94d2..0000000 +--- a/drivers/net/ethernet/freescale/fman/fman_muram.c ++++ /dev/null +@@ -1,159 +0,0 @@ +-/* +- * Copyright 2008-2015 Freescale Semiconductor Inc. +- * +- * Redistribution and use in source and binary forms, with or without +- * modification, are permitted provided that the following conditions are met: +- * * Redistributions of source code must retain the above copyright +- * notice, this list of conditions and the following disclaimer. +- * * Redistributions in binary form must reproduce the above copyright +- * notice, this list of conditions and the following disclaimer in the +- * documentation and/or other materials provided with the distribution. +- * * Neither the name of Freescale Semiconductor nor the +- * names of its contributors may be used to endorse or promote products +- * derived from this software without specific prior written permission. +- * +- * +- * ALTERNATIVELY, this software may be distributed under the terms of the +- * GNU General Public License ("GPL") as published by the Free Software +- * Foundation, either version 2 of that License or (at your option) any +- * later version. +- * +- * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY +- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +- * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY +- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +- */ +- +-#include "fman_muram.h" +- +-#include +-#include +-#include +- +-struct muram_info { +- struct gen_pool *pool; +- void __iomem *vbase; +- size_t size; +- phys_addr_t pbase; +-}; +- +-static unsigned long fman_muram_vbase_to_offset(struct muram_info *muram, +- unsigned long vaddr) +-{ +- return vaddr - (unsigned long)muram->vbase; +-} +- +-/** +- * fman_muram_init +- * @base: Pointer to base of memory mapped FM-MURAM. +- * @size: Size of the FM-MURAM partition. +- * +- * Creates partition in the MURAM. +- * The routine returns a pointer to the MURAM partition. +- * This pointer must be passed as to all other FM-MURAM function calls. +- * No actual initialization or configuration of FM_MURAM hardware is done by +- * this routine. +- * +- * Return: pointer to FM-MURAM object, or NULL for Failure. +- */ +-struct muram_info *fman_muram_init(phys_addr_t base, size_t size) +-{ +- struct muram_info *muram; +- void __iomem *vaddr; +- int ret; +- +- muram = kzalloc(sizeof(*muram), GFP_KERNEL); +- if (!muram) +- return NULL; +- +- muram->pool = gen_pool_create(ilog2(64), -1); +- if (!muram->pool) { +- pr_err("%s(): MURAM pool create failed\n", __func__); +- goto muram_free; +- } +- +- vaddr = ioremap(base, size); +- if (!vaddr) { +- pr_err("%s(): MURAM ioremap failed\n", __func__); +- goto pool_destroy; +- } +- +- ret = gen_pool_add_virt(muram->pool, (unsigned long)vaddr, +- base, size, -1); +- if (ret < 0) { +- pr_err("%s(): MURAM pool add failed\n", __func__); +- iounmap(vaddr); +- goto pool_destroy; +- } +- +- memset_io(vaddr, 0, (int)size); +- +- muram->vbase = vaddr; +- muram->pbase = base; +- return muram; +- +-pool_destroy: +- gen_pool_destroy(muram->pool); +-muram_free: +- kfree(muram); +- return NULL; +-} +- +-/** +- * fman_muram_offset_to_vbase +- * @muram: FM-MURAM module pointer. +- * @offset: the offset of the memory block +- * +- * Gives the address of the memory region from specific offset +- * +- * Return: The address of the memory block +- */ +-unsigned long fman_muram_offset_to_vbase(struct muram_info *muram, +- unsigned long offset) +-{ +- return offset + (unsigned long)muram->vbase; +-} +- +-/** +- * fman_muram_alloc +- * @muram: FM-MURAM module pointer. +- * @size: Size of the memory to be allocated. +- * +- * Allocate some memory from FM-MURAM partition. +- * +- * Return: address of the allocated memory; NULL otherwise. +- */ +-unsigned long fman_muram_alloc(struct muram_info *muram, size_t size) +-{ +- unsigned long vaddr; +- +- vaddr = gen_pool_alloc(muram->pool, size); +- if (!vaddr) +- return -ENOMEM; +- +- memset_io((void __iomem *)vaddr, 0, size); +- +- return fman_muram_vbase_to_offset(muram, vaddr); +-} +- +-/** +- * fman_muram_free_mem +- * muram: FM-MURAM module pointer. +- * offset: offset of the memory region to be freed. +- * size: size of the memory to be freed. +- * +- * Free an allocated memory from FM-MURAM partition. +- */ +-void fman_muram_free_mem(struct muram_info *muram, unsigned long offset, +- size_t size) +-{ +- unsigned long addr = fman_muram_offset_to_vbase(muram, offset); +- +- gen_pool_free(muram->pool, addr, size); +-} +diff --git a/drivers/net/ethernet/freescale/fman/fman_muram.h b/drivers/net/ethernet/freescale/fman/fman_muram.h +deleted file mode 100644 +index 453bf84..0000000 +--- a/drivers/net/ethernet/freescale/fman/fman_muram.h ++++ /dev/null +@@ -1,52 +0,0 @@ +-/* +- * Copyright 2008-2015 Freescale Semiconductor Inc. +- * +- * Redistribution and use in source and binary forms, with or without +- * modification, are permitted provided that the following conditions are met: +- * * Redistributions of source code must retain the above copyright +- * notice, this list of conditions and the following disclaimer. +- * * Redistributions in binary form must reproduce the above copyright +- * notice, this list of conditions and the following disclaimer in the +- * documentation and/or other materials provided with the distribution. +- * * Neither the name of Freescale Semiconductor nor the +- * names of its contributors may be used to endorse or promote products +- * derived from this software without specific prior written permission. +- * +- * +- * ALTERNATIVELY, this software may be distributed under the terms of the +- * GNU General Public License ("GPL") as published by the Free Software +- * Foundation, either version 2 of that License or (at your option) any +- * later version. +- * +- * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY +- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +- * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY +- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +- */ +-#ifndef __FM_MURAM_EXT +-#define __FM_MURAM_EXT +- +-#include +- +-#define FM_MURAM_INVALID_ALLOCATION -1 +- +-/* Structure for FM MURAM information */ +-struct muram_info; +- +-struct muram_info *fman_muram_init(phys_addr_t base, size_t size); +- +-unsigned long fman_muram_offset_to_vbase(struct muram_info *muram, +- unsigned long offset); +- +-unsigned long fman_muram_alloc(struct muram_info *muram, size_t size); +- +-void fman_muram_free_mem(struct muram_info *muram, unsigned long offset, +- size_t size); +- +-#endif /* __FM_MURAM_EXT */ +diff --git a/drivers/net/ethernet/freescale/fman/fman_port.c b/drivers/net/ethernet/freescale/fman/fman_port.c +deleted file mode 100644 +index 9f3bb50..0000000 +--- a/drivers/net/ethernet/freescale/fman/fman_port.c ++++ /dev/null +@@ -1,1791 +0,0 @@ +-/* +- * Copyright 2008 - 2015 Freescale Semiconductor Inc. +- * +- * Redistribution and use in source and binary forms, with or without +- * modification, are permitted provided that the following conditions are met: +- * * Redistributions of source code must retain the above copyright +- * notice, this list of conditions and the following disclaimer. +- * * Redistributions in binary form must reproduce the above copyright +- * notice, this list of conditions and the following disclaimer in the +- * documentation and/or other materials provided with the distribution. +- * * Neither the name of Freescale Semiconductor nor the +- * names of its contributors may be used to endorse or promote products +- * derived from this software without specific prior written permission. +- * +- * +- * ALTERNATIVELY, this software may be distributed under the terms of the +- * GNU General Public License ("GPL") as published by the Free Software +- * Foundation, either version 2 of that License or (at your option) any +- * later version. +- * +- * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY +- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +- * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY +- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +- */ +- +-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +- +-#include "fman_port.h" +-#include "fman.h" +-#include "fman_sp.h" +- +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-/* Queue ID */ +-#define DFLT_FQ_ID 0x00FFFFFF +- +-/* General defines */ +-#define PORT_BMI_FIFO_UNITS 0x100 +- +-#define MAX_PORT_FIFO_SIZE(bmi_max_fifo_size) \ +- min((u32)bmi_max_fifo_size, (u32)1024 * FMAN_BMI_FIFO_UNITS) +- +-#define PORT_CG_MAP_NUM 8 +-#define PORT_PRS_RESULT_WORDS_NUM 8 +-#define PORT_IC_OFFSET_UNITS 0x10 +- +-#define MIN_EXT_BUF_SIZE 64 +- +-#define BMI_PORT_REGS_OFFSET 0 +-#define QMI_PORT_REGS_OFFSET 0x400 +- +-/* Default values */ +-#define DFLT_PORT_BUFFER_PREFIX_CONTEXT_DATA_ALIGN \ +- DFLT_FM_SP_BUFFER_PREFIX_CONTEXT_DATA_ALIGN +- +-#define DFLT_PORT_CUT_BYTES_FROM_END 4 +- +-#define DFLT_PORT_ERRORS_TO_DISCARD FM_PORT_FRM_ERR_CLS_DISCARD +-#define DFLT_PORT_MAX_FRAME_LENGTH 9600 +- +-#define DFLT_PORT_RX_FIFO_PRI_ELEVATION_LEV(bmi_max_fifo_size) \ +- MAX_PORT_FIFO_SIZE(bmi_max_fifo_size) +- +-#define DFLT_PORT_RX_FIFO_THRESHOLD(major, bmi_max_fifo_size) \ +- (major == 6 ? \ +- MAX_PORT_FIFO_SIZE(bmi_max_fifo_size) : \ +- (MAX_PORT_FIFO_SIZE(bmi_max_fifo_size) * 3 / 4)) \ +- +-#define DFLT_PORT_EXTRA_NUM_OF_FIFO_BUFS 0 +- +-/* QMI defines */ +-#define QMI_DEQ_CFG_SUBPORTAL_MASK 0x1f +- +-#define QMI_PORT_CFG_EN 0x80000000 +-#define QMI_PORT_STATUS_DEQ_FD_BSY 0x20000000 +- +-#define QMI_DEQ_CFG_PRI 0x80000000 +-#define QMI_DEQ_CFG_TYPE1 0x10000000 +-#define QMI_DEQ_CFG_TYPE2 0x20000000 +-#define QMI_DEQ_CFG_TYPE3 0x30000000 +-#define QMI_DEQ_CFG_PREFETCH_PARTIAL 0x01000000 +-#define QMI_DEQ_CFG_PREFETCH_FULL 0x03000000 +-#define QMI_DEQ_CFG_SP_MASK 0xf +-#define QMI_DEQ_CFG_SP_SHIFT 20 +- +-#define QMI_BYTE_COUNT_LEVEL_CONTROL(_type) \ +- (_type == FMAN_PORT_TYPE_TX ? 0x1400 : 0x400) +- +-/* BMI defins */ +-#define BMI_EBD_EN 0x80000000 +- +-#define BMI_PORT_CFG_EN 0x80000000 +- +-#define BMI_PORT_STATUS_BSY 0x80000000 +- +-#define BMI_DMA_ATTR_SWP_SHIFT FMAN_SP_DMA_ATTR_SWP_SHIFT +-#define BMI_DMA_ATTR_WRITE_OPTIMIZE FMAN_SP_DMA_ATTR_WRITE_OPTIMIZE +- +-#define BMI_RX_FIFO_PRI_ELEVATION_SHIFT 16 +-#define BMI_RX_FIFO_THRESHOLD_ETHE 0x80000000 +- +-#define BMI_FRAME_END_CS_IGNORE_SHIFT 24 +-#define BMI_FRAME_END_CS_IGNORE_MASK 0x0000001f +- +-#define BMI_RX_FRAME_END_CUT_SHIFT 16 +-#define BMI_RX_FRAME_END_CUT_MASK 0x0000001f +- +-#define BMI_IC_TO_EXT_SHIFT FMAN_SP_IC_TO_EXT_SHIFT +-#define BMI_IC_TO_EXT_MASK 0x0000001f +-#define BMI_IC_FROM_INT_SHIFT FMAN_SP_IC_FROM_INT_SHIFT +-#define BMI_IC_FROM_INT_MASK 0x0000000f +-#define BMI_IC_SIZE_MASK 0x0000001f +- +-#define BMI_INT_BUF_MARG_SHIFT 28 +-#define BMI_INT_BUF_MARG_MASK 0x0000000f +-#define BMI_EXT_BUF_MARG_START_SHIFT FMAN_SP_EXT_BUF_MARG_START_SHIFT +-#define BMI_EXT_BUF_MARG_START_MASK 0x000001ff +-#define BMI_EXT_BUF_MARG_END_MASK 0x000001ff +- +-#define BMI_CMD_MR_LEAC 0x00200000 +-#define BMI_CMD_MR_SLEAC 0x00100000 +-#define BMI_CMD_MR_MA 0x00080000 +-#define BMI_CMD_MR_DEAS 0x00040000 +-#define BMI_CMD_RX_MR_DEF (BMI_CMD_MR_LEAC | \ +- BMI_CMD_MR_SLEAC | \ +- BMI_CMD_MR_MA | \ +- BMI_CMD_MR_DEAS) +-#define BMI_CMD_TX_MR_DEF 0 +- +-#define BMI_CMD_ATTR_ORDER 0x80000000 +-#define BMI_CMD_ATTR_SYNC 0x02000000 +-#define BMI_CMD_ATTR_COLOR_SHIFT 26 +- +-#define BMI_FIFO_PIPELINE_DEPTH_SHIFT 12 +-#define BMI_FIFO_PIPELINE_DEPTH_MASK 0x0000000f +-#define BMI_NEXT_ENG_FD_BITS_SHIFT 24 +- +-#define BMI_EXT_BUF_POOL_VALID FMAN_SP_EXT_BUF_POOL_VALID +-#define BMI_EXT_BUF_POOL_EN_COUNTER FMAN_SP_EXT_BUF_POOL_EN_COUNTER +-#define BMI_EXT_BUF_POOL_BACKUP FMAN_SP_EXT_BUF_POOL_BACKUP +-#define BMI_EXT_BUF_POOL_ID_SHIFT 16 +-#define BMI_EXT_BUF_POOL_ID_MASK 0x003F0000 +-#define BMI_POOL_DEP_NUM_OF_POOLS_SHIFT 16 +- +-#define BMI_TX_FIFO_MIN_FILL_SHIFT 16 +- +-#define BMI_PRIORITY_ELEVATION_LEVEL ((0x3FF + 1) * PORT_BMI_FIFO_UNITS) +-#define BMI_FIFO_THRESHOLD ((0x3FF + 1) * PORT_BMI_FIFO_UNITS) +- +-#define BMI_DEQUEUE_PIPELINE_DEPTH(_type, _speed) \ +- ((_type == FMAN_PORT_TYPE_TX && _speed == 10000) ? 4 : 1) +- +-#define RX_ERRS_TO_ENQ \ +- (FM_PORT_FRM_ERR_DMA | \ +- FM_PORT_FRM_ERR_PHYSICAL | \ +- FM_PORT_FRM_ERR_SIZE | \ +- FM_PORT_FRM_ERR_EXTRACTION | \ +- FM_PORT_FRM_ERR_NO_SCHEME | \ +- FM_PORT_FRM_ERR_PRS_TIMEOUT | \ +- FM_PORT_FRM_ERR_PRS_ILL_INSTRUCT | \ +- FM_PORT_FRM_ERR_BLOCK_LIMIT_EXCEEDED | \ +- FM_PORT_FRM_ERR_PRS_HDR_ERR | \ +- FM_PORT_FRM_ERR_KEYSIZE_OVERFLOW | \ +- FM_PORT_FRM_ERR_IPRE) +- +-/* NIA defines */ +-#define NIA_ORDER_RESTOR 0x00800000 +-#define NIA_ENG_BMI 0x00500000 +-#define NIA_ENG_QMI_ENQ 0x00540000 +-#define NIA_ENG_QMI_DEQ 0x00580000 +- +-#define NIA_BMI_AC_ENQ_FRAME 0x00000002 +-#define NIA_BMI_AC_TX_RELEASE 0x000002C0 +-#define NIA_BMI_AC_RELEASE 0x000000C0 +-#define NIA_BMI_AC_TX 0x00000274 +-#define NIA_BMI_AC_FETCH_ALL_FRAME 0x0000020c +- +-/* Port IDs */ +-#define TX_10G_PORT_BASE 0x30 +-#define RX_10G_PORT_BASE 0x10 +- +-/* BMI Rx port register map */ +-struct fman_port_rx_bmi_regs { +- u32 fmbm_rcfg; /* Rx Configuration */ +- u32 fmbm_rst; /* Rx Status */ +- u32 fmbm_rda; /* Rx DMA attributes */ +- u32 fmbm_rfp; /* Rx FIFO Parameters */ +- u32 fmbm_rfed; /* Rx Frame End Data */ +- u32 fmbm_ricp; /* Rx Internal Context Parameters */ +- u32 fmbm_rim; /* Rx Internal Buffer Margins */ +- u32 fmbm_rebm; /* Rx External Buffer Margins */ +- u32 fmbm_rfne; /* Rx Frame Next Engine */ +- u32 fmbm_rfca; /* Rx Frame Command Attributes. */ +- u32 fmbm_rfpne; /* Rx Frame Parser Next Engine */ +- u32 fmbm_rpso; /* Rx Parse Start Offset */ +- u32 fmbm_rpp; /* Rx Policer Profile */ +- u32 fmbm_rccb; /* Rx Coarse Classification Base */ +- u32 fmbm_reth; /* Rx Excessive Threshold */ +- u32 reserved003c[1]; /* (0x03C 0x03F) */ +- u32 fmbm_rprai[PORT_PRS_RESULT_WORDS_NUM]; +- /* Rx Parse Results Array Init */ +- u32 fmbm_rfqid; /* Rx Frame Queue ID */ +- u32 fmbm_refqid; /* Rx Error Frame Queue ID */ +- u32 fmbm_rfsdm; /* Rx Frame Status Discard Mask */ +- u32 fmbm_rfsem; /* Rx Frame Status Error Mask */ +- u32 fmbm_rfene; /* Rx Frame Enqueue Next Engine */ +- u32 reserved0074[0x2]; /* (0x074-0x07C) */ +- u32 fmbm_rcmne; /* Rx Frame Continuous Mode Next Engine */ +- u32 reserved0080[0x20]; /* (0x080 0x0FF) */ +- u32 fmbm_ebmpi[FMAN_PORT_MAX_EXT_POOLS_NUM]; +- /* Buffer Manager pool Information- */ +- u32 fmbm_acnt[FMAN_PORT_MAX_EXT_POOLS_NUM]; /* Allocate Counter- */ +- u32 reserved0130[8]; /* 0x130/0x140 - 0x15F reserved - */ +- u32 fmbm_rcgm[PORT_CG_MAP_NUM]; /* Congestion Group Map */ +- u32 fmbm_mpd; /* BM Pool Depletion */ +- u32 reserved0184[0x1F]; /* (0x184 0x1FF) */ +- u32 fmbm_rstc; /* Rx Statistics Counters */ +- u32 fmbm_rfrc; /* Rx Frame Counter */ +- u32 fmbm_rfbc; /* Rx Bad Frames Counter */ +- u32 fmbm_rlfc; /* Rx Large Frames Counter */ +- u32 fmbm_rffc; /* Rx Filter Frames Counter */ +- u32 fmbm_rfdc; /* Rx Frame Discard Counter */ +- u32 fmbm_rfldec; /* Rx Frames List DMA Error Counter */ +- u32 fmbm_rodc; /* Rx Out of Buffers Discard nntr */ +- u32 fmbm_rbdc; /* Rx Buffers Deallocate Counter */ +- u32 fmbm_rpec; /* RX Prepare to enqueue Counte */ +- u32 reserved0224[0x16]; /* (0x224 0x27F) */ +- u32 fmbm_rpc; /* Rx Performance Counters */ +- u32 fmbm_rpcp; /* Rx Performance Count Parameters */ +- u32 fmbm_rccn; /* Rx Cycle Counter */ +- u32 fmbm_rtuc; /* Rx Tasks Utilization Counter */ +- u32 fmbm_rrquc; /* Rx Receive Queue Utilization cntr */ +- u32 fmbm_rduc; /* Rx DMA Utilization Counter */ +- u32 fmbm_rfuc; /* Rx FIFO Utilization Counter */ +- u32 fmbm_rpac; /* Rx Pause Activation Counter */ +- u32 reserved02a0[0x18]; /* (0x2A0 0x2FF) */ +- u32 fmbm_rdcfg[0x3]; /* Rx Debug Configuration */ +- u32 fmbm_rgpr; /* Rx General Purpose Register */ +- u32 reserved0310[0x3a]; +-}; +- +-/* BMI Tx port register map */ +-struct fman_port_tx_bmi_regs { +- u32 fmbm_tcfg; /* Tx Configuration */ +- u32 fmbm_tst; /* Tx Status */ +- u32 fmbm_tda; /* Tx DMA attributes */ +- u32 fmbm_tfp; /* Tx FIFO Parameters */ +- u32 fmbm_tfed; /* Tx Frame End Data */ +- u32 fmbm_ticp; /* Tx Internal Context Parameters */ +- u32 fmbm_tfdne; /* Tx Frame Dequeue Next Engine. */ +- u32 fmbm_tfca; /* Tx Frame Command attribute. */ +- u32 fmbm_tcfqid; /* Tx Confirmation Frame Queue ID. */ +- u32 fmbm_tefqid; /* Tx Frame Error Queue ID */ +- u32 fmbm_tfene; /* Tx Frame Enqueue Next Engine */ +- u32 fmbm_trlmts; /* Tx Rate Limiter Scale */ +- u32 fmbm_trlmt; /* Tx Rate Limiter */ +- u32 reserved0034[0x0e]; /* (0x034-0x6c) */ +- u32 fmbm_tccb; /* Tx Coarse Classification base */ +- u32 fmbm_tfne; /* Tx Frame Next Engine */ +- u32 fmbm_tpfcm[0x02]; +- /* Tx Priority based Flow Control (PFC) Mapping */ +- u32 fmbm_tcmne; /* Tx Frame Continuous Mode Next Engine */ +- u32 reserved0080[0x60]; /* (0x080-0x200) */ +- u32 fmbm_tstc; /* Tx Statistics Counters */ +- u32 fmbm_tfrc; /* Tx Frame Counter */ +- u32 fmbm_tfdc; /* Tx Frames Discard Counter */ +- u32 fmbm_tfledc; /* Tx Frame len error discard cntr */ +- u32 fmbm_tfufdc; /* Tx Frame unsprt frmt discard cntr */ +- u32 fmbm_tbdc; /* Tx Buffers Deallocate Counter */ +- u32 reserved0218[0x1A]; /* (0x218-0x280) */ +- u32 fmbm_tpc; /* Tx Performance Counters */ +- u32 fmbm_tpcp; /* Tx Performance Count Parameters */ +- u32 fmbm_tccn; /* Tx Cycle Counter */ +- u32 fmbm_ttuc; /* Tx Tasks Utilization Counter */ +- u32 fmbm_ttcquc; /* Tx Transmit conf Q util Counter */ +- u32 fmbm_tduc; /* Tx DMA Utilization Counter */ +- u32 fmbm_tfuc; /* Tx FIFO Utilization Counter */ +- u32 reserved029c[16]; /* (0x29C-0x2FF) */ +- u32 fmbm_tdcfg[0x3]; /* Tx Debug Configuration */ +- u32 fmbm_tgpr; /* Tx General Purpose Register */ +- u32 reserved0310[0x3a]; /* (0x310-0x3FF) */ +-}; +- +-/* BMI port register map */ +-union fman_port_bmi_regs { +- struct fman_port_rx_bmi_regs rx; +- struct fman_port_tx_bmi_regs tx; +-}; +- +-/* QMI port register map */ +-struct fman_port_qmi_regs { +- u32 fmqm_pnc; /* PortID n Configuration Register */ +- u32 fmqm_pns; /* PortID n Status Register */ +- u32 fmqm_pnts; /* PortID n Task Status Register */ +- u32 reserved00c[4]; /* 0xn00C - 0xn01B */ +- u32 fmqm_pnen; /* PortID n Enqueue NIA Register */ +- u32 fmqm_pnetfc; /* PortID n Enq Total Frame Counter */ +- u32 reserved024[2]; /* 0xn024 - 0x02B */ +- u32 fmqm_pndn; /* PortID n Dequeue NIA Register */ +- u32 fmqm_pndc; /* PortID n Dequeue Config Register */ +- u32 fmqm_pndtfc; /* PortID n Dequeue tot Frame cntr */ +- u32 fmqm_pndfdc; /* PortID n Dequeue FQID Dflt Cntr */ +- u32 fmqm_pndcc; /* PortID n Dequeue Confirm Counter */ +-}; +- +-/* QMI dequeue prefetch modes */ +-enum fman_port_deq_prefetch { +- FMAN_PORT_DEQ_NO_PREFETCH, /* No prefetch mode */ +- FMAN_PORT_DEQ_PART_PREFETCH, /* Partial prefetch mode */ +- FMAN_PORT_DEQ_FULL_PREFETCH /* Full prefetch mode */ +-}; +- +-/* A structure for defining FM port resources */ +-struct fman_port_rsrc { +- u32 num; /* Committed required resource */ +- u32 extra; /* Extra (not committed) required resource */ +-}; +- +-enum fman_port_dma_swap { +- FMAN_PORT_DMA_NO_SWAP, /* No swap, transfer data as is */ +- FMAN_PORT_DMA_SWAP_LE, +- /* The transferred data should be swapped in PPC Little Endian mode */ +- FMAN_PORT_DMA_SWAP_BE +- /* The transferred data should be swapped in Big Endian mode */ +-}; +- +-/* Default port color */ +-enum fman_port_color { +- FMAN_PORT_COLOR_GREEN, /* Default port color is green */ +- FMAN_PORT_COLOR_YELLOW, /* Default port color is yellow */ +- FMAN_PORT_COLOR_RED, /* Default port color is red */ +- FMAN_PORT_COLOR_OVERRIDE /* Ignore color */ +-}; +- +-/* QMI dequeue from the SP channel - types */ +-enum fman_port_deq_type { +- FMAN_PORT_DEQ_BY_PRI, +- /* Priority precedence and Intra-Class scheduling */ +- FMAN_PORT_DEQ_ACTIVE_FQ, +- /* Active FQ precedence and Intra-Class scheduling */ +- FMAN_PORT_DEQ_ACTIVE_FQ_NO_ICS +- /* Active FQ precedence and override Intra-Class scheduling */ +-}; +- +-/* External buffer pools configuration */ +-struct fman_port_bpools { +- u8 count; /* Num of pools to set up */ +- bool counters_enable; /* Enable allocate counters */ +- u8 grp_bp_depleted_num; +- /* Number of depleted pools - if reached the BMI indicates +- * the MAC to send a pause frame +- */ +- struct { +- u8 bpid; /* BM pool ID */ +- u16 size; +- /* Pool's size - must be in ascending order */ +- bool is_backup; +- /* If this is a backup pool */ +- bool grp_bp_depleted; +- /* Consider this buffer in multiple pools depletion criteria */ +- bool single_bp_depleted; +- /* Consider this buffer in single pool depletion criteria */ +- } bpool[FMAN_PORT_MAX_EXT_POOLS_NUM]; +-}; +- +-struct fman_port_cfg { +- u32 dflt_fqid; +- u32 err_fqid; +- u8 deq_sp; +- bool deq_high_priority; +- enum fman_port_deq_type deq_type; +- enum fman_port_deq_prefetch deq_prefetch_option; +- u16 deq_byte_cnt; +- u8 cheksum_last_bytes_ignore; +- u8 rx_cut_end_bytes; +- struct fman_buf_pool_depletion buf_pool_depletion; +- struct fman_ext_pools ext_buf_pools; +- u32 tx_fifo_min_level; +- u32 tx_fifo_low_comf_level; +- u32 rx_pri_elevation; +- u32 rx_fifo_thr; +- struct fman_sp_buf_margins buf_margins; +- u32 int_buf_start_margin; +- struct fman_sp_int_context_data_copy int_context; +- u32 discard_mask; +- u32 err_mask; +- struct fman_buffer_prefix_content buffer_prefix_content; +- bool dont_release_buf; +- +- u8 rx_fd_bits; +- u32 tx_fifo_deq_pipeline_depth; +- bool errata_A006320; +- bool excessive_threshold_register; +- bool fmbm_tfne_has_features; +- +- enum fman_port_dma_swap dma_swap_data; +- enum fman_port_color color; +-}; +- +-struct fman_port_rx_pools_params { +- u8 num_of_pools; +- u16 second_largest_buf_size; +- u16 largest_buf_size; +-}; +- +-struct fman_port_dts_params { +- void __iomem *base_addr; /* FMan port virtual memory */ +- enum fman_port_type type; /* Port type */ +- u16 speed; /* Port speed */ +- u8 id; /* HW Port Id */ +- u32 qman_channel_id; /* QMan channel id (non RX only) */ +- struct fman *fman; /* FMan Handle */ +-}; +- +-struct fman_port { +- void *fm; +- struct device *dev; +- struct fman_rev_info rev_info; +- u8 port_id; +- enum fman_port_type port_type; +- u16 port_speed; +- +- union fman_port_bmi_regs __iomem *bmi_regs; +- struct fman_port_qmi_regs __iomem *qmi_regs; +- +- struct fman_sp_buffer_offsets buffer_offsets; +- +- u8 internal_buf_offset; +- struct fman_ext_pools ext_buf_pools; +- +- u16 max_frame_length; +- struct fman_port_rsrc open_dmas; +- struct fman_port_rsrc tasks; +- struct fman_port_rsrc fifo_bufs; +- struct fman_port_rx_pools_params rx_pools_params; +- +- struct fman_port_cfg *cfg; +- struct fman_port_dts_params dts_params; +- +- u8 ext_pools_num; +- u32 max_port_fifo_size; +- u32 max_num_of_ext_pools; +- u32 max_num_of_sub_portals; +- u32 bm_max_num_of_pools; +-}; +- +-static int init_bmi_rx(struct fman_port *port) +-{ +- struct fman_port_rx_bmi_regs __iomem *regs = &port->bmi_regs->rx; +- struct fman_port_cfg *cfg = port->cfg; +- u32 tmp; +- +- /* DMA attributes */ +- tmp = (u32)cfg->dma_swap_data << BMI_DMA_ATTR_SWP_SHIFT; +- /* Enable write optimization */ +- tmp |= BMI_DMA_ATTR_WRITE_OPTIMIZE; +- iowrite32be(tmp, ®s->fmbm_rda); +- +- /* Rx FIFO parameters */ +- tmp = (cfg->rx_pri_elevation / PORT_BMI_FIFO_UNITS - 1) << +- BMI_RX_FIFO_PRI_ELEVATION_SHIFT; +- tmp |= cfg->rx_fifo_thr / PORT_BMI_FIFO_UNITS - 1; +- iowrite32be(tmp, ®s->fmbm_rfp); +- +- if (cfg->excessive_threshold_register) +- /* always allow access to the extra resources */ +- iowrite32be(BMI_RX_FIFO_THRESHOLD_ETHE, ®s->fmbm_reth); +- +- /* Frame end data */ +- tmp = (cfg->cheksum_last_bytes_ignore & BMI_FRAME_END_CS_IGNORE_MASK) << +- BMI_FRAME_END_CS_IGNORE_SHIFT; +- tmp |= (cfg->rx_cut_end_bytes & BMI_RX_FRAME_END_CUT_MASK) << +- BMI_RX_FRAME_END_CUT_SHIFT; +- if (cfg->errata_A006320) +- tmp &= 0xffe0ffff; +- iowrite32be(tmp, ®s->fmbm_rfed); +- +- /* Internal context parameters */ +- tmp = ((cfg->int_context.ext_buf_offset / PORT_IC_OFFSET_UNITS) & +- BMI_IC_TO_EXT_MASK) << BMI_IC_TO_EXT_SHIFT; +- tmp |= ((cfg->int_context.int_context_offset / PORT_IC_OFFSET_UNITS) & +- BMI_IC_FROM_INT_MASK) << BMI_IC_FROM_INT_SHIFT; +- tmp |= (cfg->int_context.size / PORT_IC_OFFSET_UNITS) & +- BMI_IC_SIZE_MASK; +- iowrite32be(tmp, ®s->fmbm_ricp); +- +- /* Internal buffer offset */ +- tmp = ((cfg->int_buf_start_margin / PORT_IC_OFFSET_UNITS) & +- BMI_INT_BUF_MARG_MASK) << BMI_INT_BUF_MARG_SHIFT; +- iowrite32be(tmp, ®s->fmbm_rim); +- +- /* External buffer margins */ +- tmp = (cfg->buf_margins.start_margins & BMI_EXT_BUF_MARG_START_MASK) << +- BMI_EXT_BUF_MARG_START_SHIFT; +- tmp |= cfg->buf_margins.end_margins & BMI_EXT_BUF_MARG_END_MASK; +- iowrite32be(tmp, ®s->fmbm_rebm); +- +- /* Frame attributes */ +- tmp = BMI_CMD_RX_MR_DEF; +- tmp |= BMI_CMD_ATTR_ORDER; +- tmp |= (u32)cfg->color << BMI_CMD_ATTR_COLOR_SHIFT; +- /* Synchronization request */ +- tmp |= BMI_CMD_ATTR_SYNC; +- +- iowrite32be(tmp, ®s->fmbm_rfca); +- +- /* NIA */ +- tmp = (u32)cfg->rx_fd_bits << BMI_NEXT_ENG_FD_BITS_SHIFT; +- +- tmp |= NIA_ENG_BMI | NIA_BMI_AC_ENQ_FRAME; +- iowrite32be(tmp, ®s->fmbm_rfne); +- +- /* Enqueue NIA */ +- iowrite32be(NIA_ENG_QMI_ENQ | NIA_ORDER_RESTOR, ®s->fmbm_rfene); +- +- /* Default/error queues */ +- iowrite32be((cfg->dflt_fqid & DFLT_FQ_ID), ®s->fmbm_rfqid); +- iowrite32be((cfg->err_fqid & DFLT_FQ_ID), ®s->fmbm_refqid); +- +- /* Discard/error masks */ +- iowrite32be(cfg->discard_mask, ®s->fmbm_rfsdm); +- iowrite32be(cfg->err_mask, ®s->fmbm_rfsem); +- +- return 0; +-} +- +-static int init_bmi_tx(struct fman_port *port) +-{ +- struct fman_port_tx_bmi_regs __iomem *regs = &port->bmi_regs->tx; +- struct fman_port_cfg *cfg = port->cfg; +- u32 tmp; +- +- /* Tx Configuration register */ +- tmp = 0; +- iowrite32be(tmp, ®s->fmbm_tcfg); +- +- /* DMA attributes */ +- tmp = (u32)cfg->dma_swap_data << BMI_DMA_ATTR_SWP_SHIFT; +- iowrite32be(tmp, ®s->fmbm_tda); +- +- /* Tx FIFO parameters */ +- tmp = (cfg->tx_fifo_min_level / PORT_BMI_FIFO_UNITS) << +- BMI_TX_FIFO_MIN_FILL_SHIFT; +- tmp |= ((cfg->tx_fifo_deq_pipeline_depth - 1) & +- BMI_FIFO_PIPELINE_DEPTH_MASK) << BMI_FIFO_PIPELINE_DEPTH_SHIFT; +- tmp |= (cfg->tx_fifo_low_comf_level / PORT_BMI_FIFO_UNITS) - 1; +- iowrite32be(tmp, ®s->fmbm_tfp); +- +- /* Frame end data */ +- tmp = (cfg->cheksum_last_bytes_ignore & BMI_FRAME_END_CS_IGNORE_MASK) << +- BMI_FRAME_END_CS_IGNORE_SHIFT; +- iowrite32be(tmp, ®s->fmbm_tfed); +- +- /* Internal context parameters */ +- tmp = ((cfg->int_context.ext_buf_offset / PORT_IC_OFFSET_UNITS) & +- BMI_IC_TO_EXT_MASK) << BMI_IC_TO_EXT_SHIFT; +- tmp |= ((cfg->int_context.int_context_offset / PORT_IC_OFFSET_UNITS) & +- BMI_IC_FROM_INT_MASK) << BMI_IC_FROM_INT_SHIFT; +- tmp |= (cfg->int_context.size / PORT_IC_OFFSET_UNITS) & +- BMI_IC_SIZE_MASK; +- iowrite32be(tmp, ®s->fmbm_ticp); +- +- /* Frame attributes */ +- tmp = BMI_CMD_TX_MR_DEF; +- tmp |= BMI_CMD_ATTR_ORDER; +- tmp |= (u32)cfg->color << BMI_CMD_ATTR_COLOR_SHIFT; +- iowrite32be(tmp, ®s->fmbm_tfca); +- +- /* Dequeue NIA + enqueue NIA */ +- iowrite32be(NIA_ENG_QMI_DEQ, ®s->fmbm_tfdne); +- iowrite32be(NIA_ENG_QMI_ENQ | NIA_ORDER_RESTOR, ®s->fmbm_tfene); +- if (cfg->fmbm_tfne_has_features) +- iowrite32be(!cfg->dflt_fqid ? +- BMI_EBD_EN | NIA_BMI_AC_FETCH_ALL_FRAME : +- NIA_BMI_AC_FETCH_ALL_FRAME, ®s->fmbm_tfne); +- if (!cfg->dflt_fqid && cfg->dont_release_buf) { +- iowrite32be(DFLT_FQ_ID, ®s->fmbm_tcfqid); +- iowrite32be(NIA_ENG_BMI | NIA_BMI_AC_TX_RELEASE, +- ®s->fmbm_tfene); +- if (cfg->fmbm_tfne_has_features) +- iowrite32be(ioread32be(®s->fmbm_tfne) & ~BMI_EBD_EN, +- ®s->fmbm_tfne); +- } +- +- /* Confirmation/error queues */ +- if (cfg->dflt_fqid || !cfg->dont_release_buf) +- iowrite32be(cfg->dflt_fqid & DFLT_FQ_ID, ®s->fmbm_tcfqid); +- iowrite32be((cfg->err_fqid & DFLT_FQ_ID), ®s->fmbm_tefqid); +- +- return 0; +-} +- +-static int init_qmi(struct fman_port *port) +-{ +- struct fman_port_qmi_regs __iomem *regs = port->qmi_regs; +- struct fman_port_cfg *cfg = port->cfg; +- u32 tmp; +- +- /* Rx port configuration */ +- if (port->port_type == FMAN_PORT_TYPE_RX) { +- /* Enqueue NIA */ +- iowrite32be(NIA_ENG_BMI | NIA_BMI_AC_RELEASE, ®s->fmqm_pnen); +- return 0; +- } +- +- /* Continue with Tx port configuration */ +- if (port->port_type == FMAN_PORT_TYPE_TX) { +- /* Enqueue NIA */ +- iowrite32be(NIA_ENG_BMI | NIA_BMI_AC_TX_RELEASE, +- ®s->fmqm_pnen); +- /* Dequeue NIA */ +- iowrite32be(NIA_ENG_BMI | NIA_BMI_AC_TX, ®s->fmqm_pndn); +- } +- +- /* Dequeue Configuration register */ +- tmp = 0; +- if (cfg->deq_high_priority) +- tmp |= QMI_DEQ_CFG_PRI; +- +- switch (cfg->deq_type) { +- case FMAN_PORT_DEQ_BY_PRI: +- tmp |= QMI_DEQ_CFG_TYPE1; +- break; +- case FMAN_PORT_DEQ_ACTIVE_FQ: +- tmp |= QMI_DEQ_CFG_TYPE2; +- break; +- case FMAN_PORT_DEQ_ACTIVE_FQ_NO_ICS: +- tmp |= QMI_DEQ_CFG_TYPE3; +- break; +- default: +- return -EINVAL; +- } +- +- switch (cfg->deq_prefetch_option) { +- case FMAN_PORT_DEQ_NO_PREFETCH: +- break; +- case FMAN_PORT_DEQ_PART_PREFETCH: +- tmp |= QMI_DEQ_CFG_PREFETCH_PARTIAL; +- break; +- case FMAN_PORT_DEQ_FULL_PREFETCH: +- tmp |= QMI_DEQ_CFG_PREFETCH_FULL; +- break; +- default: +- return -EINVAL; +- } +- +- tmp |= (cfg->deq_sp & QMI_DEQ_CFG_SP_MASK) << QMI_DEQ_CFG_SP_SHIFT; +- tmp |= cfg->deq_byte_cnt; +- iowrite32be(tmp, ®s->fmqm_pndc); +- +- return 0; +-} +- +-static int init(struct fman_port *port) +-{ +- int err; +- +- /* Init BMI registers */ +- switch (port->port_type) { +- case FMAN_PORT_TYPE_RX: +- err = init_bmi_rx(port); +- break; +- case FMAN_PORT_TYPE_TX: +- err = init_bmi_tx(port); +- break; +- default: +- return -EINVAL; +- } +- +- if (err) +- return err; +- +- /* Init QMI registers */ +- err = init_qmi(port); +- return err; +- +- return 0; +-} +- +-static int set_bpools(const struct fman_port *port, +- const struct fman_port_bpools *bp) +-{ +- u32 __iomem *bp_reg, *bp_depl_reg; +- u32 tmp; +- u8 i, max_bp_num; +- bool grp_depl_used = false, rx_port; +- +- switch (port->port_type) { +- case FMAN_PORT_TYPE_RX: +- max_bp_num = port->ext_pools_num; +- rx_port = true; +- bp_reg = port->bmi_regs->rx.fmbm_ebmpi; +- bp_depl_reg = &port->bmi_regs->rx.fmbm_mpd; +- break; +- default: +- return -EINVAL; +- } +- +- if (rx_port) { +- /* Check buffers are provided in ascending order */ +- for (i = 0; (i < (bp->count - 1) && +- (i < FMAN_PORT_MAX_EXT_POOLS_NUM - 1)); i++) { +- if (bp->bpool[i].size > bp->bpool[i + 1].size) +- return -EINVAL; +- } +- } +- +- /* Set up external buffers pools */ +- for (i = 0; i < bp->count; i++) { +- tmp = BMI_EXT_BUF_POOL_VALID; +- tmp |= ((u32)bp->bpool[i].bpid << +- BMI_EXT_BUF_POOL_ID_SHIFT) & BMI_EXT_BUF_POOL_ID_MASK; +- +- if (rx_port) { +- if (bp->counters_enable) +- tmp |= BMI_EXT_BUF_POOL_EN_COUNTER; +- +- if (bp->bpool[i].is_backup) +- tmp |= BMI_EXT_BUF_POOL_BACKUP; +- +- tmp |= (u32)bp->bpool[i].size; +- } +- +- iowrite32be(tmp, &bp_reg[i]); +- } +- +- /* Clear unused pools */ +- for (i = bp->count; i < max_bp_num; i++) +- iowrite32be(0, &bp_reg[i]); +- +- /* Pools depletion */ +- tmp = 0; +- for (i = 0; i < FMAN_PORT_MAX_EXT_POOLS_NUM; i++) { +- if (bp->bpool[i].grp_bp_depleted) { +- grp_depl_used = true; +- tmp |= 0x80000000 >> i; +- } +- +- if (bp->bpool[i].single_bp_depleted) +- tmp |= 0x80 >> i; +- } +- +- if (grp_depl_used) +- tmp |= ((u32)bp->grp_bp_depleted_num - 1) << +- BMI_POOL_DEP_NUM_OF_POOLS_SHIFT; +- +- iowrite32be(tmp, bp_depl_reg); +- return 0; +-} +- +-static bool is_init_done(struct fman_port_cfg *cfg) +-{ +- /* Checks if FMan port driver parameters were initialized */ +- if (!cfg) +- return true; +- +- return false; +-} +- +-static int verify_size_of_fifo(struct fman_port *port) +-{ +- u32 min_fifo_size_required = 0, opt_fifo_size_for_b2b = 0; +- +- /* TX Ports */ +- if (port->port_type == FMAN_PORT_TYPE_TX) { +- min_fifo_size_required = (u32) +- (roundup(port->max_frame_length, +- FMAN_BMI_FIFO_UNITS) + (3 * FMAN_BMI_FIFO_UNITS)); +- +- min_fifo_size_required += +- port->cfg->tx_fifo_deq_pipeline_depth * +- FMAN_BMI_FIFO_UNITS; +- +- opt_fifo_size_for_b2b = min_fifo_size_required; +- +- /* Add some margin for back-to-back capability to improve +- * performance, allows the hardware to pipeline new frame dma +- * while the previous frame not yet transmitted. +- */ +- if (port->port_speed == 10000) +- opt_fifo_size_for_b2b += 3 * FMAN_BMI_FIFO_UNITS; +- else +- opt_fifo_size_for_b2b += 2 * FMAN_BMI_FIFO_UNITS; +- } +- +- /* RX Ports */ +- else if (port->port_type == FMAN_PORT_TYPE_RX) { +- if (port->rev_info.major >= 6) +- min_fifo_size_required = (u32) +- (roundup(port->max_frame_length, +- FMAN_BMI_FIFO_UNITS) + +- (5 * FMAN_BMI_FIFO_UNITS)); +- /* 4 according to spec + 1 for FOF>0 */ +- else +- min_fifo_size_required = (u32) +- (roundup(min(port->max_frame_length, +- port->rx_pools_params.largest_buf_size), +- FMAN_BMI_FIFO_UNITS) + +- (7 * FMAN_BMI_FIFO_UNITS)); +- +- opt_fifo_size_for_b2b = min_fifo_size_required; +- +- /* Add some margin for back-to-back capability to improve +- * performance,allows the hardware to pipeline new frame dma +- * while the previous frame not yet transmitted. +- */ +- if (port->port_speed == 10000) +- opt_fifo_size_for_b2b += 8 * FMAN_BMI_FIFO_UNITS; +- else +- opt_fifo_size_for_b2b += 3 * FMAN_BMI_FIFO_UNITS; +- } +- +- WARN_ON(min_fifo_size_required <= 0); +- WARN_ON(opt_fifo_size_for_b2b < min_fifo_size_required); +- +- /* Verify the size */ +- if (port->fifo_bufs.num < min_fifo_size_required) +- dev_dbg(port->dev, "%s: FIFO size should be enlarged to %d bytes\n", +- __func__, min_fifo_size_required); +- else if (port->fifo_bufs.num < opt_fifo_size_for_b2b) +- dev_dbg(port->dev, "%s: For b2b processing,FIFO may be enlarged to %d bytes\n", +- __func__, opt_fifo_size_for_b2b); +- +- return 0; +-} +- +-static int set_ext_buffer_pools(struct fman_port *port) +-{ +- struct fman_ext_pools *ext_buf_pools = &port->cfg->ext_buf_pools; +- struct fman_buf_pool_depletion *buf_pool_depletion = +- &port->cfg->buf_pool_depletion; +- u8 ordered_array[FMAN_PORT_MAX_EXT_POOLS_NUM]; +- u16 sizes_array[BM_MAX_NUM_OF_POOLS]; +- int i = 0, j = 0, err; +- struct fman_port_bpools bpools; +- +- memset(&ordered_array, 0, sizeof(u8) * FMAN_PORT_MAX_EXT_POOLS_NUM); +- memset(&sizes_array, 0, sizeof(u16) * BM_MAX_NUM_OF_POOLS); +- memcpy(&port->ext_buf_pools, ext_buf_pools, +- sizeof(struct fman_ext_pools)); +- +- fman_sp_set_buf_pools_in_asc_order_of_buf_sizes(ext_buf_pools, +- ordered_array, +- sizes_array); +- +- memset(&bpools, 0, sizeof(struct fman_port_bpools)); +- bpools.count = ext_buf_pools->num_of_pools_used; +- bpools.counters_enable = true; +- for (i = 0; i < ext_buf_pools->num_of_pools_used; i++) { +- bpools.bpool[i].bpid = ordered_array[i]; +- bpools.bpool[i].size = sizes_array[ordered_array[i]]; +- } +- +- /* save pools parameters for later use */ +- port->rx_pools_params.num_of_pools = ext_buf_pools->num_of_pools_used; +- port->rx_pools_params.largest_buf_size = +- sizes_array[ordered_array[ext_buf_pools->num_of_pools_used - 1]]; +- port->rx_pools_params.second_largest_buf_size = +- sizes_array[ordered_array[ext_buf_pools->num_of_pools_used - 2]]; +- +- /* FMBM_RMPD reg. - pool depletion */ +- if (buf_pool_depletion->pools_grp_mode_enable) { +- bpools.grp_bp_depleted_num = buf_pool_depletion->num_of_pools; +- for (i = 0; i < port->bm_max_num_of_pools; i++) { +- if (buf_pool_depletion->pools_to_consider[i]) { +- for (j = 0; j < ext_buf_pools-> +- num_of_pools_used; j++) { +- if (i == ordered_array[j]) { +- bpools.bpool[j]. +- grp_bp_depleted = true; +- break; +- } +- } +- } +- } +- } +- +- if (buf_pool_depletion->single_pool_mode_enable) { +- for (i = 0; i < port->bm_max_num_of_pools; i++) { +- if (buf_pool_depletion-> +- pools_to_consider_for_single_mode[i]) { +- for (j = 0; j < ext_buf_pools-> +- num_of_pools_used; j++) { +- if (i == ordered_array[j]) { +- bpools.bpool[j]. +- single_bp_depleted = true; +- break; +- } +- } +- } +- } +- } +- +- err = set_bpools(port, &bpools); +- if (err != 0) { +- dev_err(port->dev, "%s: set_bpools() failed\n", __func__); +- return -EINVAL; +- } +- +- return 0; +-} +- +-static int init_low_level_driver(struct fman_port *port) +-{ +- struct fman_port_cfg *cfg = port->cfg; +- u32 tmp_val; +- +- switch (port->port_type) { +- case FMAN_PORT_TYPE_RX: +- cfg->err_mask = (RX_ERRS_TO_ENQ & ~cfg->discard_mask); +- break; +- default: +- break; +- } +- +- tmp_val = (u32)((port->internal_buf_offset % OFFSET_UNITS) ? +- (port->internal_buf_offset / OFFSET_UNITS + 1) : +- (port->internal_buf_offset / OFFSET_UNITS)); +- port->internal_buf_offset = (u8)(tmp_val * OFFSET_UNITS); +- port->cfg->int_buf_start_margin = port->internal_buf_offset; +- +- if (init(port) != 0) { +- dev_err(port->dev, "%s: fman port initialization failed\n", +- __func__); +- return -ENODEV; +- } +- +- /* The code bellow is a trick so the FM will not release the buffer +- * to BM nor will try to enqueue the frame to QM +- */ +- if (port->port_type == FMAN_PORT_TYPE_TX) { +- if (!cfg->dflt_fqid && cfg->dont_release_buf) { +- /* override fmbm_tcfqid 0 with a false non-0 value. +- * This will force FM to act according to tfene. +- * Otherwise, if fmbm_tcfqid is 0 the FM will release +- * buffers to BM regardless of fmbm_tfene +- */ +- iowrite32be(0xFFFFFF, &port->bmi_regs->tx.fmbm_tcfqid); +- iowrite32be(NIA_ENG_BMI | NIA_BMI_AC_TX_RELEASE, +- &port->bmi_regs->tx.fmbm_tfene); +- } +- } +- +- return 0; +-} +- +-static int fill_soc_specific_params(struct fman_port *port) +-{ +- u32 bmi_max_fifo_size; +- +- bmi_max_fifo_size = fman_get_bmi_max_fifo_size(port->fm); +- port->max_port_fifo_size = MAX_PORT_FIFO_SIZE(bmi_max_fifo_size); +- port->bm_max_num_of_pools = 64; +- +- /* P4080 - Major 2 +- * P2041/P3041/P5020/P5040 - Major 3 +- * Tx/Bx - Major 6 +- */ +- switch (port->rev_info.major) { +- case 2: +- case 3: +- port->max_num_of_ext_pools = 4; +- port->max_num_of_sub_portals = 12; +- break; +- +- case 6: +- port->max_num_of_ext_pools = 8; +- port->max_num_of_sub_portals = 16; +- break; +- +- default: +- dev_err(port->dev, "%s: Unsupported FMan version\n", __func__); +- return -EINVAL; +- } +- +- return 0; +-} +- +-static int get_dflt_fifo_deq_pipeline_depth(u8 major, enum fman_port_type type, +- u16 speed) +-{ +- switch (type) { +- case FMAN_PORT_TYPE_RX: +- case FMAN_PORT_TYPE_TX: +- switch (speed) { +- case 10000: +- return 4; +- case 1000: +- if (major >= 6) +- return 2; +- else +- return 1; +- default: +- return 0; +- } +- default: +- return 0; +- } +-} +- +-static int get_dflt_num_of_tasks(u8 major, enum fman_port_type type, +- u16 speed) +-{ +- switch (type) { +- case FMAN_PORT_TYPE_RX: +- case FMAN_PORT_TYPE_TX: +- switch (speed) { +- case 10000: +- return 16; +- case 1000: +- if (major >= 6) +- return 4; +- else +- return 3; +- default: +- return 0; +- } +- default: +- return 0; +- } +-} +- +-static int get_dflt_extra_num_of_tasks(u8 major, enum fman_port_type type, +- u16 speed) +-{ +- switch (type) { +- case FMAN_PORT_TYPE_RX: +- /* FMan V3 */ +- if (major >= 6) +- return 0; +- +- /* FMan V2 */ +- if (speed == 10000) +- return 8; +- else +- return 2; +- case FMAN_PORT_TYPE_TX: +- default: +- return 0; +- } +-} +- +-static int get_dflt_num_of_open_dmas(u8 major, enum fman_port_type type, +- u16 speed) +-{ +- int val; +- +- if (major >= 6) { +- switch (type) { +- case FMAN_PORT_TYPE_TX: +- if (speed == 10000) +- val = 12; +- else +- val = 3; +- break; +- case FMAN_PORT_TYPE_RX: +- if (speed == 10000) +- val = 8; +- else +- val = 2; +- break; +- default: +- return 0; +- } +- } else { +- switch (type) { +- case FMAN_PORT_TYPE_TX: +- case FMAN_PORT_TYPE_RX: +- if (speed == 10000) +- val = 8; +- else +- val = 1; +- break; +- default: +- val = 0; +- } +- } +- +- return val; +-} +- +-static int get_dflt_extra_num_of_open_dmas(u8 major, enum fman_port_type type, +- u16 speed) +-{ +- /* FMan V3 */ +- if (major >= 6) +- return 0; +- +- /* FMan V2 */ +- switch (type) { +- case FMAN_PORT_TYPE_RX: +- case FMAN_PORT_TYPE_TX: +- if (speed == 10000) +- return 8; +- else +- return 1; +- default: +- return 0; +- } +-} +- +-static int get_dflt_num_of_fifo_bufs(u8 major, enum fman_port_type type, +- u16 speed) +-{ +- int val; +- +- if (major >= 6) { +- switch (type) { +- case FMAN_PORT_TYPE_TX: +- if (speed == 10000) +- val = 64; +- else +- val = 50; +- break; +- case FMAN_PORT_TYPE_RX: +- if (speed == 10000) +- val = 96; +- else +- val = 50; +- break; +- default: +- val = 0; +- } +- } else { +- switch (type) { +- case FMAN_PORT_TYPE_TX: +- if (speed == 10000) +- val = 48; +- else +- val = 44; +- break; +- case FMAN_PORT_TYPE_RX: +- if (speed == 10000) +- val = 48; +- else +- val = 45; +- break; +- default: +- val = 0; +- } +- } +- +- return val; +-} +- +-static void set_dflt_cfg(struct fman_port *port, +- struct fman_port_params *port_params) +-{ +- struct fman_port_cfg *cfg = port->cfg; +- +- cfg->dma_swap_data = FMAN_PORT_DMA_NO_SWAP; +- cfg->color = FMAN_PORT_COLOR_GREEN; +- cfg->rx_cut_end_bytes = DFLT_PORT_CUT_BYTES_FROM_END; +- cfg->rx_pri_elevation = BMI_PRIORITY_ELEVATION_LEVEL; +- cfg->rx_fifo_thr = BMI_FIFO_THRESHOLD; +- cfg->tx_fifo_low_comf_level = (5 * 1024); +- cfg->deq_type = FMAN_PORT_DEQ_BY_PRI; +- cfg->deq_prefetch_option = FMAN_PORT_DEQ_FULL_PREFETCH; +- cfg->tx_fifo_deq_pipeline_depth = +- BMI_DEQUEUE_PIPELINE_DEPTH(port->port_type, port->port_speed); +- cfg->deq_byte_cnt = QMI_BYTE_COUNT_LEVEL_CONTROL(port->port_type); +- +- cfg->rx_pri_elevation = +- DFLT_PORT_RX_FIFO_PRI_ELEVATION_LEV(port->max_port_fifo_size); +- port->cfg->rx_fifo_thr = +- DFLT_PORT_RX_FIFO_THRESHOLD(port->rev_info.major, +- port->max_port_fifo_size); +- +- if ((port->rev_info.major == 6) && +- ((port->rev_info.minor == 0) || (port->rev_info.minor == 3))) +- cfg->errata_A006320 = true; +- +- /* Excessive Threshold register - exists for pre-FMv3 chips only */ +- if (port->rev_info.major < 6) +- cfg->excessive_threshold_register = true; +- else +- cfg->fmbm_tfne_has_features = true; +- +- cfg->buffer_prefix_content.data_align = +- DFLT_PORT_BUFFER_PREFIX_CONTEXT_DATA_ALIGN; +-} +- +-static void set_rx_dflt_cfg(struct fman_port *port, +- struct fman_port_params *port_params) +-{ +- port->cfg->discard_mask = DFLT_PORT_ERRORS_TO_DISCARD; +- +- memcpy(&port->cfg->ext_buf_pools, +- &port_params->specific_params.rx_params.ext_buf_pools, +- sizeof(struct fman_ext_pools)); +- port->cfg->err_fqid = +- port_params->specific_params.rx_params.err_fqid; +- port->cfg->dflt_fqid = +- port_params->specific_params.rx_params.dflt_fqid; +-} +- +-static void set_tx_dflt_cfg(struct fman_port *port, +- struct fman_port_params *port_params, +- struct fman_port_dts_params *dts_params) +-{ +- port->cfg->tx_fifo_deq_pipeline_depth = +- get_dflt_fifo_deq_pipeline_depth(port->rev_info.major, +- port->port_type, +- port->port_speed); +- port->cfg->err_fqid = +- port_params->specific_params.non_rx_params.err_fqid; +- port->cfg->deq_sp = +- (u8)(dts_params->qman_channel_id & QMI_DEQ_CFG_SUBPORTAL_MASK); +- port->cfg->dflt_fqid = +- port_params->specific_params.non_rx_params.dflt_fqid; +- port->cfg->deq_high_priority = true; +-} +- +-/** +- * fman_port_config +- * @port: Pointer to the port structure +- * @params: Pointer to data structure of parameters +- * +- * Creates a descriptor for the FM PORT module. +- * The routine returns a pointer to the FM PORT object. +- * This descriptor must be passed as first parameter to all other FM PORT +- * function calls. +- * No actual initialization or configuration of FM hardware is done by this +- * routine. +- * +- * Return: 0 on success; Error code otherwise. +- */ +-int fman_port_config(struct fman_port *port, struct fman_port_params *params) +-{ +- void __iomem *base_addr = port->dts_params.base_addr; +- int err; +- +- /* Allocate the FM driver's parameters structure */ +- port->cfg = kzalloc(sizeof(*port->cfg), GFP_KERNEL); +- if (!port->cfg) +- goto err_params; +- +- /* Initialize FM port parameters which will be kept by the driver */ +- port->port_type = port->dts_params.type; +- port->port_speed = port->dts_params.speed; +- port->port_id = port->dts_params.id; +- port->fm = port->dts_params.fman; +- port->ext_pools_num = (u8)8; +- +- /* get FM revision */ +- fman_get_revision(port->fm, &port->rev_info); +- +- err = fill_soc_specific_params(port); +- if (err) +- goto err_port_cfg; +- +- switch (port->port_type) { +- case FMAN_PORT_TYPE_RX: +- set_rx_dflt_cfg(port, params); +- case FMAN_PORT_TYPE_TX: +- set_tx_dflt_cfg(port, params, &port->dts_params); +- default: +- set_dflt_cfg(port, params); +- } +- +- /* Continue with other parameters */ +- /* set memory map pointers */ +- port->bmi_regs = base_addr + BMI_PORT_REGS_OFFSET; +- port->qmi_regs = base_addr + QMI_PORT_REGS_OFFSET; +- +- port->max_frame_length = DFLT_PORT_MAX_FRAME_LENGTH; +- /* resource distribution. */ +- +- port->fifo_bufs.num = +- get_dflt_num_of_fifo_bufs(port->rev_info.major, port->port_type, +- port->port_speed) * FMAN_BMI_FIFO_UNITS; +- port->fifo_bufs.extra = +- DFLT_PORT_EXTRA_NUM_OF_FIFO_BUFS * FMAN_BMI_FIFO_UNITS; +- +- port->open_dmas.num = +- get_dflt_num_of_open_dmas(port->rev_info.major, +- port->port_type, port->port_speed); +- port->open_dmas.extra = +- get_dflt_extra_num_of_open_dmas(port->rev_info.major, +- port->port_type, port->port_speed); +- port->tasks.num = +- get_dflt_num_of_tasks(port->rev_info.major, +- port->port_type, port->port_speed); +- port->tasks.extra = +- get_dflt_extra_num_of_tasks(port->rev_info.major, +- port->port_type, port->port_speed); +- +- /* FM_HEAVY_TRAFFIC_SEQUENCER_HANG_ERRATA_FMAN_A006981 errata +- * workaround +- */ +- if ((port->rev_info.major == 6) && (port->rev_info.minor == 0) && +- (((port->port_type == FMAN_PORT_TYPE_TX) && +- (port->port_speed == 1000)))) { +- port->open_dmas.num = 16; +- port->open_dmas.extra = 0; +- } +- +- if (port->rev_info.major >= 6 && +- port->port_type == FMAN_PORT_TYPE_TX && +- port->port_speed == 1000) { +- /* FM_WRONG_RESET_VALUES_ERRATA_FMAN_A005127 Errata +- * workaround +- */ +- if (port->rev_info.major >= 6) { +- u32 reg; +- +- reg = 0x00001013; +- iowrite32be(reg, &port->bmi_regs->tx.fmbm_tfp); +- } +- } +- +- return 0; +- +-err_port_cfg: +- kfree(port->cfg); +-err_params: +- kfree(port); +- return -EINVAL; +-} +-EXPORT_SYMBOL(fman_port_config); +- +-/** +- * fman_port_init +- * port: A pointer to a FM Port module. +- * Initializes the FM PORT module by defining the software structure and +- * configuring the hardware registers. +- * +- * Return: 0 on success; Error code otherwise. +- */ +-int fman_port_init(struct fman_port *port) +-{ +- struct fman_port_cfg *cfg; +- int err; +- struct fman_port_init_params params; +- +- if (is_init_done(port->cfg)) +- return -EINVAL; +- +- err = fman_sp_build_buffer_struct(&port->cfg->int_context, +- &port->cfg->buffer_prefix_content, +- &port->cfg->buf_margins, +- &port->buffer_offsets, +- &port->internal_buf_offset); +- if (err) +- return err; +- +- cfg = port->cfg; +- +- if (port->port_type == FMAN_PORT_TYPE_RX) { +- /* Call the external Buffer routine which also checks fifo +- * size and updates it if necessary +- */ +- /* define external buffer pools and pool depletion */ +- err = set_ext_buffer_pools(port); +- if (err) +- return err; +- /* check if the largest external buffer pool is large enough */ +- if (cfg->buf_margins.start_margins + MIN_EXT_BUF_SIZE + +- cfg->buf_margins.end_margins > +- port->rx_pools_params.largest_buf_size) { +- dev_err(port->dev, "%s: buf_margins.start_margins (%d) + minimum buf size (64) + buf_margins.end_margins (%d) is larger than maximum external buffer size (%d)\n", +- __func__, cfg->buf_margins.start_margins, +- cfg->buf_margins.end_margins, +- port->rx_pools_params.largest_buf_size); +- return -EINVAL; +- } +- } +- +- /* Call FM module routine for communicating parameters */ +- memset(¶ms, 0, sizeof(params)); +- params.port_id = port->port_id; +- params.port_type = port->port_type; +- params.port_speed = port->port_speed; +- params.num_of_tasks = (u8)port->tasks.num; +- params.num_of_extra_tasks = (u8)port->tasks.extra; +- params.num_of_open_dmas = (u8)port->open_dmas.num; +- params.num_of_extra_open_dmas = (u8)port->open_dmas.extra; +- +- if (port->fifo_bufs.num) { +- err = verify_size_of_fifo(port); +- if (err) +- return err; +- } +- params.size_of_fifo = port->fifo_bufs.num; +- params.extra_size_of_fifo = port->fifo_bufs.extra; +- params.deq_pipeline_depth = port->cfg->tx_fifo_deq_pipeline_depth; +- params.max_frame_length = port->max_frame_length; +- +- err = fman_set_port_params(port->fm, ¶ms); +- if (err) +- return err; +- +- err = init_low_level_driver(port); +- if (err) +- return err; +- +- kfree(port->cfg); +- port->cfg = NULL; +- +- return 0; +-} +-EXPORT_SYMBOL(fman_port_init); +- +-/** +- * fman_port_cfg_buf_prefix_content +- * @port A pointer to a FM Port module. +- * @buffer_prefix_content A structure of parameters describing +- * the structure of the buffer. +- * Out parameter: +- * Start margin - offset of data from +- * start of external buffer. +- * Defines the structure, size and content of the application buffer. +- * The prefix, in Tx ports, if 'pass_prs_result', the application should set +- * a value to their offsets in the prefix of the FM will save the first +- * 'priv_data_size', than, depending on 'pass_prs_result' and +- * 'pass_time_stamp', copy parse result and timeStamp, and the packet itself +- * (in this order), to the application buffer, and to offset. +- * Calling this routine changes the buffer margins definitions in the internal +- * driver data base from its default configuration: +- * Data size: [DEFAULT_PORT_BUFFER_PREFIX_CONTENT_PRIV_DATA_SIZE] +- * Pass Parser result: [DEFAULT_PORT_BUFFER_PREFIX_CONTENT_PASS_PRS_RESULT]. +- * Pass timestamp: [DEFAULT_PORT_BUFFER_PREFIX_CONTENT_PASS_TIME_STAMP]. +- * May be used for all ports +- * +- * Allowed only following fman_port_config() and before fman_port_init(). +- * +- * Return: 0 on success; Error code otherwise. +- */ +-int fman_port_cfg_buf_prefix_content(struct fman_port *port, +- struct fman_buffer_prefix_content * +- buffer_prefix_content) +-{ +- if (is_init_done(port->cfg)) +- return -EINVAL; +- +- memcpy(&port->cfg->buffer_prefix_content, +- buffer_prefix_content, +- sizeof(struct fman_buffer_prefix_content)); +- /* if data_align was not initialized by user, +- * we return to driver's default +- */ +- if (!port->cfg->buffer_prefix_content.data_align) +- port->cfg->buffer_prefix_content.data_align = +- DFLT_PORT_BUFFER_PREFIX_CONTEXT_DATA_ALIGN; +- +- return 0; +-} +-EXPORT_SYMBOL(fman_port_cfg_buf_prefix_content); +- +-/** +- * fman_port_disable +- * port: A pointer to a FM Port module. +- * +- * Gracefully disable an FM port. The port will not start new tasks after all +- * tasks associated with the port are terminated. +- * +- * This is a blocking routine, it returns after port is gracefully stopped, +- * i.e. the port will not except new frames, but it will finish all frames +- * or tasks which were already began. +- * Allowed only following fman_port_init(). +- * +- * Return: 0 on success; Error code otherwise. +- */ +-int fman_port_disable(struct fman_port *port) +-{ +- u32 __iomem *bmi_cfg_reg, *bmi_status_reg; +- u32 tmp; +- bool rx_port, failure = false; +- int count; +- +- if (!is_init_done(port->cfg)) +- return -EINVAL; +- +- switch (port->port_type) { +- case FMAN_PORT_TYPE_RX: +- bmi_cfg_reg = &port->bmi_regs->rx.fmbm_rcfg; +- bmi_status_reg = &port->bmi_regs->rx.fmbm_rst; +- rx_port = true; +- break; +- case FMAN_PORT_TYPE_TX: +- bmi_cfg_reg = &port->bmi_regs->tx.fmbm_tcfg; +- bmi_status_reg = &port->bmi_regs->tx.fmbm_tst; +- rx_port = false; +- break; +- default: +- return -EINVAL; +- } +- +- /* Disable QMI */ +- if (!rx_port) { +- tmp = ioread32be(&port->qmi_regs->fmqm_pnc) & ~QMI_PORT_CFG_EN; +- iowrite32be(tmp, &port->qmi_regs->fmqm_pnc); +- +- /* Wait for QMI to finish FD handling */ +- count = 100; +- do { +- udelay(10); +- tmp = ioread32be(&port->qmi_regs->fmqm_pns); +- } while ((tmp & QMI_PORT_STATUS_DEQ_FD_BSY) && --count); +- +- if (count == 0) { +- /* Timeout */ +- failure = true; +- } +- } +- +- /* Disable BMI */ +- tmp = ioread32be(bmi_cfg_reg) & ~BMI_PORT_CFG_EN; +- iowrite32be(tmp, bmi_cfg_reg); +- +- /* Wait for graceful stop end */ +- count = 500; +- do { +- udelay(10); +- tmp = ioread32be(bmi_status_reg); +- } while ((tmp & BMI_PORT_STATUS_BSY) && --count); +- +- if (count == 0) { +- /* Timeout */ +- failure = true; +- } +- +- if (failure) +- dev_dbg(port->dev, "%s: FMan Port[%d]: BMI or QMI is Busy. Port forced down\n", +- __func__, port->port_id); +- +- return 0; +-} +-EXPORT_SYMBOL(fman_port_disable); +- +-/** +- * fman_port_enable +- * port: A pointer to a FM Port module. +- * +- * A runtime routine provided to allow disable/enable of port. +- * +- * Allowed only following fman_port_init(). +- * +- * Return: 0 on success; Error code otherwise. +- */ +-int fman_port_enable(struct fman_port *port) +-{ +- u32 __iomem *bmi_cfg_reg; +- u32 tmp; +- bool rx_port; +- +- if (!is_init_done(port->cfg)) +- return -EINVAL; +- +- switch (port->port_type) { +- case FMAN_PORT_TYPE_RX: +- bmi_cfg_reg = &port->bmi_regs->rx.fmbm_rcfg; +- rx_port = true; +- break; +- case FMAN_PORT_TYPE_TX: +- bmi_cfg_reg = &port->bmi_regs->tx.fmbm_tcfg; +- rx_port = false; +- break; +- default: +- return -EINVAL; +- } +- +- /* Enable QMI */ +- if (!rx_port) { +- tmp = ioread32be(&port->qmi_regs->fmqm_pnc) | QMI_PORT_CFG_EN; +- iowrite32be(tmp, &port->qmi_regs->fmqm_pnc); +- } +- +- /* Enable BMI */ +- tmp = ioread32be(bmi_cfg_reg) | BMI_PORT_CFG_EN; +- iowrite32be(tmp, bmi_cfg_reg); +- +- return 0; +-} +-EXPORT_SYMBOL(fman_port_enable); +- +-/** +- * fman_port_bind +- * dev: FMan Port OF device pointer +- * +- * Bind to a specific FMan Port. +- * +- * Allowed only after the port was created. +- * +- * Return: A pointer to the FMan port device. +- */ +-struct fman_port *fman_port_bind(struct device *dev) +-{ +- return (struct fman_port *)(dev_get_drvdata(get_device(dev))); +-} +-EXPORT_SYMBOL(fman_port_bind); +- +-/** +- * fman_port_get_qman_channel_id +- * port: Pointer to the FMan port devuce +- * +- * Get the QMan channel ID for the specific port +- * +- * Return: QMan channel ID +- */ +-u32 fman_port_get_qman_channel_id(struct fman_port *port) +-{ +- return port->dts_params.qman_channel_id; +-} +-EXPORT_SYMBOL(fman_port_get_qman_channel_id); +- +-static int fman_port_probe(struct platform_device *of_dev) +-{ +- struct fman_port *port; +- struct fman *fman; +- struct device_node *fm_node, *port_node; +- struct resource res; +- struct resource *dev_res; +- u32 val; +- int err = 0, lenp; +- enum fman_port_type port_type; +- u16 port_speed; +- u8 port_id; +- +- port = kzalloc(sizeof(*port), GFP_KERNEL); +- if (!port) +- return -ENOMEM; +- +- port->dev = &of_dev->dev; +- +- port_node = of_node_get(of_dev->dev.of_node); +- +- /* Get the FM node */ +- fm_node = of_get_parent(port_node); +- if (!fm_node) { +- dev_err(port->dev, "%s: of_get_parent() failed\n", __func__); +- err = -ENODEV; +- goto return_err; +- } +- +- fman = dev_get_drvdata(&of_find_device_by_node(fm_node)->dev); +- of_node_put(fm_node); +- if (!fman) { +- err = -EINVAL; +- goto return_err; +- } +- +- err = of_property_read_u32(port_node, "cell-index", &val); +- if (err) { +- dev_err(port->dev, "%s: reading cell-index for %s failed\n", +- __func__, port_node->full_name); +- err = -EINVAL; +- goto return_err; +- } +- port_id = (u8)val; +- port->dts_params.id = port_id; +- +- if (of_device_is_compatible(port_node, "fsl,fman-v3-port-tx")) { +- port_type = FMAN_PORT_TYPE_TX; +- port_speed = 1000; +- if (of_find_property(port_node, "fsl,fman-10g-port", &lenp)) +- port_speed = 10000; +- +- } else if (of_device_is_compatible(port_node, "fsl,fman-v2-port-tx")) { +- if (port_id >= TX_10G_PORT_BASE) +- port_speed = 10000; +- else +- port_speed = 1000; +- port_type = FMAN_PORT_TYPE_TX; +- +- } else if (of_device_is_compatible(port_node, "fsl,fman-v3-port-rx")) { +- port_type = FMAN_PORT_TYPE_RX; +- port_speed = 1000; +- if (of_find_property(port_node, "fsl,fman-10g-port", &lenp)) +- port_speed = 10000; +- +- } else if (of_device_is_compatible(port_node, "fsl,fman-v2-port-rx")) { +- if (port_id >= RX_10G_PORT_BASE) +- port_speed = 10000; +- else +- port_speed = 1000; +- port_type = FMAN_PORT_TYPE_RX; +- +- } else { +- dev_err(port->dev, "%s: Illegal port type\n", __func__); +- err = -EINVAL; +- goto return_err; +- } +- +- port->dts_params.type = port_type; +- port->dts_params.speed = port_speed; +- +- if (port_type == FMAN_PORT_TYPE_TX) { +- u32 qman_channel_id; +- +- qman_channel_id = fman_get_qman_channel_id(fman, port_id); +- if (qman_channel_id == 0) { +- dev_err(port->dev, "%s: incorrect qman-channel-id\n", +- __func__); +- err = -EINVAL; +- goto return_err; +- } +- port->dts_params.qman_channel_id = qman_channel_id; +- } +- +- err = of_address_to_resource(port_node, 0, &res); +- if (err < 0) { +- dev_err(port->dev, "%s: of_address_to_resource() failed\n", +- __func__); +- err = -ENOMEM; +- goto return_err; +- } +- +- port->dts_params.fman = fman; +- +- of_node_put(port_node); +- +- dev_res = __devm_request_region(port->dev, &res, res.start, +- resource_size(&res), "fman-port"); +- if (!dev_res) { +- dev_err(port->dev, "%s: __devm_request_region() failed\n", +- __func__); +- err = -EINVAL; +- goto free_port; +- } +- +- port->dts_params.base_addr = devm_ioremap(port->dev, res.start, +- resource_size(&res)); +- if (!port->dts_params.base_addr) +- dev_err(port->dev, "%s: devm_ioremap() failed\n", __func__); +- +- dev_set_drvdata(&of_dev->dev, port); +- +- return 0; +- +-return_err: +- of_node_put(port_node); +-free_port: +- kfree(port); +- return err; +-} +- +-static const struct of_device_id fman_port_match[] = { +- {.compatible = "fsl,fman-v3-port-rx"}, +- {.compatible = "fsl,fman-v2-port-rx"}, +- {.compatible = "fsl,fman-v3-port-tx"}, +- {.compatible = "fsl,fman-v2-port-tx"}, +- {} +-}; +- +-MODULE_DEVICE_TABLE(of, fman_port_match); +- +-static struct platform_driver fman_port_driver = { +- .driver = { +- .name = "fsl-fman-port", +- .of_match_table = fman_port_match, +- }, +- .probe = fman_port_probe, +-}; +- +-static int __init fman_port_load(void) +-{ +- int err; +- +- pr_debug("FSL DPAA FMan driver\n"); +- +- err = platform_driver_register(&fman_port_driver); +- if (err < 0) +- pr_err("Error, platform_driver_register() = %d\n", err); +- +- return err; +-} +-module_init(fman_port_load); +- +-static void __exit fman_port_unload(void) +-{ +- platform_driver_unregister(&fman_port_driver); +-} +-module_exit(fman_port_unload); +- +-MODULE_LICENSE("Dual BSD/GPL"); +-MODULE_DESCRIPTION("Freescale DPAA Frame Manager Port driver"); +diff --git a/drivers/net/ethernet/freescale/fman/fman_port.h b/drivers/net/ethernet/freescale/fman/fman_port.h +deleted file mode 100644 +index 8ba9017..0000000 +--- a/drivers/net/ethernet/freescale/fman/fman_port.h ++++ /dev/null +@@ -1,151 +0,0 @@ +-/* +- * Copyright 2008 - 2015 Freescale Semiconductor Inc. +- * +- * Redistribution and use in source and binary forms, with or without +- * modification, are permitted provided that the following conditions are met: +- * * Redistributions of source code must retain the above copyright +- * notice, this list of conditions and the following disclaimer. +- * * Redistributions in binary form must reproduce the above copyright +- * notice, this list of conditions and the following disclaimer in the +- * documentation and/or other materials provided with the distribution. +- * * Neither the name of Freescale Semiconductor nor the +- * names of its contributors may be used to endorse or promote products +- * derived from this software without specific prior written permission. +- * +- * +- * ALTERNATIVELY, this software may be distributed under the terms of the +- * GNU General Public License ("GPL") as published by the Free Software +- * Foundation, either version 2 of that License or (at your option) any +- * later version. +- * +- * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY +- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +- * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY +- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +- */ +- +-#ifndef __FMAN_PORT_H +-#define __FMAN_PORT_H +- +-#include "fman.h" +- +-/* FM Port API +- * The FM uses a general module called "port" to represent a Tx port (MAC), +- * an Rx port (MAC). +- * The number of ports in an FM varies between SOCs. +- * The SW driver manages these ports as sub-modules of the FM,i.e. after an +- * FM is initialized, its ports may be initialized and operated upon. +- * The port is initialized aware of its type, but other functions on a port +- * may be indifferent to its type. When necessary, the driver verifies +- * coherence and returns error if applicable. +- * On initialization, user specifies the port type and it's index (relative +- * to the port's type) - always starting at 0. +- */ +- +-/* FM Frame error */ +-/* Frame Descriptor errors */ +-/* Not for Rx-Port! Unsupported Format */ +-#define FM_PORT_FRM_ERR_UNSUPPORTED_FORMAT FM_FD_ERR_UNSUPPORTED_FORMAT +-/* Not for Rx-Port! Length Error */ +-#define FM_PORT_FRM_ERR_LENGTH FM_FD_ERR_LENGTH +-/* DMA Data error */ +-#define FM_PORT_FRM_ERR_DMA FM_FD_ERR_DMA +-/* non Frame-Manager error; probably come from SEC that was chained to FM */ +-#define FM_PORT_FRM_ERR_NON_FM FM_FD_RX_STATUS_ERR_NON_FM +- /* IPR error */ +-#define FM_PORT_FRM_ERR_IPRE (FM_FD_ERR_IPR & ~FM_FD_IPR) +-/* IPR non-consistent-sp */ +-#define FM_PORT_FRM_ERR_IPR_NCSP (FM_FD_ERR_IPR_NCSP & \ +- ~FM_FD_IPR) +- +-/* Rx FIFO overflow, FCS error, code error, running disparity +- * error (SGMII and TBI modes), FIFO parity error. +- * PHY Sequence error, PHY error control character detected. +- */ +-#define FM_PORT_FRM_ERR_PHYSICAL FM_FD_ERR_PHYSICAL +-/* Frame too long OR Frame size exceeds max_length_frame */ +-#define FM_PORT_FRM_ERR_SIZE FM_FD_ERR_SIZE +-/* indicates a classifier "drop" operation */ +-#define FM_PORT_FRM_ERR_CLS_DISCARD FM_FD_ERR_CLS_DISCARD +-/* Extract Out of Frame */ +-#define FM_PORT_FRM_ERR_EXTRACTION FM_FD_ERR_EXTRACTION +-/* No Scheme Selected */ +-#define FM_PORT_FRM_ERR_NO_SCHEME FM_FD_ERR_NO_SCHEME +-/* Keysize Overflow */ +-#define FM_PORT_FRM_ERR_KEYSIZE_OVERFLOW FM_FD_ERR_KEYSIZE_OVERFLOW +-/* Frame color is red */ +-#define FM_PORT_FRM_ERR_COLOR_RED FM_FD_ERR_COLOR_RED +-/* Frame color is yellow */ +-#define FM_PORT_FRM_ERR_COLOR_YELLOW FM_FD_ERR_COLOR_YELLOW +-/* Parser Time out Exceed */ +-#define FM_PORT_FRM_ERR_PRS_TIMEOUT FM_FD_ERR_PRS_TIMEOUT +-/* Invalid Soft Parser instruction */ +-#define FM_PORT_FRM_ERR_PRS_ILL_INSTRUCT FM_FD_ERR_PRS_ILL_INSTRUCT +-/* Header error was identified during parsing */ +-#define FM_PORT_FRM_ERR_PRS_HDR_ERR FM_FD_ERR_PRS_HDR_ERR +-/* Frame parsed beyind 256 first bytes */ +-#define FM_PORT_FRM_ERR_BLOCK_LIMIT_EXCEEDED FM_FD_ERR_BLOCK_LIMIT_EXCEEDED +-/* FPM Frame Processing Timeout Exceeded */ +-#define FM_PORT_FRM_ERR_PROCESS_TIMEOUT 0x00000001 +- +-struct fman_port; +- +-/* A structure for additional Rx port parameters */ +-struct fman_port_rx_params { +- u32 err_fqid; /* Error Queue Id. */ +- u32 dflt_fqid; /* Default Queue Id. */ +- /* Which external buffer pools are used +- * (up to FMAN_PORT_MAX_EXT_POOLS_NUM), and their sizes. +- */ +- struct fman_ext_pools ext_buf_pools; +-}; +- +-/* A structure for additional non-Rx port parameters */ +-struct fman_port_non_rx_params { +- /* Error Queue Id. */ +- u32 err_fqid; +- /* For Tx - Default Confirmation queue, 0 means no Tx confirmation +- * for processed frames. For OP port - default Rx queue. +- */ +- u32 dflt_fqid; +-}; +- +-/* A union for additional parameters depending on port type */ +-union fman_port_specific_params { +- /* Rx port parameters structure */ +- struct fman_port_rx_params rx_params; +- /* Non-Rx port parameters structure */ +- struct fman_port_non_rx_params non_rx_params; +-}; +- +-/* A structure representing FM initialization parameters */ +-struct fman_port_params { +- /* Virtual Address of memory mapped FM Port registers. */ +- void *fm; +- union fman_port_specific_params specific_params; +- /* Additional parameters depending on port type. */ +-}; +- +-int fman_port_config(struct fman_port *port, struct fman_port_params *params); +- +-int fman_port_init(struct fman_port *port); +- +-int fman_port_cfg_buf_prefix_content(struct fman_port *port, +- struct fman_buffer_prefix_content +- *buffer_prefix_content); +- +-int fman_port_disable(struct fman_port *port); +- +-int fman_port_enable(struct fman_port *port); +- +-u32 fman_port_get_qman_channel_id(struct fman_port *port); +- +-struct fman_port *fman_port_bind(struct device *dev); +- +-#endif /* __FMAN_PORT_H */ +diff --git a/drivers/net/ethernet/freescale/fman/fman_sp.c b/drivers/net/ethernet/freescale/fman/fman_sp.c +deleted file mode 100644 +index 248f5bc..0000000 +--- a/drivers/net/ethernet/freescale/fman/fman_sp.c ++++ /dev/null +@@ -1,169 +0,0 @@ +-/* +- * Copyright 2008 - 2015 Freescale Semiconductor Inc. +- * +- * Redistribution and use in source and binary forms, with or without +- * modification, are permitted provided that the following conditions are met: +- * * Redistributions of source code must retain the above copyright +- * notice, this list of conditions and the following disclaimer. +- * * Redistributions in binary form must reproduce the above copyright +- * notice, this list of conditions and the following disclaimer in the +- * documentation and/or other materials provided with the distribution. +- * * Neither the name of Freescale Semiconductor nor the +- * names of its contributors may be used to endorse or promote products +- * derived from this software without specific prior written permission. +- * +- * +- * ALTERNATIVELY, this software may be distributed under the terms of the +- * GNU General Public License ("GPL") as published by the Free Software +- * Foundation, either version 2 of that License or (at your option) any +- * later version. +- * +- * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY +- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +- * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY +- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +- */ +- +-#include "fman_sp.h" +-#include "fman.h" +- +-void fman_sp_set_buf_pools_in_asc_order_of_buf_sizes(struct fman_ext_pools +- *fm_ext_pools, +- u8 *ordered_array, +- u16 *sizes_array) +-{ +- u16 buf_size = 0; +- int i = 0, j = 0, k = 0; +- +- /* First we copy the external buffers pools information +- * to an ordered local array +- */ +- for (i = 0; i < fm_ext_pools->num_of_pools_used; i++) { +- /* get pool size */ +- buf_size = fm_ext_pools->ext_buf_pool[i].size; +- +- /* keep sizes in an array according to poolId +- * for direct access +- */ +- sizes_array[fm_ext_pools->ext_buf_pool[i].id] = buf_size; +- +- /* save poolId in an ordered array according to size */ +- for (j = 0; j <= i; j++) { +- /* this is the next free place in the array */ +- if (j == i) +- ordered_array[i] = +- fm_ext_pools->ext_buf_pool[i].id; +- else { +- /* find the right place for this poolId */ +- if (buf_size < sizes_array[ordered_array[j]]) { +- /* move the pool_ids one place ahead +- * to make room for this poolId +- */ +- for (k = i; k > j; k--) +- ordered_array[k] = +- ordered_array[k - 1]; +- +- /* now k==j, this is the place for +- * the new size +- */ +- ordered_array[k] = +- fm_ext_pools->ext_buf_pool[i].id; +- break; +- } +- } +- } +- } +-} +-EXPORT_SYMBOL(fman_sp_set_buf_pools_in_asc_order_of_buf_sizes); +- +-int fman_sp_build_buffer_struct(struct fman_sp_int_context_data_copy * +- int_context_data_copy, +- struct fman_buffer_prefix_content * +- buffer_prefix_content, +- struct fman_sp_buf_margins *buf_margins, +- struct fman_sp_buffer_offsets *buffer_offsets, +- u8 *internal_buf_offset) +-{ +- u32 tmp; +- +- /* Align start of internal context data to 16 byte */ +- int_context_data_copy->ext_buf_offset = (u16) +- ((buffer_prefix_content->priv_data_size & (OFFSET_UNITS - 1)) ? +- ((buffer_prefix_content->priv_data_size + OFFSET_UNITS) & +- ~(u16)(OFFSET_UNITS - 1)) : +- buffer_prefix_content->priv_data_size); +- +- /* Translate margin and int_context params to FM parameters */ +- /* Initialize with illegal value. Later we'll set legal values. */ +- buffer_offsets->prs_result_offset = (u32)ILLEGAL_BASE; +- buffer_offsets->time_stamp_offset = (u32)ILLEGAL_BASE; +- buffer_offsets->hash_result_offset = (u32)ILLEGAL_BASE; +- +- /* Internally the driver supports 4 options +- * 1. prsResult/timestamp/hashResult selection (in fact 8 options, +- * but for simplicity we'll +- * relate to it as 1). +- * 2. All IC context (from AD) not including debug. +- */ +- +- /* This case covers the options under 1 */ +- /* Copy size must be in 16-byte granularity. */ +- int_context_data_copy->size = +- (u16)((buffer_prefix_content->pass_prs_result ? 32 : 0) + +- ((buffer_prefix_content->pass_time_stamp || +- buffer_prefix_content->pass_hash_result) ? 16 : 0)); +- +- /* Align start of internal context data to 16 byte */ +- int_context_data_copy->int_context_offset = +- (u8)(buffer_prefix_content->pass_prs_result ? 32 : +- ((buffer_prefix_content->pass_time_stamp || +- buffer_prefix_content->pass_hash_result) ? 64 : 0)); +- +- if (buffer_prefix_content->pass_prs_result) +- buffer_offsets->prs_result_offset = +- int_context_data_copy->ext_buf_offset; +- if (buffer_prefix_content->pass_time_stamp) +- buffer_offsets->time_stamp_offset = +- buffer_prefix_content->pass_prs_result ? +- (int_context_data_copy->ext_buf_offset + +- sizeof(struct fman_prs_result)) : +- int_context_data_copy->ext_buf_offset; +- if (buffer_prefix_content->pass_hash_result) +- /* If PR is not requested, whether TS is +- * requested or not, IC will be copied from TS +- */ +- buffer_offsets->hash_result_offset = +- buffer_prefix_content->pass_prs_result ? +- (int_context_data_copy->ext_buf_offset + +- sizeof(struct fman_prs_result) + 8) : +- int_context_data_copy->ext_buf_offset + 8; +- +- if (int_context_data_copy->size) +- buf_margins->start_margins = +- (u16)(int_context_data_copy->ext_buf_offset + +- int_context_data_copy->size); +- else +- /* No Internal Context passing, STartMargin is +- * immediately after private_info +- */ +- buf_margins->start_margins = +- buffer_prefix_content->priv_data_size; +- +- /* align data start */ +- tmp = (u32)(buf_margins->start_margins % +- buffer_prefix_content->data_align); +- if (tmp) +- buf_margins->start_margins += +- (buffer_prefix_content->data_align - tmp); +- buffer_offsets->data_offset = buf_margins->start_margins; +- +- return 0; +-} +-EXPORT_SYMBOL(fman_sp_build_buffer_struct); +- +diff --git a/drivers/net/ethernet/freescale/fman/fman_sp.h b/drivers/net/ethernet/freescale/fman/fman_sp.h +deleted file mode 100644 +index 820b7f6..0000000 +--- a/drivers/net/ethernet/freescale/fman/fman_sp.h ++++ /dev/null +@@ -1,103 +0,0 @@ +-/* +- * Copyright 2008 - 2015 Freescale Semiconductor Inc. +- * +- * Redistribution and use in source and binary forms, with or without +- * modification, are permitted provided that the following conditions are met: +- * * Redistributions of source code must retain the above copyright +- * notice, this list of conditions and the following disclaimer. +- * * Redistributions in binary form must reproduce the above copyright +- * notice, this list of conditions and the following disclaimer in the +- * documentation and/or other materials provided with the distribution. +- * * Neither the name of Freescale Semiconductor nor the +- * names of its contributors may be used to endorse or promote products +- * derived from this software without specific prior written permission. +- * +- * ALTERNATIVELY, this software may be distributed under the terms of the +- * GNU General Public License ("GPL") as published by the Free Software +- * Foundation, either version 2 of that License or (at your option) any +- * later version. +- * +- * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY +- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +- * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY +- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +- */ +- +-#ifndef __FM_SP_H +-#define __FM_SP_H +- +-#include "fman.h" +-#include +- +-#define ILLEGAL_BASE (~0) +- +-/* defaults */ +-#define DFLT_FM_SP_BUFFER_PREFIX_CONTEXT_DATA_ALIGN 64 +- +-/* Registers bit fields */ +-#define FMAN_SP_EXT_BUF_POOL_EN_COUNTER 0x40000000 +-#define FMAN_SP_EXT_BUF_POOL_VALID 0x80000000 +-#define FMAN_SP_EXT_BUF_POOL_BACKUP 0x20000000 +-#define FMAN_SP_DMA_ATTR_WRITE_OPTIMIZE 0x00100000 +-#define FMAN_SP_SG_DISABLE 0x80000000 +- +-/* shifts */ +-#define FMAN_SP_EXT_BUF_MARG_START_SHIFT 16 +-#define FMAN_SP_DMA_ATTR_SWP_SHIFT 30 +-#define FMAN_SP_IC_TO_EXT_SHIFT 16 +-#define FMAN_SP_IC_FROM_INT_SHIFT 8 +- +-/* structure for defining internal context copying */ +-struct fman_sp_int_context_data_copy { +- /* < Offset in External buffer to which internal +- * context is copied to (Rx) or taken from (Tx, Op). +- */ +- u16 ext_buf_offset; +- /* Offset within internal context to copy from +- * (Rx) or to copy to (Tx, Op). +- */ +- u8 int_context_offset; +- /* Internal offset size to be copied */ +- u16 size; +-}; +- +-/* struct for defining external buffer margins */ +-struct fman_sp_buf_margins { +- /* Number of bytes to be left at the beginning +- * of the external buffer (must be divisible by 16) +- */ +- u16 start_margins; +- /* number of bytes to be left at the end +- * of the external buffer(must be divisible by 16) +- */ +- u16 end_margins; +-}; +- +-struct fman_sp_buffer_offsets { +- u32 data_offset; +- u32 prs_result_offset; +- u32 time_stamp_offset; +- u32 hash_result_offset; +-}; +- +-int fman_sp_build_buffer_struct(struct fman_sp_int_context_data_copy +- *int_context_data_copy, +- struct fman_buffer_prefix_content +- *buffer_prefix_content, +- struct fman_sp_buf_margins *buf_margins, +- struct fman_sp_buffer_offsets +- *buffer_offsets, +- u8 *internal_buf_offset); +- +-void fman_sp_set_buf_pools_in_asc_order_of_buf_sizes(struct fman_ext_pools +- *fm_ext_pools, +- u8 *ordered_array, +- u16 *sizes_array); +- +-#endif /* __FM_SP_H */ +diff --git a/drivers/net/ethernet/freescale/fman/fman_tgec.c b/drivers/net/ethernet/freescale/fman/fman_tgec.c +deleted file mode 100644 +index 4b0f3a5..0000000 +--- a/drivers/net/ethernet/freescale/fman/fman_tgec.c ++++ /dev/null +@@ -1,783 +0,0 @@ +-/* +- * Copyright 2008-2015 Freescale Semiconductor Inc. +- * +- * Redistribution and use in source and binary forms, with or without +- * modification, are permitted provided that the following conditions are met: +- * * Redistributions of source code must retain the above copyright +- * notice, this list of conditions and the following disclaimer. +- * * Redistributions in binary form must reproduce the above copyright +- * notice, this list of conditions and the following disclaimer in the +- * documentation and/or other materials provided with the distribution. +- * * Neither the name of Freescale Semiconductor nor the +- * names of its contributors may be used to endorse or promote products +- * derived from this software without specific prior written permission. +- * +- * +- * ALTERNATIVELY, this software may be distributed under the terms of the +- * GNU General Public License ("GPL") as published by the Free Software +- * Foundation, either version 2 of that License or (at your option) any +- * later version. +- * +- * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY +- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +- * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY +- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +- */ +- +-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +- +-#include "fman_tgec.h" +-#include "fman.h" +- +-#include +-#include +-#include +-#include +- +-/* Transmit Inter-Packet Gap Length Register (TX_IPG_LENGTH) */ +-#define TGEC_TX_IPG_LENGTH_MASK 0x000003ff +- +-/* Command and Configuration Register (COMMAND_CONFIG) */ +-#define CMD_CFG_NO_LEN_CHK 0x00020000 +-#define CMD_CFG_PAUSE_IGNORE 0x00000100 +-#define CMF_CFG_CRC_FWD 0x00000040 +-#define CMD_CFG_PROMIS_EN 0x00000010 +-#define CMD_CFG_RX_EN 0x00000002 +-#define CMD_CFG_TX_EN 0x00000001 +- +-/* Interrupt Mask Register (IMASK) */ +-#define TGEC_IMASK_MDIO_SCAN_EVENT 0x00010000 +-#define TGEC_IMASK_MDIO_CMD_CMPL 0x00008000 +-#define TGEC_IMASK_REM_FAULT 0x00004000 +-#define TGEC_IMASK_LOC_FAULT 0x00002000 +-#define TGEC_IMASK_TX_ECC_ER 0x00001000 +-#define TGEC_IMASK_TX_FIFO_UNFL 0x00000800 +-#define TGEC_IMASK_TX_FIFO_OVFL 0x00000400 +-#define TGEC_IMASK_TX_ER 0x00000200 +-#define TGEC_IMASK_RX_FIFO_OVFL 0x00000100 +-#define TGEC_IMASK_RX_ECC_ER 0x00000080 +-#define TGEC_IMASK_RX_JAB_FRM 0x00000040 +-#define TGEC_IMASK_RX_OVRSZ_FRM 0x00000020 +-#define TGEC_IMASK_RX_RUNT_FRM 0x00000010 +-#define TGEC_IMASK_RX_FRAG_FRM 0x00000008 +-#define TGEC_IMASK_RX_LEN_ER 0x00000004 +-#define TGEC_IMASK_RX_CRC_ER 0x00000002 +-#define TGEC_IMASK_RX_ALIGN_ER 0x00000001 +- +-/* Hashtable Control Register (HASHTABLE_CTRL) */ +-#define TGEC_HASH_MCAST_SHIFT 23 +-#define TGEC_HASH_MCAST_EN 0x00000200 +-#define TGEC_HASH_ADR_MSK 0x000001ff +- +-#define DEFAULT_TX_IPG_LENGTH 12 +-#define DEFAULT_MAX_FRAME_LENGTH 0x600 +-#define DEFAULT_PAUSE_QUANT 0xf000 +- +-/* number of pattern match registers (entries) */ +-#define TGEC_NUM_OF_PADDRS 1 +- +-/* Group address bit indication */ +-#define GROUP_ADDRESS 0x0000010000000000LL +- +-/* Hash table size (= 32 bits*8 regs) */ +-#define TGEC_HASH_TABLE_SIZE 512 +- +-/* tGEC memory map */ +-struct tgec_regs { +- u32 tgec_id; /* 0x000 Controller ID */ +- u32 reserved001[1]; /* 0x004 */ +- u32 command_config; /* 0x008 Control and configuration */ +- u32 mac_addr_0; /* 0x00c Lower 32 bits of the MAC adr */ +- u32 mac_addr_1; /* 0x010 Upper 16 bits of the MAC adr */ +- u32 maxfrm; /* 0x014 Maximum frame length */ +- u32 pause_quant; /* 0x018 Pause quanta */ +- u32 rx_fifo_sections; /* 0x01c */ +- u32 tx_fifo_sections; /* 0x020 */ +- u32 rx_fifo_almost_f_e; /* 0x024 */ +- u32 tx_fifo_almost_f_e; /* 0x028 */ +- u32 hashtable_ctrl; /* 0x02c Hash table control */ +- u32 mdio_cfg_status; /* 0x030 */ +- u32 mdio_command; /* 0x034 */ +- u32 mdio_data; /* 0x038 */ +- u32 mdio_regaddr; /* 0x03c */ +- u32 status; /* 0x040 */ +- u32 tx_ipg_len; /* 0x044 Transmitter inter-packet-gap */ +- u32 mac_addr_2; /* 0x048 Lower 32 bits of 2nd MAC adr */ +- u32 mac_addr_3; /* 0x04c Upper 16 bits of 2nd MAC adr */ +- u32 rx_fifo_ptr_rd; /* 0x050 */ +- u32 rx_fifo_ptr_wr; /* 0x054 */ +- u32 tx_fifo_ptr_rd; /* 0x058 */ +- u32 tx_fifo_ptr_wr; /* 0x05c */ +- u32 imask; /* 0x060 Interrupt mask */ +- u32 ievent; /* 0x064 Interrupt event */ +- u32 udp_port; /* 0x068 Defines a UDP Port number */ +- u32 type_1588v2; /* 0x06c Type field for 1588v2 */ +- u32 reserved070[4]; /* 0x070 */ +- /* 10Ge Statistics Counter */ +- u32 tfrm_u; /* 80 aFramesTransmittedOK */ +- u32 tfrm_l; /* 84 aFramesTransmittedOK */ +- u32 rfrm_u; /* 88 aFramesReceivedOK */ +- u32 rfrm_l; /* 8c aFramesReceivedOK */ +- u32 rfcs_u; /* 90 aFrameCheckSequenceErrors */ +- u32 rfcs_l; /* 94 aFrameCheckSequenceErrors */ +- u32 raln_u; /* 98 aAlignmentErrors */ +- u32 raln_l; /* 9c aAlignmentErrors */ +- u32 txpf_u; /* A0 aPAUSEMACCtrlFramesTransmitted */ +- u32 txpf_l; /* A4 aPAUSEMACCtrlFramesTransmitted */ +- u32 rxpf_u; /* A8 aPAUSEMACCtrlFramesReceived */ +- u32 rxpf_l; /* Ac aPAUSEMACCtrlFramesReceived */ +- u32 rlong_u; /* B0 aFrameTooLongErrors */ +- u32 rlong_l; /* B4 aFrameTooLongErrors */ +- u32 rflr_u; /* B8 aInRangeLengthErrors */ +- u32 rflr_l; /* Bc aInRangeLengthErrors */ +- u32 tvlan_u; /* C0 VLANTransmittedOK */ +- u32 tvlan_l; /* C4 VLANTransmittedOK */ +- u32 rvlan_u; /* C8 VLANReceivedOK */ +- u32 rvlan_l; /* Cc VLANReceivedOK */ +- u32 toct_u; /* D0 if_out_octets */ +- u32 toct_l; /* D4 if_out_octets */ +- u32 roct_u; /* D8 if_in_octets */ +- u32 roct_l; /* Dc if_in_octets */ +- u32 ruca_u; /* E0 if_in_ucast_pkts */ +- u32 ruca_l; /* E4 if_in_ucast_pkts */ +- u32 rmca_u; /* E8 ifInMulticastPkts */ +- u32 rmca_l; /* Ec ifInMulticastPkts */ +- u32 rbca_u; /* F0 ifInBroadcastPkts */ +- u32 rbca_l; /* F4 ifInBroadcastPkts */ +- u32 terr_u; /* F8 if_out_errors */ +- u32 terr_l; /* Fc if_out_errors */ +- u32 reserved100[2]; /* 100-108 */ +- u32 tuca_u; /* 108 if_out_ucast_pkts */ +- u32 tuca_l; /* 10c if_out_ucast_pkts */ +- u32 tmca_u; /* 110 ifOutMulticastPkts */ +- u32 tmca_l; /* 114 ifOutMulticastPkts */ +- u32 tbca_u; /* 118 ifOutBroadcastPkts */ +- u32 tbca_l; /* 11c ifOutBroadcastPkts */ +- u32 rdrp_u; /* 120 etherStatsDropEvents */ +- u32 rdrp_l; /* 124 etherStatsDropEvents */ +- u32 reoct_u; /* 128 etherStatsOctets */ +- u32 reoct_l; /* 12c etherStatsOctets */ +- u32 rpkt_u; /* 130 etherStatsPkts */ +- u32 rpkt_l; /* 134 etherStatsPkts */ +- u32 trund_u; /* 138 etherStatsUndersizePkts */ +- u32 trund_l; /* 13c etherStatsUndersizePkts */ +- u32 r64_u; /* 140 etherStatsPkts64Octets */ +- u32 r64_l; /* 144 etherStatsPkts64Octets */ +- u32 r127_u; /* 148 etherStatsPkts65to127Octets */ +- u32 r127_l; /* 14c etherStatsPkts65to127Octets */ +- u32 r255_u; /* 150 etherStatsPkts128to255Octets */ +- u32 r255_l; /* 154 etherStatsPkts128to255Octets */ +- u32 r511_u; /* 158 etherStatsPkts256to511Octets */ +- u32 r511_l; /* 15c etherStatsPkts256to511Octets */ +- u32 r1023_u; /* 160 etherStatsPkts512to1023Octets */ +- u32 r1023_l; /* 164 etherStatsPkts512to1023Octets */ +- u32 r1518_u; /* 168 etherStatsPkts1024to1518Octets */ +- u32 r1518_l; /* 16c etherStatsPkts1024to1518Octets */ +- u32 r1519x_u; /* 170 etherStatsPkts1519toX */ +- u32 r1519x_l; /* 174 etherStatsPkts1519toX */ +- u32 trovr_u; /* 178 etherStatsOversizePkts */ +- u32 trovr_l; /* 17c etherStatsOversizePkts */ +- u32 trjbr_u; /* 180 etherStatsJabbers */ +- u32 trjbr_l; /* 184 etherStatsJabbers */ +- u32 trfrg_u; /* 188 etherStatsFragments */ +- u32 trfrg_l; /* 18C etherStatsFragments */ +- u32 rerr_u; /* 190 if_in_errors */ +- u32 rerr_l; /* 194 if_in_errors */ +-}; +- +-struct tgec_cfg { +- bool pause_ignore; +- bool promiscuous_mode_enable; +- u16 max_frame_length; +- u16 pause_quant; +- u32 tx_ipg_length; +-}; +- +-struct fman_mac { +- /* Pointer to the memory mapped registers. */ +- struct tgec_regs __iomem *regs; +- /* MAC address of device; */ +- u64 addr; +- u16 max_speed; +- void *dev_id; /* device cookie used by the exception cbs */ +- fman_mac_exception_cb *exception_cb; +- fman_mac_exception_cb *event_cb; +- /* pointer to driver's global address hash table */ +- struct eth_hash_t *multicast_addr_hash; +- /* pointer to driver's individual address hash table */ +- struct eth_hash_t *unicast_addr_hash; +- u8 mac_id; +- u32 exceptions; +- struct tgec_cfg *cfg; +- void *fm; +- struct fman_rev_info fm_rev_info; +-}; +- +-static void set_mac_address(struct tgec_regs __iomem *regs, u8 *adr) +-{ +- u32 tmp0, tmp1; +- +- tmp0 = (u32)(adr[0] | adr[1] << 8 | adr[2] << 16 | adr[3] << 24); +- tmp1 = (u32)(adr[4] | adr[5] << 8); +- iowrite32be(tmp0, ®s->mac_addr_0); +- iowrite32be(tmp1, ®s->mac_addr_1); +-} +- +-static void set_dflts(struct tgec_cfg *cfg) +-{ +- cfg->promiscuous_mode_enable = false; +- cfg->pause_ignore = false; +- cfg->tx_ipg_length = DEFAULT_TX_IPG_LENGTH; +- cfg->max_frame_length = DEFAULT_MAX_FRAME_LENGTH; +- cfg->pause_quant = DEFAULT_PAUSE_QUANT; +-} +- +-static int init(struct tgec_regs __iomem *regs, struct tgec_cfg *cfg, +- u32 exception_mask) +-{ +- u32 tmp; +- +- /* Config */ +- tmp = CMF_CFG_CRC_FWD; +- if (cfg->promiscuous_mode_enable) +- tmp |= CMD_CFG_PROMIS_EN; +- if (cfg->pause_ignore) +- tmp |= CMD_CFG_PAUSE_IGNORE; +- /* Payload length check disable */ +- tmp |= CMD_CFG_NO_LEN_CHK; +- iowrite32be(tmp, ®s->command_config); +- +- /* Max Frame Length */ +- iowrite32be((u32)cfg->max_frame_length, ®s->maxfrm); +- /* Pause Time */ +- iowrite32be(cfg->pause_quant, ®s->pause_quant); +- +- /* clear all pending events and set-up interrupts */ +- iowrite32be(0xffffffff, ®s->ievent); +- iowrite32be(ioread32be(®s->imask) | exception_mask, ®s->imask); +- +- return 0; +-} +- +-static int check_init_parameters(struct fman_mac *tgec) +-{ +- if (tgec->max_speed < SPEED_10000) { +- pr_err("10G MAC driver only support 10G speed\n"); +- return -EINVAL; +- } +- if (tgec->addr == 0) { +- pr_err("Ethernet 10G MAC Must have valid MAC Address\n"); +- return -EINVAL; +- } +- if (!tgec->exception_cb) { +- pr_err("uninitialized exception_cb\n"); +- return -EINVAL; +- } +- if (!tgec->event_cb) { +- pr_err("uninitialized event_cb\n"); +- return -EINVAL; +- } +- +- return 0; +-} +- +-static int get_exception_flag(enum fman_mac_exceptions exception) +-{ +- u32 bit_mask; +- +- switch (exception) { +- case FM_MAC_EX_10G_MDIO_SCAN_EVENT: +- bit_mask = TGEC_IMASK_MDIO_SCAN_EVENT; +- break; +- case FM_MAC_EX_10G_MDIO_CMD_CMPL: +- bit_mask = TGEC_IMASK_MDIO_CMD_CMPL; +- break; +- case FM_MAC_EX_10G_REM_FAULT: +- bit_mask = TGEC_IMASK_REM_FAULT; +- break; +- case FM_MAC_EX_10G_LOC_FAULT: +- bit_mask = TGEC_IMASK_LOC_FAULT; +- break; +- case FM_MAC_EX_10G_TX_ECC_ER: +- bit_mask = TGEC_IMASK_TX_ECC_ER; +- break; +- case FM_MAC_EX_10G_TX_FIFO_UNFL: +- bit_mask = TGEC_IMASK_TX_FIFO_UNFL; +- break; +- case FM_MAC_EX_10G_TX_FIFO_OVFL: +- bit_mask = TGEC_IMASK_TX_FIFO_OVFL; +- break; +- case FM_MAC_EX_10G_TX_ER: +- bit_mask = TGEC_IMASK_TX_ER; +- break; +- case FM_MAC_EX_10G_RX_FIFO_OVFL: +- bit_mask = TGEC_IMASK_RX_FIFO_OVFL; +- break; +- case FM_MAC_EX_10G_RX_ECC_ER: +- bit_mask = TGEC_IMASK_RX_ECC_ER; +- break; +- case FM_MAC_EX_10G_RX_JAB_FRM: +- bit_mask = TGEC_IMASK_RX_JAB_FRM; +- break; +- case FM_MAC_EX_10G_RX_OVRSZ_FRM: +- bit_mask = TGEC_IMASK_RX_OVRSZ_FRM; +- break; +- case FM_MAC_EX_10G_RX_RUNT_FRM: +- bit_mask = TGEC_IMASK_RX_RUNT_FRM; +- break; +- case FM_MAC_EX_10G_RX_FRAG_FRM: +- bit_mask = TGEC_IMASK_RX_FRAG_FRM; +- break; +- case FM_MAC_EX_10G_RX_LEN_ER: +- bit_mask = TGEC_IMASK_RX_LEN_ER; +- break; +- case FM_MAC_EX_10G_RX_CRC_ER: +- bit_mask = TGEC_IMASK_RX_CRC_ER; +- break; +- case FM_MAC_EX_10G_RX_ALIGN_ER: +- bit_mask = TGEC_IMASK_RX_ALIGN_ER; +- break; +- default: +- bit_mask = 0; +- break; +- } +- +- return bit_mask; +-} +- +-static void tgec_err_exception(void *handle) +-{ +- struct fman_mac *tgec = (struct fman_mac *)handle; +- struct tgec_regs __iomem *regs = tgec->regs; +- u32 event; +- +- /* do not handle MDIO events */ +- event = ioread32be(®s->ievent) & +- ~(TGEC_IMASK_MDIO_SCAN_EVENT | +- TGEC_IMASK_MDIO_CMD_CMPL); +- +- event &= ioread32be(®s->imask); +- +- iowrite32be(event, ®s->ievent); +- +- if (event & TGEC_IMASK_REM_FAULT) +- tgec->exception_cb(tgec->dev_id, FM_MAC_EX_10G_REM_FAULT); +- if (event & TGEC_IMASK_LOC_FAULT) +- tgec->exception_cb(tgec->dev_id, FM_MAC_EX_10G_LOC_FAULT); +- if (event & TGEC_IMASK_TX_ECC_ER) +- tgec->exception_cb(tgec->dev_id, FM_MAC_EX_10G_TX_ECC_ER); +- if (event & TGEC_IMASK_TX_FIFO_UNFL) +- tgec->exception_cb(tgec->dev_id, FM_MAC_EX_10G_TX_FIFO_UNFL); +- if (event & TGEC_IMASK_TX_FIFO_OVFL) +- tgec->exception_cb(tgec->dev_id, FM_MAC_EX_10G_TX_FIFO_OVFL); +- if (event & TGEC_IMASK_TX_ER) +- tgec->exception_cb(tgec->dev_id, FM_MAC_EX_10G_TX_ER); +- if (event & TGEC_IMASK_RX_FIFO_OVFL) +- tgec->exception_cb(tgec->dev_id, FM_MAC_EX_10G_RX_FIFO_OVFL); +- if (event & TGEC_IMASK_RX_ECC_ER) +- tgec->exception_cb(tgec->dev_id, FM_MAC_EX_10G_RX_ECC_ER); +- if (event & TGEC_IMASK_RX_JAB_FRM) +- tgec->exception_cb(tgec->dev_id, FM_MAC_EX_10G_RX_JAB_FRM); +- if (event & TGEC_IMASK_RX_OVRSZ_FRM) +- tgec->exception_cb(tgec->dev_id, FM_MAC_EX_10G_RX_OVRSZ_FRM); +- if (event & TGEC_IMASK_RX_RUNT_FRM) +- tgec->exception_cb(tgec->dev_id, FM_MAC_EX_10G_RX_RUNT_FRM); +- if (event & TGEC_IMASK_RX_FRAG_FRM) +- tgec->exception_cb(tgec->dev_id, FM_MAC_EX_10G_RX_FRAG_FRM); +- if (event & TGEC_IMASK_RX_LEN_ER) +- tgec->exception_cb(tgec->dev_id, FM_MAC_EX_10G_RX_LEN_ER); +- if (event & TGEC_IMASK_RX_CRC_ER) +- tgec->exception_cb(tgec->dev_id, FM_MAC_EX_10G_RX_CRC_ER); +- if (event & TGEC_IMASK_RX_ALIGN_ER) +- tgec->exception_cb(tgec->dev_id, FM_MAC_EX_10G_RX_ALIGN_ER); +-} +- +-static void free_init_resources(struct fman_mac *tgec) +-{ +- fman_unregister_intr(tgec->fm, FMAN_MOD_MAC, tgec->mac_id, +- FMAN_INTR_TYPE_ERR); +- +- /* release the driver's group hash table */ +- free_hash_table(tgec->multicast_addr_hash); +- tgec->multicast_addr_hash = NULL; +- +- /* release the driver's individual hash table */ +- free_hash_table(tgec->unicast_addr_hash); +- tgec->unicast_addr_hash = NULL; +-} +- +-static bool is_init_done(struct tgec_cfg *cfg) +-{ +- /* Checks if tGEC driver parameters were initialized */ +- if (!cfg) +- return true; +- +- return false; +-} +- +-int tgec_enable(struct fman_mac *tgec, enum comm_mode mode) +-{ +- struct tgec_regs __iomem *regs = tgec->regs; +- u32 tmp; +- +- if (!is_init_done(tgec->cfg)) +- return -EINVAL; +- +- tmp = ioread32be(®s->command_config); +- if (mode & COMM_MODE_RX) +- tmp |= CMD_CFG_RX_EN; +- if (mode & COMM_MODE_TX) +- tmp |= CMD_CFG_TX_EN; +- iowrite32be(tmp, ®s->command_config); +- +- return 0; +-} +- +-int tgec_disable(struct fman_mac *tgec, enum comm_mode mode) +-{ +- struct tgec_regs __iomem *regs = tgec->regs; +- u32 tmp; +- +- if (!is_init_done(tgec->cfg)) +- return -EINVAL; +- +- tmp = ioread32be(®s->command_config); +- if (mode & COMM_MODE_RX) +- tmp &= ~CMD_CFG_RX_EN; +- if (mode & COMM_MODE_TX) +- tmp &= ~CMD_CFG_TX_EN; +- iowrite32be(tmp, ®s->command_config); +- +- return 0; +-} +- +-int tgec_set_promiscuous(struct fman_mac *tgec, bool new_val) +-{ +- struct tgec_regs __iomem *regs = tgec->regs; +- u32 tmp; +- +- if (!is_init_done(tgec->cfg)) +- return -EINVAL; +- +- tmp = ioread32be(®s->command_config); +- if (new_val) +- tmp |= CMD_CFG_PROMIS_EN; +- else +- tmp &= ~CMD_CFG_PROMIS_EN; +- iowrite32be(tmp, ®s->command_config); +- +- return 0; +-} +- +-int tgec_cfg_max_frame_len(struct fman_mac *tgec, u16 new_val) +-{ +- if (is_init_done(tgec->cfg)) +- return -EINVAL; +- +- tgec->cfg->max_frame_length = new_val; +- +- return 0; +-} +- +-int tgec_set_tx_pause_frames(struct fman_mac *tgec, u8 __maybe_unused priority, +- u16 pause_time, u16 __maybe_unused thresh_time) +-{ +- struct tgec_regs __iomem *regs = tgec->regs; +- +- if (!is_init_done(tgec->cfg)) +- return -EINVAL; +- +- iowrite32be((u32)pause_time, ®s->pause_quant); +- +- return 0; +-} +- +-int tgec_accept_rx_pause_frames(struct fman_mac *tgec, bool en) +-{ +- struct tgec_regs __iomem *regs = tgec->regs; +- u32 tmp; +- +- if (!is_init_done(tgec->cfg)) +- return -EINVAL; +- +- tmp = ioread32be(®s->command_config); +- if (!en) +- tmp |= CMD_CFG_PAUSE_IGNORE; +- else +- tmp &= ~CMD_CFG_PAUSE_IGNORE; +- iowrite32be(tmp, ®s->command_config); +- +- return 0; +-} +- +-int tgec_modify_mac_address(struct fman_mac *tgec, enet_addr_t *p_enet_addr) +-{ +- if (!is_init_done(tgec->cfg)) +- return -EINVAL; +- +- tgec->addr = ENET_ADDR_TO_UINT64(*p_enet_addr); +- set_mac_address(tgec->regs, (u8 *)(*p_enet_addr)); +- +- return 0; +-} +- +-int tgec_add_hash_mac_address(struct fman_mac *tgec, enet_addr_t *eth_addr) +-{ +- struct tgec_regs __iomem *regs = tgec->regs; +- struct eth_hash_entry *hash_entry; +- u32 crc = 0xFFFFFFFF, hash; +- u64 addr; +- +- if (!is_init_done(tgec->cfg)) +- return -EINVAL; +- +- addr = ENET_ADDR_TO_UINT64(*eth_addr); +- +- if (!(addr & GROUP_ADDRESS)) { +- /* Unicast addresses not supported in hash */ +- pr_err("Unicast Address\n"); +- return -EINVAL; +- } +- /* CRC calculation */ +- crc = crc32_le(crc, (u8 *)eth_addr, ETH_ALEN); +- crc = bitrev32(crc); +- /* Take 9 MSB bits */ +- hash = (crc >> TGEC_HASH_MCAST_SHIFT) & TGEC_HASH_ADR_MSK; +- +- /* Create element to be added to the driver hash table */ +- hash_entry = kmalloc(sizeof(*hash_entry), GFP_KERNEL); +- if (!hash_entry) +- return -ENOMEM; +- hash_entry->addr = addr; +- INIT_LIST_HEAD(&hash_entry->node); +- +- list_add_tail(&hash_entry->node, +- &tgec->multicast_addr_hash->lsts[hash]); +- iowrite32be((hash | TGEC_HASH_MCAST_EN), ®s->hashtable_ctrl); +- +- return 0; +-} +- +-int tgec_del_hash_mac_address(struct fman_mac *tgec, enet_addr_t *eth_addr) +-{ +- struct tgec_regs __iomem *regs = tgec->regs; +- struct eth_hash_entry *hash_entry = NULL; +- struct list_head *pos; +- u32 crc = 0xFFFFFFFF, hash; +- u64 addr; +- +- if (!is_init_done(tgec->cfg)) +- return -EINVAL; +- +- addr = ((*(u64 *)eth_addr) >> 16); +- +- /* CRC calculation */ +- crc = crc32_le(crc, (u8 *)eth_addr, ETH_ALEN); +- crc = bitrev32(crc); +- /* Take 9 MSB bits */ +- hash = (crc >> TGEC_HASH_MCAST_SHIFT) & TGEC_HASH_ADR_MSK; +- +- list_for_each(pos, &tgec->multicast_addr_hash->lsts[hash]) { +- hash_entry = ETH_HASH_ENTRY_OBJ(pos); +- if (hash_entry->addr == addr) { +- list_del_init(&hash_entry->node); +- kfree(hash_entry); +- break; +- } +- } +- if (list_empty(&tgec->multicast_addr_hash->lsts[hash])) +- iowrite32be((hash & ~TGEC_HASH_MCAST_EN), +- ®s->hashtable_ctrl); +- +- return 0; +-} +- +-int tgec_get_version(struct fman_mac *tgec, u32 *mac_version) +-{ +- struct tgec_regs __iomem *regs = tgec->regs; +- +- if (!is_init_done(tgec->cfg)) +- return -EINVAL; +- +- *mac_version = ioread32be(®s->tgec_id); +- +- return 0; +-} +- +-int tgec_set_exception(struct fman_mac *tgec, +- enum fman_mac_exceptions exception, bool enable) +-{ +- struct tgec_regs __iomem *regs = tgec->regs; +- u32 bit_mask = 0; +- +- if (!is_init_done(tgec->cfg)) +- return -EINVAL; +- +- bit_mask = get_exception_flag(exception); +- if (bit_mask) { +- if (enable) +- tgec->exceptions |= bit_mask; +- else +- tgec->exceptions &= ~bit_mask; +- } else { +- pr_err("Undefined exception\n"); +- return -EINVAL; +- } +- if (enable) +- iowrite32be(ioread32be(®s->imask) | bit_mask, ®s->imask); +- else +- iowrite32be(ioread32be(®s->imask) & ~bit_mask, ®s->imask); +- +- return 0; +-} +- +-int tgec_init(struct fman_mac *tgec) +-{ +- struct tgec_cfg *cfg; +- enet_addr_t eth_addr; +- int err; +- +- if (is_init_done(tgec->cfg)) +- return -EINVAL; +- +- if (DEFAULT_RESET_ON_INIT && +- (fman_reset_mac(tgec->fm, tgec->mac_id) != 0)) { +- pr_err("Can't reset MAC!\n"); +- return -EINVAL; +- } +- +- err = check_init_parameters(tgec); +- if (err) +- return err; +- +- cfg = tgec->cfg; +- +- MAKE_ENET_ADDR_FROM_UINT64(tgec->addr, eth_addr); +- set_mac_address(tgec->regs, (u8 *)eth_addr); +- +- /* interrupts */ +- /* FM_10G_REM_N_LCL_FLT_EX_10GMAC_ERRATA_SW005 Errata workaround */ +- if (tgec->fm_rev_info.major <= 2) +- tgec->exceptions &= ~(TGEC_IMASK_REM_FAULT | +- TGEC_IMASK_LOC_FAULT); +- +- err = init(tgec->regs, cfg, tgec->exceptions); +- if (err) { +- free_init_resources(tgec); +- pr_err("TGEC version doesn't support this i/f mode\n"); +- return err; +- } +- +- /* Max Frame Length */ +- err = fman_set_mac_max_frame(tgec->fm, tgec->mac_id, +- cfg->max_frame_length); +- if (err) { +- pr_err("Setting max frame length FAILED\n"); +- free_init_resources(tgec); +- return -EINVAL; +- } +- +- /* FM_TX_FIFO_CORRUPTION_ERRATA_10GMAC_A007 Errata workaround */ +- if (tgec->fm_rev_info.major == 2) { +- struct tgec_regs __iomem *regs = tgec->regs; +- u32 tmp; +- +- /* restore the default tx ipg Length */ +- tmp = (ioread32be(®s->tx_ipg_len) & +- ~TGEC_TX_IPG_LENGTH_MASK) | 12; +- +- iowrite32be(tmp, ®s->tx_ipg_len); +- } +- +- tgec->multicast_addr_hash = alloc_hash_table(TGEC_HASH_TABLE_SIZE); +- if (!tgec->multicast_addr_hash) { +- free_init_resources(tgec); +- pr_err("allocation hash table is FAILED\n"); +- return -ENOMEM; +- } +- +- tgec->unicast_addr_hash = alloc_hash_table(TGEC_HASH_TABLE_SIZE); +- if (!tgec->unicast_addr_hash) { +- free_init_resources(tgec); +- pr_err("allocation hash table is FAILED\n"); +- return -ENOMEM; +- } +- +- fman_register_intr(tgec->fm, FMAN_MOD_MAC, tgec->mac_id, +- FMAN_INTR_TYPE_ERR, tgec_err_exception, tgec); +- +- kfree(cfg); +- tgec->cfg = NULL; +- +- return 0; +-} +- +-int tgec_free(struct fman_mac *tgec) +-{ +- free_init_resources(tgec); +- +- kfree(tgec->cfg); +- kfree(tgec); +- +- return 0; +-} +- +-struct fman_mac *tgec_config(struct fman_mac_params *params) +-{ +- struct fman_mac *tgec; +- struct tgec_cfg *cfg; +- void __iomem *base_addr; +- +- base_addr = params->base_addr; +- /* allocate memory for the UCC GETH data structure. */ +- tgec = kzalloc(sizeof(*tgec), GFP_KERNEL); +- if (!tgec) +- return NULL; +- +- /* allocate memory for the 10G MAC driver parameters data structure. */ +- cfg = kzalloc(sizeof(*cfg), GFP_KERNEL); +- if (!cfg) { +- tgec_free(tgec); +- return NULL; +- } +- +- /* Plant parameter structure pointer */ +- tgec->cfg = cfg; +- +- set_dflts(cfg); +- +- tgec->regs = base_addr; +- tgec->addr = ENET_ADDR_TO_UINT64(params->addr); +- tgec->max_speed = params->max_speed; +- tgec->mac_id = params->mac_id; +- tgec->exceptions = (TGEC_IMASK_MDIO_SCAN_EVENT | +- TGEC_IMASK_REM_FAULT | +- TGEC_IMASK_LOC_FAULT | +- TGEC_IMASK_TX_ECC_ER | +- TGEC_IMASK_TX_FIFO_UNFL | +- TGEC_IMASK_TX_FIFO_OVFL | +- TGEC_IMASK_TX_ER | +- TGEC_IMASK_RX_FIFO_OVFL | +- TGEC_IMASK_RX_ECC_ER | +- TGEC_IMASK_RX_JAB_FRM | +- TGEC_IMASK_RX_OVRSZ_FRM | +- TGEC_IMASK_RX_RUNT_FRM | +- TGEC_IMASK_RX_FRAG_FRM | +- TGEC_IMASK_RX_CRC_ER | +- TGEC_IMASK_RX_ALIGN_ER); +- tgec->exception_cb = params->exception_cb; +- tgec->event_cb = params->event_cb; +- tgec->dev_id = params->dev_id; +- tgec->fm = params->fm; +- +- /* Save FMan revision */ +- fman_get_revision(tgec->fm, &tgec->fm_rev_info); +- +- return tgec; +-} +diff --git a/drivers/net/ethernet/freescale/fman/fman_tgec.h b/drivers/net/ethernet/freescale/fman/fman_tgec.h +deleted file mode 100644 +index 514bba9..0000000 +--- a/drivers/net/ethernet/freescale/fman/fman_tgec.h ++++ /dev/null +@@ -1,55 +0,0 @@ +-/* +- * Copyright 2008-2015 Freescale Semiconductor Inc. +- * +- * Redistribution and use in source and binary forms, with or without +- * modification, are permitted provided that the following conditions are met: +- * * Redistributions of source code must retain the above copyright +- * notice, this list of conditions and the following disclaimer. +- * * Redistributions in binary form must reproduce the above copyright +- * notice, this list of conditions and the following disclaimer in the +- * documentation and/or other materials provided with the distribution. +- * * Neither the name of Freescale Semiconductor nor the +- * names of its contributors may be used to endorse or promote products +- * derived from this software without specific prior written permission. +- * +- * +- * ALTERNATIVELY, this software may be distributed under the terms of the +- * GNU General Public License ("GPL") as published by the Free Software +- * Foundation, either version 2 of that License or (at your option) any +- * later version. +- * +- * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY +- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +- * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY +- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +- */ +- +-#ifndef __TGEC_H +-#define __TGEC_H +- +-#include "fman_mac.h" +- +-struct fman_mac *tgec_config(struct fman_mac_params *params); +-int tgec_set_promiscuous(struct fman_mac *tgec, bool new_val); +-int tgec_modify_mac_address(struct fman_mac *tgec, enet_addr_t *enet_addr); +-int tgec_cfg_max_frame_len(struct fman_mac *tgec, u16 new_val); +-int tgec_enable(struct fman_mac *tgec, enum comm_mode mode); +-int tgec_disable(struct fman_mac *tgec, enum comm_mode mode); +-int tgec_init(struct fman_mac *tgec); +-int tgec_free(struct fman_mac *tgec); +-int tgec_accept_rx_pause_frames(struct fman_mac *tgec, bool en); +-int tgec_set_tx_pause_frames(struct fman_mac *tgec, u8 priority, +- u16 pause_time, u16 thresh_time); +-int tgec_set_exception(struct fman_mac *tgec, +- enum fman_mac_exceptions exception, bool enable); +-int tgec_add_hash_mac_address(struct fman_mac *tgec, enet_addr_t *eth_addr); +-int tgec_del_hash_mac_address(struct fman_mac *tgec, enet_addr_t *eth_addr); +-int tgec_get_version(struct fman_mac *tgec, u32 *mac_version); +- +-#endif /* __TGEC_H */ +diff --git a/drivers/net/ethernet/freescale/fman/mac.c b/drivers/net/ethernet/freescale/fman/mac.c +deleted file mode 100644 +index 736db9d..0000000 +--- a/drivers/net/ethernet/freescale/fman/mac.c ++++ /dev/null +@@ -1,950 +0,0 @@ +-/* Copyright 2008-2015 Freescale Semiconductor, Inc. +- * +- * Redistribution and use in source and binary forms, with or without +- * modification, are permitted provided that the following conditions are met: +- * * Redistributions of source code must retain the above copyright +- * notice, this list of conditions and the following disclaimer. +- * * Redistributions in binary form must reproduce the above copyright +- * notice, this list of conditions and the following disclaimer in the +- * documentation and/or other materials provided with the distribution. +- * * Neither the name of Freescale Semiconductor nor the +- * names of its contributors may be used to endorse or promote products +- * derived from this software without specific prior written permission. +- * +- * +- * ALTERNATIVELY, this software may be distributed under the terms of the +- * GNU General Public License ("GPL") as published by the Free Software +- * Foundation, either version 2 of that License or (at your option) any +- * later version. +- * +- * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY +- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +- * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY +- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +- */ +- +-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +- +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-#include "mac.h" +-#include "fman_mac.h" +-#include "fman_dtsec.h" +-#include "fman_tgec.h" +-#include "fman_memac.h" +- +-MODULE_LICENSE("Dual BSD/GPL"); +-MODULE_DESCRIPTION("FSL FMan MAC API based driver"); +- +-struct mac_priv_s { +- struct device *dev; +- void __iomem *vaddr; +- u8 cell_index; +- phy_interface_t phy_if; +- struct fman *fman; +- struct device_node *phy_node; +- struct device_node *internal_phy_node; +- /* List of multicast addresses */ +- struct list_head mc_addr_list; +- struct platform_device *eth_dev; +- struct fixed_phy_status *fixed_link; +- u16 speed; +- u16 max_speed; +- +- int (*enable)(struct fman_mac *mac_dev, enum comm_mode mode); +- int (*disable)(struct fman_mac *mac_dev, enum comm_mode mode); +-}; +- +-struct mac_address { +- u8 addr[ETH_ALEN]; +- struct list_head list; +-}; +- +-static void mac_exception(void *handle, enum fman_mac_exceptions ex) +-{ +- struct mac_device *mac_dev; +- struct mac_priv_s *priv; +- +- mac_dev = handle; +- priv = mac_dev->priv; +- +- if (ex == FM_MAC_EX_10G_RX_FIFO_OVFL) { +- /* don't flag RX FIFO after the first */ +- mac_dev->set_exception(mac_dev->fman_mac, +- FM_MAC_EX_10G_RX_FIFO_OVFL, false); +- dev_err(priv->dev, "10G MAC got RX FIFO Error = %x\n", ex); +- } +- +- dev_dbg(priv->dev, "%s:%s() -> %d\n", KBUILD_BASENAME ".c", +- __func__, ex); +-} +- +-static void set_fman_mac_params(struct mac_device *mac_dev, +- struct fman_mac_params *params) +-{ +- struct mac_priv_s *priv = mac_dev->priv; +- +- params->base_addr = (typeof(params->base_addr)) +- devm_ioremap(priv->dev, mac_dev->res->start, +- resource_size(mac_dev->res)); +- memcpy(¶ms->addr, mac_dev->addr, sizeof(mac_dev->addr)); +- params->max_speed = priv->max_speed; +- params->phy_if = priv->phy_if; +- params->basex_if = false; +- params->mac_id = priv->cell_index; +- params->fm = (void *)priv->fman; +- params->exception_cb = mac_exception; +- params->event_cb = mac_exception; +- params->dev_id = mac_dev; +- params->internal_phy_node = priv->internal_phy_node; +-} +- +-static int tgec_initialization(struct mac_device *mac_dev) +-{ +- int err; +- struct mac_priv_s *priv; +- struct fman_mac_params params; +- u32 version; +- +- priv = mac_dev->priv; +- +- set_fman_mac_params(mac_dev, ¶ms); +- +- mac_dev->fman_mac = tgec_config(¶ms); +- if (!mac_dev->fman_mac) { +- err = -EINVAL; +- goto _return; +- } +- +- err = tgec_cfg_max_frame_len(mac_dev->fman_mac, fman_get_max_frm()); +- if (err < 0) +- goto _return_fm_mac_free; +- +- err = tgec_init(mac_dev->fman_mac); +- if (err < 0) +- goto _return_fm_mac_free; +- +- /* For 10G MAC, disable Tx ECC exception */ +- err = mac_dev->set_exception(mac_dev->fman_mac, +- FM_MAC_EX_10G_TX_ECC_ER, false); +- if (err < 0) +- goto _return_fm_mac_free; +- +- err = tgec_get_version(mac_dev->fman_mac, &version); +- if (err < 0) +- goto _return_fm_mac_free; +- +- dev_info(priv->dev, "FMan XGEC version: 0x%08x\n", version); +- +- goto _return; +- +-_return_fm_mac_free: +- tgec_free(mac_dev->fman_mac); +- +-_return: +- return err; +-} +- +-static int dtsec_initialization(struct mac_device *mac_dev) +-{ +- int err; +- struct mac_priv_s *priv; +- struct fman_mac_params params; +- u32 version; +- +- priv = mac_dev->priv; +- +- set_fman_mac_params(mac_dev, ¶ms); +- +- mac_dev->fman_mac = dtsec_config(¶ms); +- if (!mac_dev->fman_mac) { +- err = -EINVAL; +- goto _return; +- } +- +- err = dtsec_cfg_max_frame_len(mac_dev->fman_mac, fman_get_max_frm()); +- if (err < 0) +- goto _return_fm_mac_free; +- +- err = dtsec_cfg_pad_and_crc(mac_dev->fman_mac, true); +- if (err < 0) +- goto _return_fm_mac_free; +- +- err = dtsec_init(mac_dev->fman_mac); +- if (err < 0) +- goto _return_fm_mac_free; +- +- /* For 1G MAC, disable by default the MIB counters overflow interrupt */ +- err = mac_dev->set_exception(mac_dev->fman_mac, +- FM_MAC_EX_1G_RX_MIB_CNT_OVFL, false); +- if (err < 0) +- goto _return_fm_mac_free; +- +- err = dtsec_get_version(mac_dev->fman_mac, &version); +- if (err < 0) +- goto _return_fm_mac_free; +- +- dev_info(priv->dev, "FMan dTSEC version: 0x%08x\n", version); +- +- goto _return; +- +-_return_fm_mac_free: +- dtsec_free(mac_dev->fman_mac); +- +-_return: +- return err; +-} +- +-static int memac_initialization(struct mac_device *mac_dev) +-{ +- int err; +- struct mac_priv_s *priv; +- struct fman_mac_params params; +- +- priv = mac_dev->priv; +- +- set_fman_mac_params(mac_dev, ¶ms); +- +- if (priv->max_speed == SPEED_10000) +- params.phy_if = PHY_INTERFACE_MODE_XGMII; +- +- mac_dev->fman_mac = memac_config(¶ms); +- if (!mac_dev->fman_mac) { +- err = -EINVAL; +- goto _return; +- } +- +- err = memac_cfg_max_frame_len(mac_dev->fman_mac, fman_get_max_frm()); +- if (err < 0) +- goto _return_fm_mac_free; +- +- err = memac_cfg_reset_on_init(mac_dev->fman_mac, true); +- if (err < 0) +- goto _return_fm_mac_free; +- +- err = memac_cfg_fixed_link(mac_dev->fman_mac, priv->fixed_link); +- if (err < 0) +- goto _return_fm_mac_free; +- +- err = memac_init(mac_dev->fman_mac); +- if (err < 0) +- goto _return_fm_mac_free; +- +- dev_info(priv->dev, "FMan MEMAC\n"); +- +- goto _return; +- +-_return_fm_mac_free: +- memac_free(mac_dev->fman_mac); +- +-_return: +- return err; +-} +- +-static int start(struct mac_device *mac_dev) +-{ +- int err; +- struct phy_device *phy_dev = mac_dev->phy_dev; +- struct mac_priv_s *priv = mac_dev->priv; +- +- err = priv->enable(mac_dev->fman_mac, COMM_MODE_RX_AND_TX); +- if (!err && phy_dev) +- phy_start(phy_dev); +- +- return err; +-} +- +-static int stop(struct mac_device *mac_dev) +-{ +- struct mac_priv_s *priv = mac_dev->priv; +- +- if (mac_dev->phy_dev) +- phy_stop(mac_dev->phy_dev); +- +- return priv->disable(mac_dev->fman_mac, COMM_MODE_RX_AND_TX); +-} +- +-static int set_multi(struct net_device *net_dev, struct mac_device *mac_dev) +-{ +- struct mac_priv_s *priv; +- struct mac_address *old_addr, *tmp; +- struct netdev_hw_addr *ha; +- int err; +- enet_addr_t *addr; +- +- priv = mac_dev->priv; +- +- /* Clear previous address list */ +- list_for_each_entry_safe(old_addr, tmp, &priv->mc_addr_list, list) { +- addr = (enet_addr_t *)old_addr->addr; +- err = mac_dev->remove_hash_mac_addr(mac_dev->fman_mac, addr); +- if (err < 0) +- return err; +- +- list_del(&old_addr->list); +- kfree(old_addr); +- } +- +- /* Add all the addresses from the new list */ +- netdev_for_each_mc_addr(ha, net_dev) { +- addr = (enet_addr_t *)ha->addr; +- err = mac_dev->add_hash_mac_addr(mac_dev->fman_mac, addr); +- if (err < 0) +- return err; +- +- tmp = kmalloc(sizeof(*tmp), GFP_ATOMIC); +- if (!tmp) +- return -ENOMEM; +- +- ether_addr_copy(tmp->addr, ha->addr); +- list_add(&tmp->list, &priv->mc_addr_list); +- } +- return 0; +-} +- +-/** +- * fman_set_mac_active_pause +- * @mac_dev: A pointer to the MAC device +- * @rx: Pause frame setting for RX +- * @tx: Pause frame setting for TX +- * +- * Set the MAC RX/TX PAUSE frames settings +- * +- * Avoid redundant calls to FMD, if the MAC driver already contains the desired +- * active PAUSE settings. Otherwise, the new active settings should be reflected +- * in FMan. +- * +- * Return: 0 on success; Error code otherwise. +- */ +-int fman_set_mac_active_pause(struct mac_device *mac_dev, bool rx, bool tx) +-{ +- struct fman_mac *fman_mac = mac_dev->fman_mac; +- int err = 0; +- +- if (rx != mac_dev->rx_pause_active) { +- err = mac_dev->set_rx_pause(fman_mac, rx); +- if (likely(err == 0)) +- mac_dev->rx_pause_active = rx; +- } +- +- if (tx != mac_dev->tx_pause_active) { +- u16 pause_time = (tx ? FSL_FM_PAUSE_TIME_ENABLE : +- FSL_FM_PAUSE_TIME_DISABLE); +- +- err = mac_dev->set_tx_pause(fman_mac, 0, pause_time, 0); +- +- if (likely(err == 0)) +- mac_dev->tx_pause_active = tx; +- } +- +- return err; +-} +-EXPORT_SYMBOL(fman_set_mac_active_pause); +- +-/** +- * fman_get_pause_cfg +- * @mac_dev: A pointer to the MAC device +- * @rx: Return value for RX setting +- * @tx: Return value for TX setting +- * +- * Determine the MAC RX/TX PAUSE frames settings based on PHY +- * autonegotiation or values set by eththool. +- * +- * Return: Pointer to FMan device. +- */ +-void fman_get_pause_cfg(struct mac_device *mac_dev, bool *rx_pause, +- bool *tx_pause) +-{ +- struct phy_device *phy_dev = mac_dev->phy_dev; +- u16 lcl_adv, rmt_adv; +- u8 flowctrl; +- +- *rx_pause = *tx_pause = false; +- +- if (!phy_dev->duplex) +- return; +- +- /* If PAUSE autonegotiation is disabled, the TX/RX PAUSE settings +- * are those set by ethtool. +- */ +- if (!mac_dev->autoneg_pause) { +- *rx_pause = mac_dev->rx_pause_req; +- *tx_pause = mac_dev->tx_pause_req; +- return; +- } +- +- /* Else if PAUSE autonegotiation is enabled, the TX/RX PAUSE +- * settings depend on the result of the link negotiation. +- */ +- +- /* get local capabilities */ +- lcl_adv = 0; +- if (phy_dev->advertising & ADVERTISED_Pause) +- lcl_adv |= ADVERTISE_PAUSE_CAP; +- if (phy_dev->advertising & ADVERTISED_Asym_Pause) +- lcl_adv |= ADVERTISE_PAUSE_ASYM; +- +- /* get link partner capabilities */ +- rmt_adv = 0; +- if (phy_dev->pause) +- rmt_adv |= LPA_PAUSE_CAP; +- if (phy_dev->asym_pause) +- rmt_adv |= LPA_PAUSE_ASYM; +- +- /* Calculate TX/RX settings based on local and peer advertised +- * symmetric/asymmetric PAUSE capabilities. +- */ +- flowctrl = mii_resolve_flowctrl_fdx(lcl_adv, rmt_adv); +- if (flowctrl & FLOW_CTRL_RX) +- *rx_pause = true; +- if (flowctrl & FLOW_CTRL_TX) +- *tx_pause = true; +-} +-EXPORT_SYMBOL(fman_get_pause_cfg); +- +-static void adjust_link_void(struct net_device *net_dev) +-{ +-} +- +-static void adjust_link_dtsec(struct net_device *net_dev) +-{ +- struct device *dev = net_dev->dev.parent; +- struct dpaa_eth_data *eth_data = dev->platform_data; +- struct mac_device *mac_dev = eth_data->mac_dev; +- struct phy_device *phy_dev = mac_dev->phy_dev; +- struct fman_mac *fman_mac; +- bool rx_pause, tx_pause; +- int err; +- +- fman_mac = mac_dev->fman_mac; +- if (!phy_dev->link) { +- dtsec_restart_autoneg(fman_mac); +- +- return; +- } +- +- dtsec_adjust_link(fman_mac, phy_dev->speed); +- fman_get_pause_cfg(mac_dev, &rx_pause, &tx_pause); +- err = fman_set_mac_active_pause(mac_dev, rx_pause, tx_pause); +- if (err < 0) +- netdev_err(net_dev, "fman_set_mac_active_pause() = %d\n", err); +-} +- +-static void adjust_link_memac(struct net_device *net_dev) +-{ +- struct device *dev = net_dev->dev.parent; +- struct dpaa_eth_data *eth_data = dev->platform_data; +- struct mac_device *mac_dev = eth_data->mac_dev; +- struct phy_device *phy_dev = mac_dev->phy_dev; +- struct fman_mac *fman_mac; +- bool rx_pause, tx_pause; +- int err; +- +- fman_mac = mac_dev->fman_mac; +- memac_adjust_link(fman_mac, phy_dev->speed); +- +- fman_get_pause_cfg(mac_dev, &rx_pause, &tx_pause); +- err = fman_set_mac_active_pause(mac_dev, rx_pause, tx_pause); +- if (err < 0) +- netdev_err(net_dev, "fman_set_mac_active_pause() = %d\n", err); +-} +- +-/* Initializes driver's PHY state, and attaches to the PHY. +- * Returns 0 on success. +- */ +-static struct phy_device *init_phy(struct net_device *net_dev, +- struct mac_device *mac_dev, +- void (*adj_lnk)(struct net_device *)) +-{ +- struct phy_device *phy_dev; +- struct mac_priv_s *priv = mac_dev->priv; +- +- phy_dev = of_phy_connect(net_dev, priv->phy_node, adj_lnk, 0, +- priv->phy_if); +- if (!phy_dev) { +- netdev_err(net_dev, "Could not connect to PHY\n"); +- return NULL; +- } +- +- /* Remove any features not supported by the controller */ +- phy_dev->supported &= mac_dev->if_support; +- /* Enable the symmetric and asymmetric PAUSE frame advertisements, +- * as most of the PHY drivers do not enable them by default. +- */ +- phy_dev->supported |= (SUPPORTED_Pause | SUPPORTED_Asym_Pause); +- phy_dev->advertising = phy_dev->supported; +- +- mac_dev->phy_dev = phy_dev; +- +- return phy_dev; +-} +- +-static struct phy_device *dtsec_init_phy(struct net_device *net_dev, +- struct mac_device *mac_dev) +-{ +- return init_phy(net_dev, mac_dev, &adjust_link_dtsec); +-} +- +-static struct phy_device *tgec_init_phy(struct net_device *net_dev, +- struct mac_device *mac_dev) +-{ +- return init_phy(net_dev, mac_dev, adjust_link_void); +-} +- +-static struct phy_device *memac_init_phy(struct net_device *net_dev, +- struct mac_device *mac_dev) +-{ +- return init_phy(net_dev, mac_dev, &adjust_link_memac); +-} +- +-static void setup_dtsec(struct mac_device *mac_dev) +-{ +- mac_dev->init_phy = dtsec_init_phy; +- mac_dev->init = dtsec_initialization; +- mac_dev->set_promisc = dtsec_set_promiscuous; +- mac_dev->change_addr = dtsec_modify_mac_address; +- mac_dev->add_hash_mac_addr = dtsec_add_hash_mac_address; +- mac_dev->remove_hash_mac_addr = dtsec_del_hash_mac_address; +- mac_dev->set_tx_pause = dtsec_set_tx_pause_frames; +- mac_dev->set_rx_pause = dtsec_accept_rx_pause_frames; +- mac_dev->set_exception = dtsec_set_exception; +- mac_dev->set_multi = set_multi; +- mac_dev->start = start; +- mac_dev->stop = stop; +- +- mac_dev->priv->enable = dtsec_enable; +- mac_dev->priv->disable = dtsec_disable; +-} +- +-static void setup_tgec(struct mac_device *mac_dev) +-{ +- mac_dev->init_phy = tgec_init_phy; +- mac_dev->init = tgec_initialization; +- mac_dev->set_promisc = tgec_set_promiscuous; +- mac_dev->change_addr = tgec_modify_mac_address; +- mac_dev->add_hash_mac_addr = tgec_add_hash_mac_address; +- mac_dev->remove_hash_mac_addr = tgec_del_hash_mac_address; +- mac_dev->set_tx_pause = tgec_set_tx_pause_frames; +- mac_dev->set_rx_pause = tgec_accept_rx_pause_frames; +- mac_dev->set_exception = tgec_set_exception; +- mac_dev->set_multi = set_multi; +- mac_dev->start = start; +- mac_dev->stop = stop; +- +- mac_dev->priv->enable = tgec_enable; +- mac_dev->priv->disable = tgec_disable; +-} +- +-static void setup_memac(struct mac_device *mac_dev) +-{ +- mac_dev->init_phy = memac_init_phy; +- mac_dev->init = memac_initialization; +- mac_dev->set_promisc = memac_set_promiscuous; +- mac_dev->change_addr = memac_modify_mac_address; +- mac_dev->add_hash_mac_addr = memac_add_hash_mac_address; +- mac_dev->remove_hash_mac_addr = memac_del_hash_mac_address; +- mac_dev->set_tx_pause = memac_set_tx_pause_frames; +- mac_dev->set_rx_pause = memac_accept_rx_pause_frames; +- mac_dev->set_exception = memac_set_exception; +- mac_dev->set_multi = set_multi; +- mac_dev->start = start; +- mac_dev->stop = stop; +- +- mac_dev->priv->enable = memac_enable; +- mac_dev->priv->disable = memac_disable; +-} +- +-#define DTSEC_SUPPORTED \ +- (SUPPORTED_10baseT_Half \ +- | SUPPORTED_10baseT_Full \ +- | SUPPORTED_100baseT_Half \ +- | SUPPORTED_100baseT_Full \ +- | SUPPORTED_Autoneg \ +- | SUPPORTED_Pause \ +- | SUPPORTED_Asym_Pause \ +- | SUPPORTED_MII) +- +-static DEFINE_MUTEX(eth_lock); +- +-static const u16 phy2speed[] = { +- [PHY_INTERFACE_MODE_MII] = SPEED_100, +- [PHY_INTERFACE_MODE_GMII] = SPEED_1000, +- [PHY_INTERFACE_MODE_SGMII] = SPEED_1000, +- [PHY_INTERFACE_MODE_TBI] = SPEED_1000, +- [PHY_INTERFACE_MODE_RMII] = SPEED_100, +- [PHY_INTERFACE_MODE_RGMII] = SPEED_1000, +- [PHY_INTERFACE_MODE_RGMII_ID] = SPEED_1000, +- [PHY_INTERFACE_MODE_RGMII_RXID] = SPEED_1000, +- [PHY_INTERFACE_MODE_RGMII_TXID] = SPEED_1000, +- [PHY_INTERFACE_MODE_RTBI] = SPEED_1000, +- [PHY_INTERFACE_MODE_XGMII] = SPEED_10000 +-}; +- +-static struct platform_device *dpaa_eth_add_device(int fman_id, +- struct mac_device *mac_dev, +- struct device_node *node) +-{ +- struct platform_device *pdev; +- struct dpaa_eth_data data; +- struct mac_priv_s *priv; +- static int dpaa_eth_dev_cnt; +- int ret; +- +- priv = mac_dev->priv; +- +- data.mac_dev = mac_dev; +- data.mac_hw_id = priv->cell_index; +- data.fman_hw_id = fman_id; +- data.mac_node = node; +- +- mutex_lock(ð_lock); +- +- pdev = platform_device_alloc("dpaa-ethernet", dpaa_eth_dev_cnt); +- if (!pdev) { +- ret = -ENOMEM; +- goto no_mem; +- } +- +- ret = platform_device_add_data(pdev, &data, sizeof(data)); +- if (ret) +- goto err; +- +- ret = platform_device_add(pdev); +- if (ret) +- goto err; +- +- dpaa_eth_dev_cnt++; +- mutex_unlock(ð_lock); +- +- return pdev; +- +-err: +- platform_device_put(pdev); +-no_mem: +- mutex_unlock(ð_lock); +- +- return ERR_PTR(ret); +-} +- +-static const struct of_device_id mac_match[] = { +- { .compatible = "fsl,fman-dtsec" }, +- { .compatible = "fsl,fman-xgec" }, +- { .compatible = "fsl,fman-memac" }, +- {} +-}; +-MODULE_DEVICE_TABLE(of, mac_match); +- +-static int mac_probe(struct platform_device *_of_dev) +-{ +- int err, i, nph; +- struct device *dev; +- struct device_node *mac_node, *dev_node; +- struct mac_device *mac_dev; +- struct platform_device *of_dev; +- struct resource res; +- struct mac_priv_s *priv; +- const u8 *mac_addr; +- u32 val; +- u8 fman_id; +- int phy_if; +- +- dev = &_of_dev->dev; +- mac_node = dev->of_node; +- +- mac_dev = devm_kzalloc(dev, sizeof(*mac_dev), GFP_KERNEL); +- if (!mac_dev) { +- err = -ENOMEM; +- dev_err(dev, "devm_kzalloc() = %d\n", err); +- goto _return; +- } +- priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); +- if (!priv) { +- err = -ENOMEM; +- goto _return; +- } +- +- /* Save private information */ +- mac_dev->priv = priv; +- priv->dev = dev; +- +- if (of_device_is_compatible(mac_node, "fsl,fman-dtsec")) { +- setup_dtsec(mac_dev); +- priv->internal_phy_node = of_parse_phandle(mac_node, +- "tbi-handle", 0); +- } else if (of_device_is_compatible(mac_node, "fsl,fman-xgec")) { +- setup_tgec(mac_dev); +- } else if (of_device_is_compatible(mac_node, "fsl,fman-memac")) { +- setup_memac(mac_dev); +- priv->internal_phy_node = of_parse_phandle(mac_node, +- "pcsphy-handle", 0); +- } else { +- dev_err(dev, "MAC node (%s) contains unsupported MAC\n", +- mac_node->full_name); +- err = -EINVAL; +- goto _return; +- } +- +- /* Register mac_dev */ +- dev_set_drvdata(dev, mac_dev); +- +- INIT_LIST_HEAD(&priv->mc_addr_list); +- +- /* Get the FM node */ +- dev_node = of_get_parent(mac_node); +- if (!dev_node) { +- dev_err(dev, "of_get_parent(%s) failed\n", +- mac_node->full_name); +- err = -EINVAL; +- goto _return_dev_set_drvdata; +- } +- +- of_dev = of_find_device_by_node(dev_node); +- if (!of_dev) { +- dev_err(dev, "of_find_device_by_node(%s) failed\n", +- dev_node->full_name); +- err = -EINVAL; +- goto _return_of_node_put; +- } +- +- /* Get the FMan cell-index */ +- err = of_property_read_u32(dev_node, "cell-index", &val); +- if (err) { +- dev_err(dev, "failed to read cell-index for %s\n", +- dev_node->full_name); +- err = -EINVAL; +- goto _return_of_node_put; +- } +- /* cell-index 0 => FMan id 1 */ +- fman_id = (u8)(val + 1); +- +- priv->fman = fman_bind(&of_dev->dev); +- if (!priv->fman) { +- dev_err(dev, "fman_bind(%s) failed\n", dev_node->full_name); +- err = -ENODEV; +- goto _return_of_node_put; +- } +- +- of_node_put(dev_node); +- +- /* Get the address of the memory mapped registers */ +- err = of_address_to_resource(mac_node, 0, &res); +- if (err < 0) { +- dev_err(dev, "of_address_to_resource(%s) = %d\n", +- mac_node->full_name, err); +- goto _return_dev_set_drvdata; +- } +- +- mac_dev->res = __devm_request_region(dev, +- fman_get_mem_region(priv->fman), +- res.start, res.end + 1 - res.start, +- "mac"); +- if (!mac_dev->res) { +- dev_err(dev, "__devm_request_mem_region(mac) failed\n"); +- err = -EBUSY; +- goto _return_dev_set_drvdata; +- } +- +- priv->vaddr = devm_ioremap(dev, mac_dev->res->start, +- mac_dev->res->end + 1 - mac_dev->res->start); +- if (!priv->vaddr) { +- dev_err(dev, "devm_ioremap() failed\n"); +- err = -EIO; +- goto _return_dev_set_drvdata; +- } +- +- if (!of_device_is_available(mac_node)) { +- devm_iounmap(dev, priv->vaddr); +- __devm_release_region(dev, fman_get_mem_region(priv->fman), +- res.start, res.end + 1 - res.start); +- devm_kfree(dev, mac_dev); +- dev_set_drvdata(dev, NULL); +- return -ENODEV; +- } +- +- /* Get the cell-index */ +- err = of_property_read_u32(mac_node, "cell-index", &val); +- if (err) { +- dev_err(dev, "failed to read cell-index for %s\n", +- mac_node->full_name); +- err = -EINVAL; +- goto _return_dev_set_drvdata; +- } +- priv->cell_index = (u8)val; +- +- /* Get the MAC address */ +- mac_addr = of_get_mac_address(mac_node); +- if (!mac_addr) { +- dev_err(dev, "of_get_mac_address(%s) failed\n", +- mac_node->full_name); +- err = -EINVAL; +- goto _return_dev_set_drvdata; +- } +- memcpy(mac_dev->addr, mac_addr, sizeof(mac_dev->addr)); +- +- /* Get the port handles */ +- nph = of_count_phandle_with_args(mac_node, "fsl,fman-ports", NULL); +- if (unlikely(nph < 0)) { +- dev_err(dev, "of_count_phandle_with_args(%s, fsl,fman-ports) failed\n", +- mac_node->full_name); +- err = nph; +- goto _return_dev_set_drvdata; +- } +- +- if (nph != ARRAY_SIZE(mac_dev->port)) { +- dev_err(dev, "Not supported number of fman-ports handles of mac node %s from device tree\n", +- mac_node->full_name); +- err = -EINVAL; +- goto _return_dev_set_drvdata; +- } +- +- for (i = 0; i < ARRAY_SIZE(mac_dev->port); i++) { +- /* Find the port node */ +- dev_node = of_parse_phandle(mac_node, "fsl,fman-ports", i); +- if (!dev_node) { +- dev_err(dev, "of_parse_phandle(%s, fsl,fman-ports) failed\n", +- mac_node->full_name); +- err = -EINVAL; +- goto _return_of_node_put; +- } +- +- of_dev = of_find_device_by_node(dev_node); +- if (!of_dev) { +- dev_err(dev, "of_find_device_by_node(%s) failed\n", +- dev_node->full_name); +- err = -EINVAL; +- goto _return_of_node_put; +- } +- +- mac_dev->port[i] = fman_port_bind(&of_dev->dev); +- if (!mac_dev->port[i]) { +- dev_err(dev, "dev_get_drvdata(%s) failed\n", +- dev_node->full_name); +- err = -EINVAL; +- goto _return_of_node_put; +- } +- of_node_put(dev_node); +- } +- +- /* Get the PHY connection type */ +- phy_if = of_get_phy_mode(mac_node); +- if (phy_if < 0) { +- dev_warn(dev, +- "of_get_phy_mode() for %s failed. Defaulting to SGMII\n", +- mac_node->full_name); +- phy_if = PHY_INTERFACE_MODE_SGMII; +- } +- priv->phy_if = phy_if; +- +- priv->speed = phy2speed[priv->phy_if]; +- priv->max_speed = priv->speed; +- mac_dev->if_support = DTSEC_SUPPORTED; +- /* We don't support half-duplex in SGMII mode */ +- if (priv->phy_if == PHY_INTERFACE_MODE_SGMII) +- mac_dev->if_support &= ~(SUPPORTED_10baseT_Half | +- SUPPORTED_100baseT_Half); +- +- /* Gigabit support (no half-duplex) */ +- if (priv->max_speed == 1000) +- mac_dev->if_support |= SUPPORTED_1000baseT_Full; +- +- /* The 10G interface only supports one mode */ +- if (priv->phy_if == PHY_INTERFACE_MODE_XGMII) +- mac_dev->if_support = SUPPORTED_10000baseT_Full; +- +- /* Get the rest of the PHY information */ +- priv->phy_node = of_parse_phandle(mac_node, "phy-handle", 0); +- if (!priv->phy_node && of_phy_is_fixed_link(mac_node)) { +- struct phy_device *phy; +- +- err = of_phy_register_fixed_link(mac_node); +- if (err) +- goto _return_dev_set_drvdata; +- +- priv->fixed_link = kzalloc(sizeof(*priv->fixed_link), +- GFP_KERNEL); +- if (!priv->fixed_link) +- goto _return_dev_set_drvdata; +- +- priv->phy_node = of_node_get(mac_node); +- phy = of_phy_find_device(priv->phy_node); +- if (!phy) +- goto _return_dev_set_drvdata; +- +- priv->fixed_link->link = phy->link; +- priv->fixed_link->speed = phy->speed; +- priv->fixed_link->duplex = phy->duplex; +- priv->fixed_link->pause = phy->pause; +- priv->fixed_link->asym_pause = phy->asym_pause; +- +- put_device(&phy->mdio.dev); +- } +- +- err = mac_dev->init(mac_dev); +- if (err < 0) { +- dev_err(dev, "mac_dev->init() = %d\n", err); +- of_node_put(priv->phy_node); +- goto _return_dev_set_drvdata; +- } +- +- /* pause frame autonegotiation enabled */ +- mac_dev->autoneg_pause = true; +- +- /* By intializing the values to false, force FMD to enable PAUSE frames +- * on RX and TX +- */ +- mac_dev->rx_pause_req = true; +- mac_dev->tx_pause_req = true; +- mac_dev->rx_pause_active = false; +- mac_dev->tx_pause_active = false; +- err = fman_set_mac_active_pause(mac_dev, true, true); +- if (err < 0) +- dev_err(dev, "fman_set_mac_active_pause() = %d\n", err); +- +- dev_info(dev, "FMan MAC address: %02hx:%02hx:%02hx:%02hx:%02hx:%02hx\n", +- mac_dev->addr[0], mac_dev->addr[1], mac_dev->addr[2], +- mac_dev->addr[3], mac_dev->addr[4], mac_dev->addr[5]); +- +- priv->eth_dev = dpaa_eth_add_device(fman_id, mac_dev, mac_node); +- if (IS_ERR(priv->eth_dev)) { +- dev_err(dev, "failed to add Ethernet platform device for MAC %d\n", +- priv->cell_index); +- priv->eth_dev = NULL; +- } +- +- goto _return; +- +-_return_of_node_put: +- of_node_put(dev_node); +-_return_dev_set_drvdata: +- kfree(priv->fixed_link); +- dev_set_drvdata(dev, NULL); +-_return: +- return err; +-} +- +-static struct platform_driver mac_driver = { +- .driver = { +- .name = KBUILD_MODNAME, +- .of_match_table = mac_match, +- }, +- .probe = mac_probe, +-}; +- +-builtin_platform_driver(mac_driver); +diff --git a/drivers/net/ethernet/freescale/fman/mac.h b/drivers/net/ethernet/freescale/fman/mac.h +deleted file mode 100644 +index d7313f0..0000000 +--- a/drivers/net/ethernet/freescale/fman/mac.h ++++ /dev/null +@@ -1,98 +0,0 @@ +-/* Copyright 2008-2015 Freescale Semiconductor, Inc. +- * +- * Redistribution and use in source and binary forms, with or without +- * modification, are permitted provided that the following conditions are met: +- * * Redistributions of source code must retain the above copyright +- * notice, this list of conditions and the following disclaimer. +- * * Redistributions in binary form must reproduce the above copyright +- * notice, this list of conditions and the following disclaimer in the +- * documentation and/or other materials provided with the distribution. +- * * Neither the name of Freescale Semiconductor nor the +- * names of its contributors may be used to endorse or promote products +- * derived from this software without specific prior written permission. +- * +- * +- * ALTERNATIVELY, this software may be distributed under the terms of the +- * GNU General Public License ("GPL") as published by the Free Software +- * Foundation, either version 2 of that License or (at your option) any +- * later version. +- * +- * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY +- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +- * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY +- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +- */ +- +-#ifndef __MAC_H +-#define __MAC_H +- +-#include +-#include +-#include +-#include +- +-#include "fman_port.h" +-#include "fman.h" +-#include "fman_mac.h" +- +-struct fman_mac; +-struct mac_priv_s; +- +-struct mac_device { +- struct resource *res; +- u8 addr[ETH_ALEN]; +- struct fman_port *port[2]; +- u32 if_support; +- struct phy_device *phy_dev; +- +- bool autoneg_pause; +- bool rx_pause_req; +- bool tx_pause_req; +- bool rx_pause_active; +- bool tx_pause_active; +- bool promisc; +- +- struct phy_device *(*init_phy)(struct net_device *net_dev, +- struct mac_device *mac_dev); +- int (*init)(struct mac_device *mac_dev); +- int (*start)(struct mac_device *mac_dev); +- int (*stop)(struct mac_device *mac_dev); +- int (*set_promisc)(struct fman_mac *mac_dev, bool enable); +- int (*change_addr)(struct fman_mac *mac_dev, enet_addr_t *enet_addr); +- int (*set_multi)(struct net_device *net_dev, +- struct mac_device *mac_dev); +- int (*set_rx_pause)(struct fman_mac *mac_dev, bool en); +- int (*set_tx_pause)(struct fman_mac *mac_dev, u8 priority, +- u16 pause_time, u16 thresh_time); +- int (*set_exception)(struct fman_mac *mac_dev, +- enum fman_mac_exceptions exception, bool enable); +- int (*add_hash_mac_addr)(struct fman_mac *mac_dev, +- enet_addr_t *eth_addr); +- int (*remove_hash_mac_addr)(struct fman_mac *mac_dev, +- enet_addr_t *eth_addr); +- +- struct fman_mac *fman_mac; +- struct mac_priv_s *priv; +-}; +- +-struct dpaa_eth_data { +- struct device_node *mac_node; +- struct mac_device *mac_dev; +- int mac_hw_id; +- int fman_hw_id; +-}; +- +-extern const char *mac_driver_description; +- +-int fman_set_mac_active_pause(struct mac_device *mac_dev, bool rx, bool tx); +- +-void fman_get_pause_cfg(struct mac_device *mac_dev, bool *rx_pause, +- bool *tx_pause); +- +-#endif /* __MAC_H */ +diff --git a/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c b/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c +index 4b86260..9b3639e 100644 +--- a/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c ++++ b/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c +@@ -60,9 +60,6 @@ module_param(fs_enet_debug, int, 0); + MODULE_PARM_DESC(fs_enet_debug, + "Freescale bitmapped debugging message enable value"); + +-#define RX_RING_SIZE 32 +-#define TX_RING_SIZE 64 +- + #ifdef CONFIG_NET_POLL_CONTROLLER + static void fs_enet_netpoll(struct net_device *dev); + #endif +@@ -82,113 +79,20 @@ static void skb_align(struct sk_buff *skb, int align) + skb_reserve(skb, align - off); + } + +-/* NAPI function */ +-static int fs_enet_napi(struct napi_struct *napi, int budget) ++/* NAPI receive function */ ++static int fs_enet_rx_napi(struct napi_struct *napi, int budget) + { + struct fs_enet_private *fep = container_of(napi, struct fs_enet_private, napi); + struct net_device *dev = fep->ndev; + const struct fs_platform_info *fpi = fep->fpi; + cbd_t __iomem *bdp; +- struct sk_buff *skb, *skbn; ++ struct sk_buff *skb, *skbn, *skbt; + int received = 0; + u16 pkt_len, sc; + int curidx; +- int dirtyidx, do_wake, do_restart; +- int tx_left = TX_RING_SIZE; +- +- spin_lock(&fep->tx_lock); +- bdp = fep->dirty_tx; +- +- /* clear status bits for napi*/ +- (*fep->ops->napi_clear_event)(dev); +- +- do_wake = do_restart = 0; +- while (((sc = CBDR_SC(bdp)) & BD_ENET_TX_READY) == 0 && tx_left) { +- dirtyidx = bdp - fep->tx_bd_base; +- +- if (fep->tx_free == fep->tx_ring) +- break; +- +- skb = fep->tx_skbuff[dirtyidx]; +- +- /* +- * Check for errors. +- */ +- if (sc & (BD_ENET_TX_HB | BD_ENET_TX_LC | +- BD_ENET_TX_RL | BD_ENET_TX_UN | BD_ENET_TX_CSL)) { +- +- if (sc & BD_ENET_TX_HB) /* No heartbeat */ +- fep->stats.tx_heartbeat_errors++; +- if (sc & BD_ENET_TX_LC) /* Late collision */ +- fep->stats.tx_window_errors++; +- if (sc & BD_ENET_TX_RL) /* Retrans limit */ +- fep->stats.tx_aborted_errors++; +- if (sc & BD_ENET_TX_UN) /* Underrun */ +- fep->stats.tx_fifo_errors++; +- if (sc & BD_ENET_TX_CSL) /* Carrier lost */ +- fep->stats.tx_carrier_errors++; +- +- if (sc & (BD_ENET_TX_LC | BD_ENET_TX_RL | BD_ENET_TX_UN)) { +- fep->stats.tx_errors++; +- do_restart = 1; +- } +- } else +- fep->stats.tx_packets++; +- +- if (sc & BD_ENET_TX_READY) { +- dev_warn(fep->dev, +- "HEY! Enet xmit interrupt and TX_READY.\n"); +- } +- +- /* +- * Deferred means some collisions occurred during transmit, +- * but we eventually sent the packet OK. +- */ +- if (sc & BD_ENET_TX_DEF) +- fep->stats.collisions++; +- +- /* unmap */ +- if (fep->mapped_as_page[dirtyidx]) +- dma_unmap_page(fep->dev, CBDR_BUFADDR(bdp), +- CBDR_DATLEN(bdp), DMA_TO_DEVICE); +- else +- dma_unmap_single(fep->dev, CBDR_BUFADDR(bdp), +- CBDR_DATLEN(bdp), DMA_TO_DEVICE); + +- /* +- * Free the sk buffer associated with this last transmit. +- */ +- if (skb) { +- dev_kfree_skb(skb); +- fep->tx_skbuff[dirtyidx] = NULL; +- } +- +- /* +- * Update pointer to next buffer descriptor to be transmitted. +- */ +- if ((sc & BD_ENET_TX_WRAP) == 0) +- bdp++; +- else +- bdp = fep->tx_bd_base; +- +- /* +- * Since we have freed up a buffer, the ring is no longer +- * full. +- */ +- if (++fep->tx_free == MAX_SKB_FRAGS) +- do_wake = 1; +- tx_left--; +- } +- +- fep->dirty_tx = bdp; +- +- if (do_restart) +- (*fep->ops->tx_restart)(dev); +- +- spin_unlock(&fep->tx_lock); +- +- if (do_wake) +- netif_wake_queue(dev); ++ if (budget <= 0) ++ return received; + + /* + * First, grab all of the stats for the incoming packet. +@@ -196,8 +100,10 @@ static int fs_enet_napi(struct napi_struct *napi, int budget) + */ + bdp = fep->cur_rx; + +- while (((sc = CBDR_SC(bdp)) & BD_ENET_RX_EMPTY) == 0 && +- received < budget) { ++ /* clear RX status bits for napi*/ ++ (*fep->ops->napi_clear_rx_event)(dev); ++ ++ while (((sc = CBDR_SC(bdp)) & BD_ENET_RX_EMPTY) == 0) { + curidx = bdp - fep->rx_bd_base; + + /* +@@ -226,10 +132,21 @@ static int fs_enet_napi(struct napi_struct *napi, int budget) + if (sc & BD_ENET_RX_OV) + fep->stats.rx_crc_errors++; + +- skbn = fep->rx_skbuff[curidx]; ++ skb = fep->rx_skbuff[curidx]; ++ ++ dma_unmap_single(fep->dev, CBDR_BUFADDR(bdp), ++ L1_CACHE_ALIGN(PKT_MAXBUF_SIZE), ++ DMA_FROM_DEVICE); ++ ++ skbn = skb; ++ + } else { + skb = fep->rx_skbuff[curidx]; + ++ dma_unmap_single(fep->dev, CBDR_BUFADDR(bdp), ++ L1_CACHE_ALIGN(PKT_MAXBUF_SIZE), ++ DMA_FROM_DEVICE); ++ + /* + * Process the incoming frame. + */ +@@ -244,31 +161,16 @@ static int fs_enet_napi(struct napi_struct *napi, int budget) + skb_reserve(skbn, 2); /* align IP header */ + skb_copy_from_linear_data(skb, + skbn->data, pkt_len); +- swap(skb, skbn); +- dma_sync_single_for_cpu(fep->dev, +- CBDR_BUFADDR(bdp), +- L1_CACHE_ALIGN(pkt_len), +- DMA_FROM_DEVICE); ++ /* swap */ ++ skbt = skb; ++ skb = skbn; ++ skbn = skbt; + } + } else { + skbn = netdev_alloc_skb(dev, ENET_RX_FRSIZE); + +- if (skbn) { +- dma_addr_t dma; +- ++ if (skbn) + skb_align(skbn, ENET_RX_ALIGN); +- +- dma_unmap_single(fep->dev, +- CBDR_BUFADDR(bdp), +- L1_CACHE_ALIGN(PKT_MAXBUF_SIZE), +- DMA_FROM_DEVICE); +- +- dma = dma_map_single(fep->dev, +- skbn->data, +- L1_CACHE_ALIGN(PKT_MAXBUF_SIZE), +- DMA_FROM_DEVICE); +- CBDW_BUFADDR(bdp, dma); +- } + } + + if (skbn != NULL) { +@@ -283,6 +185,9 @@ static int fs_enet_napi(struct napi_struct *napi, int budget) + } + + fep->rx_skbuff[curidx] = skbn; ++ CBDW_BUFADDR(bdp, dma_map_single(fep->dev, skbn->data, ++ L1_CACHE_ALIGN(PKT_MAXBUF_SIZE), ++ DMA_FROM_DEVICE)); + CBDW_DATLEN(bdp, 0); + CBDW_SC(bdp, (sc & ~BD_ENET_RX_STATS) | BD_ENET_RX_EMPTY); + +@@ -295,19 +200,134 @@ static int fs_enet_napi(struct napi_struct *napi, int budget) + bdp = fep->rx_bd_base; + + (*fep->ops->rx_bd_done)(dev); ++ ++ if (received >= budget) ++ break; + } + + fep->cur_rx = bdp; + +- if (received < budget && tx_left) { ++ if (received < budget) { + /* done */ + napi_complete(napi); +- (*fep->ops->napi_enable)(dev); ++ (*fep->ops->napi_enable_rx)(dev); ++ } ++ return received; ++} + +- return received; ++static int fs_enet_tx_napi(struct napi_struct *napi, int budget) ++{ ++ struct fs_enet_private *fep = container_of(napi, struct fs_enet_private, ++ napi_tx); ++ struct net_device *dev = fep->ndev; ++ cbd_t __iomem *bdp; ++ struct sk_buff *skb; ++ int dirtyidx, do_wake, do_restart; ++ u16 sc; ++ int has_tx_work = 0; ++ ++ spin_lock(&fep->tx_lock); ++ bdp = fep->dirty_tx; ++ ++ /* clear TX status bits for napi*/ ++ (*fep->ops->napi_clear_tx_event)(dev); ++ ++ do_wake = do_restart = 0; ++ while (((sc = CBDR_SC(bdp)) & BD_ENET_TX_READY) == 0) { ++ dirtyidx = bdp - fep->tx_bd_base; ++ ++ if (fep->tx_free == fep->tx_ring) ++ break; ++ ++ skb = fep->tx_skbuff[dirtyidx]; ++ ++ /* ++ * Check for errors. ++ */ ++ if (sc & (BD_ENET_TX_HB | BD_ENET_TX_LC | ++ BD_ENET_TX_RL | BD_ENET_TX_UN | BD_ENET_TX_CSL)) { ++ ++ if (sc & BD_ENET_TX_HB) /* No heartbeat */ ++ fep->stats.tx_heartbeat_errors++; ++ if (sc & BD_ENET_TX_LC) /* Late collision */ ++ fep->stats.tx_window_errors++; ++ if (sc & BD_ENET_TX_RL) /* Retrans limit */ ++ fep->stats.tx_aborted_errors++; ++ if (sc & BD_ENET_TX_UN) /* Underrun */ ++ fep->stats.tx_fifo_errors++; ++ if (sc & BD_ENET_TX_CSL) /* Carrier lost */ ++ fep->stats.tx_carrier_errors++; ++ ++ if (sc & (BD_ENET_TX_LC | BD_ENET_TX_RL | BD_ENET_TX_UN)) { ++ fep->stats.tx_errors++; ++ do_restart = 1; ++ } ++ } else ++ fep->stats.tx_packets++; ++ ++ if (sc & BD_ENET_TX_READY) { ++ dev_warn(fep->dev, ++ "HEY! Enet xmit interrupt and TX_READY.\n"); ++ } ++ ++ /* ++ * Deferred means some collisions occurred during transmit, ++ * but we eventually sent the packet OK. ++ */ ++ if (sc & BD_ENET_TX_DEF) ++ fep->stats.collisions++; ++ ++ /* unmap */ ++ if (fep->mapped_as_page[dirtyidx]) ++ dma_unmap_page(fep->dev, CBDR_BUFADDR(bdp), ++ CBDR_DATLEN(bdp), DMA_TO_DEVICE); ++ else ++ dma_unmap_single(fep->dev, CBDR_BUFADDR(bdp), ++ CBDR_DATLEN(bdp), DMA_TO_DEVICE); ++ ++ /* ++ * Free the sk buffer associated with this last transmit. ++ */ ++ if (skb) { ++ dev_kfree_skb(skb); ++ fep->tx_skbuff[dirtyidx] = NULL; ++ } ++ ++ /* ++ * Update pointer to next buffer descriptor to be transmitted. ++ */ ++ if ((sc & BD_ENET_TX_WRAP) == 0) ++ bdp++; ++ else ++ bdp = fep->tx_bd_base; ++ ++ /* ++ * Since we have freed up a buffer, the ring is no longer ++ * full. ++ */ ++ if (++fep->tx_free >= MAX_SKB_FRAGS) ++ do_wake = 1; ++ has_tx_work = 1; ++ } ++ ++ fep->dirty_tx = bdp; ++ ++ if (do_restart) ++ (*fep->ops->tx_restart)(dev); ++ ++ if (!has_tx_work) { ++ napi_complete(napi); ++ (*fep->ops->napi_enable_tx)(dev); + } + +- return budget; ++ spin_unlock(&fep->tx_lock); ++ ++ if (do_wake) ++ netif_wake_queue(dev); ++ ++ if (has_tx_work) ++ return budget; ++ return 0; + } + + /* +@@ -333,18 +353,18 @@ fs_enet_interrupt(int irq, void *dev_id) + nr++; + + int_clr_events = int_events; +- int_clr_events &= ~fep->ev_napi; ++ int_clr_events &= ~fep->ev_napi_rx; + + (*fep->ops->clear_int_events)(dev, int_clr_events); + + if (int_events & fep->ev_err) + (*fep->ops->ev_error)(dev, int_events); + +- if (int_events & fep->ev) { ++ if (int_events & fep->ev_rx) { + napi_ok = napi_schedule_prep(&fep->napi); + +- (*fep->ops->napi_disable)(dev); +- (*fep->ops->clear_int_events)(dev, fep->ev_napi); ++ (*fep->ops->napi_disable_rx)(dev); ++ (*fep->ops->clear_int_events)(dev, fep->ev_napi_rx); + + /* NOTE: it is possible for FCCs in NAPI mode */ + /* to submit a spurious interrupt while in poll */ +@@ -352,6 +372,17 @@ fs_enet_interrupt(int irq, void *dev_id) + __napi_schedule(&fep->napi); + } + ++ if (int_events & fep->ev_tx) { ++ napi_ok = napi_schedule_prep(&fep->napi_tx); ++ ++ (*fep->ops->napi_disable_tx)(dev); ++ (*fep->ops->clear_int_events)(dev, fep->ev_napi_tx); ++ ++ /* NOTE: it is possible for FCCs in NAPI mode */ ++ /* to submit a spurious interrupt while in poll */ ++ if (napi_ok) ++ __napi_schedule(&fep->napi_tx); ++ } + } + + handled = nr > 0; +@@ -459,9 +490,6 @@ static struct sk_buff *tx_skb_align_workaround(struct net_device *dev, + { + struct sk_buff *new_skb; + +- if (skb_linearize(skb)) +- return NULL; +- + /* Alloc new skb */ + new_skb = netdev_alloc_skb(dev, skb->len + 4); + if (!new_skb) +@@ -487,27 +515,12 @@ static int fs_enet_start_xmit(struct sk_buff *skb, struct net_device *dev) + cbd_t __iomem *bdp; + int curidx; + u16 sc; +- int nr_frags; ++ int nr_frags = skb_shinfo(skb)->nr_frags; + skb_frag_t *frag; + int len; +-#ifdef CONFIG_FS_ENET_MPC5121_FEC +- int is_aligned = 1; +- int i; +- +- if (!IS_ALIGNED((unsigned long)skb->data, 4)) { +- is_aligned = 0; +- } else { +- nr_frags = skb_shinfo(skb)->nr_frags; +- frag = skb_shinfo(skb)->frags; +- for (i = 0; i < nr_frags; i++, frag++) { +- if (!IS_ALIGNED(frag->page_offset, 4)) { +- is_aligned = 0; +- break; +- } +- } +- } + +- if (!is_aligned) { ++#ifdef CONFIG_FS_ENET_MPC5121_FEC ++ if (((unsigned long)skb->data) & 0x3) { + skb = tx_skb_align_workaround(dev, skb); + if (!skb) { + /* +@@ -519,7 +532,6 @@ static int fs_enet_start_xmit(struct sk_buff *skb, struct net_device *dev) + } + } + #endif +- + spin_lock(&fep->tx_lock); + + /* +@@ -527,7 +539,6 @@ static int fs_enet_start_xmit(struct sk_buff *skb, struct net_device *dev) + */ + bdp = fep->cur_tx; + +- nr_frags = skb_shinfo(skb)->nr_frags; + if (fep->tx_free <= nr_frags || (CBDR_SC(bdp) & BD_ENET_TX_READY)) { + netif_stop_queue(dev); + spin_unlock(&fep->tx_lock); +@@ -558,8 +569,7 @@ static int fs_enet_start_xmit(struct sk_buff *skb, struct net_device *dev) + frag = skb_shinfo(skb)->frags; + while (nr_frags) { + CBDC_SC(bdp, +- BD_ENET_TX_STATS | BD_ENET_TX_INTR | BD_ENET_TX_LAST | +- BD_ENET_TX_TC); ++ BD_ENET_TX_STATS | BD_ENET_TX_LAST | BD_ENET_TX_TC); + CBDS_SC(bdp, BD_ENET_TX_READY); + + if ((CBDR_SC(bdp) & BD_ENET_TX_WRAP) == 0) +@@ -624,15 +634,14 @@ static void fs_timeout(struct net_device *dev) + spin_lock_irqsave(&fep->lock, flags); + + if (dev->flags & IFF_UP) { +- phy_stop(dev->phydev); ++ phy_stop(fep->phydev); + (*fep->ops->stop)(dev); + (*fep->ops->restart)(dev); +- phy_start(dev->phydev); ++ phy_start(fep->phydev); + } + +- phy_start(dev->phydev); +- wake = fep->tx_free >= MAX_SKB_FRAGS && +- !(CBDR_SC(fep->cur_tx) & BD_ENET_TX_READY); ++ phy_start(fep->phydev); ++ wake = fep->tx_free && !(CBDR_SC(fep->cur_tx) & BD_ENET_TX_READY); + spin_unlock_irqrestore(&fep->lock, flags); + + if (wake) +@@ -645,7 +654,7 @@ static void fs_timeout(struct net_device *dev) + static void generic_adjust_link(struct net_device *dev) + { + struct fs_enet_private *fep = netdev_priv(dev); +- struct phy_device *phydev = dev->phydev; ++ struct phy_device *phydev = fep->phydev; + int new_state = 0; + + if (phydev->link) { +@@ -714,6 +723,8 @@ static int fs_init_phy(struct net_device *dev) + return -ENODEV; + } + ++ fep->phydev = phydev; ++ + return 0; + } + +@@ -724,10 +735,11 @@ static int fs_enet_open(struct net_device *dev) + int err; + + /* to initialize the fep->cur_rx,... */ +- /* not doing this, will cause a crash in fs_enet_napi */ ++ /* not doing this, will cause a crash in fs_enet_rx_napi */ + fs_init_bds(fep->ndev); + + napi_enable(&fep->napi); ++ napi_enable(&fep->napi_tx); + + /* Install our interrupt handler. */ + r = request_irq(fep->interrupt, fs_enet_interrupt, IRQF_SHARED, +@@ -735,6 +747,7 @@ static int fs_enet_open(struct net_device *dev) + if (r != 0) { + dev_err(fep->dev, "Could not allocate FS_ENET IRQ!"); + napi_disable(&fep->napi); ++ napi_disable(&fep->napi_tx); + return -EINVAL; + } + +@@ -742,9 +755,10 @@ static int fs_enet_open(struct net_device *dev) + if (err) { + free_irq(fep->interrupt, dev); + napi_disable(&fep->napi); ++ napi_disable(&fep->napi_tx); + return err; + } +- phy_start(dev->phydev); ++ phy_start(fep->phydev); + + netif_start_queue(dev); + +@@ -759,7 +773,8 @@ static int fs_enet_close(struct net_device *dev) + netif_stop_queue(dev); + netif_carrier_off(dev); + napi_disable(&fep->napi); +- phy_stop(dev->phydev); ++ napi_disable(&fep->napi_tx); ++ phy_stop(fep->phydev); + + spin_lock_irqsave(&fep->lock, flags); + spin_lock(&fep->tx_lock); +@@ -768,7 +783,8 @@ static int fs_enet_close(struct net_device *dev) + spin_unlock_irqrestore(&fep->lock, flags); + + /* release any irqs */ +- phy_disconnect(dev->phydev); ++ phy_disconnect(fep->phydev); ++ fep->phydev = NULL; + free_irq(fep->interrupt, dev); + + return 0; +@@ -813,82 +829,64 @@ static void fs_get_regs(struct net_device *dev, struct ethtool_regs *regs, + regs->version = 0; + } + +-static int fs_nway_reset(struct net_device *dev) ++static int fs_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) + { +- return 0; ++ struct fs_enet_private *fep = netdev_priv(dev); ++ ++ if (!fep->phydev) ++ return -ENODEV; ++ ++ return phy_ethtool_gset(fep->phydev, cmd); + } + +-static u32 fs_get_msglevel(struct net_device *dev) ++static int fs_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) + { + struct fs_enet_private *fep = netdev_priv(dev); +- return fep->msg_enable; ++ ++ if (!fep->phydev) ++ return -ENODEV; ++ ++ return phy_ethtool_sset(fep->phydev, cmd); + } + +-static void fs_set_msglevel(struct net_device *dev, u32 value) ++static int fs_nway_reset(struct net_device *dev) + { +- struct fs_enet_private *fep = netdev_priv(dev); +- fep->msg_enable = value; ++ return 0; + } + +-static int fs_get_tunable(struct net_device *dev, +- const struct ethtool_tunable *tuna, void *data) ++static u32 fs_get_msglevel(struct net_device *dev) + { + struct fs_enet_private *fep = netdev_priv(dev); +- struct fs_platform_info *fpi = fep->fpi; +- int ret = 0; +- +- switch (tuna->id) { +- case ETHTOOL_RX_COPYBREAK: +- *(u32 *)data = fpi->rx_copybreak; +- break; +- default: +- ret = -EINVAL; +- break; +- } +- +- return ret; ++ return fep->msg_enable; + } + +-static int fs_set_tunable(struct net_device *dev, +- const struct ethtool_tunable *tuna, const void *data) ++static void fs_set_msglevel(struct net_device *dev, u32 value) + { + struct fs_enet_private *fep = netdev_priv(dev); +- struct fs_platform_info *fpi = fep->fpi; +- int ret = 0; +- +- switch (tuna->id) { +- case ETHTOOL_RX_COPYBREAK: +- fpi->rx_copybreak = *(u32 *)data; +- break; +- default: +- ret = -EINVAL; +- break; +- } +- +- return ret; ++ fep->msg_enable = value; + } + + static const struct ethtool_ops fs_ethtool_ops = { + .get_drvinfo = fs_get_drvinfo, + .get_regs_len = fs_get_regs_len, ++ .get_settings = fs_get_settings, ++ .set_settings = fs_set_settings, + .nway_reset = fs_nway_reset, + .get_link = ethtool_op_get_link, + .get_msglevel = fs_get_msglevel, + .set_msglevel = fs_set_msglevel, + .get_regs = fs_get_regs, + .get_ts_info = ethtool_op_get_ts_info, +- .get_link_ksettings = phy_ethtool_get_link_ksettings, +- .set_link_ksettings = phy_ethtool_set_link_ksettings, +- .get_tunable = fs_get_tunable, +- .set_tunable = fs_set_tunable, + }; + + static int fs_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) + { ++ struct fs_enet_private *fep = netdev_priv(dev); ++ + if (!netif_running(dev)) + return -EINVAL; + +- return phy_mii_ioctl(dev->phydev, rq, cmd); ++ return phy_mii_ioctl(fep->phydev, rq, cmd); + } + + extern int fs_mii_connect(struct net_device *dev); +@@ -948,8 +946,8 @@ static int fs_enet_probe(struct platform_device *ofdev) + fpi->cp_command = *data; + } + +- fpi->rx_ring = RX_RING_SIZE; +- fpi->tx_ring = TX_RING_SIZE; ++ fpi->rx_ring = 32; ++ fpi->tx_ring = 64; + fpi->rx_copybreak = 240; + fpi->napi_weight = 17; + fpi->phy_node = of_parse_phandle(ofdev->dev.of_node, "phy-handle", 0); +@@ -980,7 +978,7 @@ static int fs_enet_probe(struct platform_device *ofdev) + err = clk_prepare_enable(clk); + if (err) { + ret = err; +- goto out_deregister_fixed_link; ++ goto out_free_fpi; + } + fpi->clk_per = clk; + } +@@ -1033,7 +1031,8 @@ static int fs_enet_probe(struct platform_device *ofdev) + + ndev->netdev_ops = &fs_enet_netdev_ops; + ndev->watchdog_timeo = 2 * HZ; +- netif_napi_add(ndev, &fep->napi, fs_enet_napi, fpi->napi_weight); ++ netif_napi_add(ndev, &fep->napi, fs_enet_rx_napi, fpi->napi_weight); ++ netif_napi_add(ndev, &fep->napi_tx, fs_enet_tx_napi, 2); + + ndev->ethtool_ops = &fs_ethtool_ops; + +@@ -1061,9 +1060,6 @@ static int fs_enet_probe(struct platform_device *ofdev) + of_node_put(fpi->phy_node); + if (fpi->clk_per) + clk_disable_unprepare(fpi->clk_per); +-out_deregister_fixed_link: +- if (of_phy_is_fixed_link(ofdev->dev.of_node)) +- of_phy_deregister_fixed_link(ofdev->dev.of_node); + out_free_fpi: + kfree(fpi); + return ret; +@@ -1082,8 +1078,6 @@ static int fs_enet_remove(struct platform_device *ofdev) + of_node_put(fep->fpi->phy_node); + if (fep->fpi->clk_per) + clk_disable_unprepare(fep->fpi->clk_per); +- if (of_phy_is_fixed_link(ofdev->dev.of_node)) +- of_phy_deregister_fixed_link(ofdev->dev.of_node); + free_netdev(ndev); + return 0; + } +diff --git a/drivers/net/ethernet/freescale/fs_enet/fs_enet.h b/drivers/net/ethernet/freescale/fs_enet/fs_enet.h +index fee24c8..f184d8f 100644 +--- a/drivers/net/ethernet/freescale/fs_enet/fs_enet.h ++++ b/drivers/net/ethernet/freescale/fs_enet/fs_enet.h +@@ -81,9 +81,12 @@ struct fs_ops { + void (*adjust_link)(struct net_device *dev); + void (*restart)(struct net_device *dev); + void (*stop)(struct net_device *dev); +- void (*napi_clear_event)(struct net_device *dev); +- void (*napi_enable)(struct net_device *dev); +- void (*napi_disable)(struct net_device *dev); ++ void (*napi_clear_rx_event)(struct net_device *dev); ++ void (*napi_enable_rx)(struct net_device *dev); ++ void (*napi_disable_rx)(struct net_device *dev); ++ void (*napi_clear_tx_event)(struct net_device *dev); ++ void (*napi_enable_tx)(struct net_device *dev); ++ void (*napi_disable_tx)(struct net_device *dev); + void (*rx_bd_done)(struct net_device *dev); + void (*tx_kickstart)(struct net_device *dev); + u32 (*get_int_events)(struct net_device *dev); +@@ -119,6 +122,7 @@ struct phy_info { + + struct fs_enet_private { + struct napi_struct napi; ++ struct napi_struct napi_tx; + struct device *dev; /* pointer back to the device (must be initialized first) */ + struct net_device *ndev; + spinlock_t lock; /* during all ops except TX pckt processing */ +@@ -145,11 +149,14 @@ struct fs_enet_private { + unsigned int last_mii_status; + int interrupt; + ++ struct phy_device *phydev; + int oldduplex, oldspeed, oldlink; /* current settings */ + + /* event masks */ +- u32 ev_napi; /* mask of NAPI events */ +- u32 ev; /* event mask */ ++ u32 ev_napi_rx; /* mask of NAPI rx events */ ++ u32 ev_napi_tx; /* mask of NAPI rx events */ ++ u32 ev_rx; /* rx event mask */ ++ u32 ev_tx; /* tx event mask */ + u32 ev_err; /* error event mask */ + + u16 bd_rx_empty; /* mask of BD rx empty */ +diff --git a/drivers/net/ethernet/freescale/fs_enet/mac-fcc.c b/drivers/net/ethernet/freescale/fs_enet/mac-fcc.c +index 120c758..08f5b91 100644 +--- a/drivers/net/ethernet/freescale/fs_enet/mac-fcc.c ++++ b/drivers/net/ethernet/freescale/fs_enet/mac-fcc.c +@@ -90,7 +90,7 @@ static int do_pd_setup(struct fs_enet_private *fep) + int ret = -EINVAL; + + fep->interrupt = irq_of_parse_and_map(ofdev->dev.of_node, 0); +- if (!fep->interrupt) ++ if (fep->interrupt == NO_IRQ) + goto out; + + fep->fcc.fccp = of_iomap(ofdev->dev.of_node, 0); +@@ -124,8 +124,10 @@ static int do_pd_setup(struct fs_enet_private *fep) + return ret; + } + +-#define FCC_NAPI_EVENT_MSK (FCC_ENET_RXF | FCC_ENET_RXB | FCC_ENET_TXB) +-#define FCC_EVENT (FCC_ENET_RXF | FCC_ENET_TXB) ++#define FCC_NAPI_RX_EVENT_MSK (FCC_ENET_RXF | FCC_ENET_RXB) ++#define FCC_NAPI_TX_EVENT_MSK (FCC_ENET_TXB) ++#define FCC_RX_EVENT (FCC_ENET_RXF) ++#define FCC_TX_EVENT (FCC_ENET_TXB) + #define FCC_ERR_EVENT_MSK (FCC_ENET_TXE) + + static int setup_data(struct net_device *dev) +@@ -135,8 +137,10 @@ static int setup_data(struct net_device *dev) + if (do_pd_setup(fep) != 0) + return -EINVAL; + +- fep->ev_napi = FCC_NAPI_EVENT_MSK; +- fep->ev = FCC_EVENT; ++ fep->ev_napi_rx = FCC_NAPI_RX_EVENT_MSK; ++ fep->ev_napi_tx = FCC_NAPI_TX_EVENT_MSK; ++ fep->ev_rx = FCC_RX_EVENT; ++ fep->ev_tx = FCC_TX_EVENT; + fep->ev_err = FCC_ERR_EVENT_MSK; + + return 0; +@@ -366,7 +370,7 @@ static void restart(struct net_device *dev) + + /* adjust to speed (for RMII mode) */ + if (fpi->use_rmii) { +- if (dev->phydev->speed == 100) ++ if (fep->phydev->speed == 100) + C8(fcccp, fcc_gfemr, 0x20); + else + S8(fcccp, fcc_gfemr, 0x20); +@@ -392,7 +396,7 @@ static void restart(struct net_device *dev) + S32(fccp, fcc_fpsmr, FCC_PSMR_RMII); + + /* adjust to duplex mode */ +- if (dev->phydev->duplex) ++ if (fep->phydev->duplex) + S32(fccp, fcc_fpsmr, FCC_PSMR_FDE | FCC_PSMR_LPB); + else + C32(fccp, fcc_fpsmr, FCC_PSMR_FDE | FCC_PSMR_LPB); +@@ -420,28 +424,52 @@ static void stop(struct net_device *dev) + fs_cleanup_bds(dev); + } + +-static void napi_clear_event_fs(struct net_device *dev) ++static void napi_clear_rx_event(struct net_device *dev) + { + struct fs_enet_private *fep = netdev_priv(dev); + fcc_t __iomem *fccp = fep->fcc.fccp; + +- W16(fccp, fcc_fcce, FCC_NAPI_EVENT_MSK); ++ W16(fccp, fcc_fcce, FCC_NAPI_RX_EVENT_MSK); + } + +-static void napi_enable_fs(struct net_device *dev) ++static void napi_enable_rx(struct net_device *dev) + { + struct fs_enet_private *fep = netdev_priv(dev); + fcc_t __iomem *fccp = fep->fcc.fccp; + +- S16(fccp, fcc_fccm, FCC_NAPI_EVENT_MSK); ++ S16(fccp, fcc_fccm, FCC_NAPI_RX_EVENT_MSK); + } + +-static void napi_disable_fs(struct net_device *dev) ++static void napi_disable_rx(struct net_device *dev) + { + struct fs_enet_private *fep = netdev_priv(dev); + fcc_t __iomem *fccp = fep->fcc.fccp; + +- C16(fccp, fcc_fccm, FCC_NAPI_EVENT_MSK); ++ C16(fccp, fcc_fccm, FCC_NAPI_RX_EVENT_MSK); ++} ++ ++static void napi_clear_tx_event(struct net_device *dev) ++{ ++ struct fs_enet_private *fep = netdev_priv(dev); ++ fcc_t __iomem *fccp = fep->fcc.fccp; ++ ++ W16(fccp, fcc_fcce, FCC_NAPI_TX_EVENT_MSK); ++} ++ ++static void napi_enable_tx(struct net_device *dev) ++{ ++ struct fs_enet_private *fep = netdev_priv(dev); ++ fcc_t __iomem *fccp = fep->fcc.fccp; ++ ++ S16(fccp, fcc_fccm, FCC_NAPI_TX_EVENT_MSK); ++} ++ ++static void napi_disable_tx(struct net_device *dev) ++{ ++ struct fs_enet_private *fep = netdev_priv(dev); ++ fcc_t __iomem *fccp = fep->fcc.fccp; ++ ++ C16(fccp, fcc_fccm, FCC_NAPI_TX_EVENT_MSK); + } + + static void rx_bd_done(struct net_device *dev) +@@ -524,7 +552,7 @@ static void tx_restart(struct net_device *dev) + cbd_t __iomem *prev_bd; + cbd_t __iomem *last_tx_bd; + +- last_tx_bd = fep->tx_bd_base + (fpi->tx_ring - 1); ++ last_tx_bd = fep->tx_bd_base + (fpi->tx_ring * sizeof(cbd_t)); + + /* get the current bd held in TBPTR and scan back from this point */ + recheck_bd = curr_tbptr = (cbd_t __iomem *) +@@ -567,9 +595,12 @@ const struct fs_ops fs_fcc_ops = { + .set_multicast_list = set_multicast_list, + .restart = restart, + .stop = stop, +- .napi_clear_event = napi_clear_event_fs, +- .napi_enable = napi_enable_fs, +- .napi_disable = napi_disable_fs, ++ .napi_clear_rx_event = napi_clear_rx_event, ++ .napi_enable_rx = napi_enable_rx, ++ .napi_disable_rx = napi_disable_rx, ++ .napi_clear_tx_event = napi_clear_tx_event, ++ .napi_enable_tx = napi_enable_tx, ++ .napi_disable_tx = napi_disable_tx, + .rx_bd_done = rx_bd_done, + .tx_kickstart = tx_kickstart, + .get_int_events = get_int_events, +diff --git a/drivers/net/ethernet/freescale/fs_enet/mac-fec.c b/drivers/net/ethernet/freescale/fs_enet/mac-fec.c +index 777beff..b34214e 100644 +--- a/drivers/net/ethernet/freescale/fs_enet/mac-fec.c ++++ b/drivers/net/ethernet/freescale/fs_enet/mac-fec.c +@@ -99,7 +99,7 @@ static int do_pd_setup(struct fs_enet_private *fep) + struct platform_device *ofdev = to_platform_device(fep->dev); + + fep->interrupt = irq_of_parse_and_map(ofdev->dev.of_node, 0); +- if (!fep->interrupt) ++ if (fep->interrupt == NO_IRQ) + return -EINVAL; + + fep->fec.fecp = of_iomap(ofdev->dev.of_node, 0); +@@ -109,8 +109,10 @@ static int do_pd_setup(struct fs_enet_private *fep) + return 0; + } + +-#define FEC_NAPI_EVENT_MSK (FEC_ENET_RXF | FEC_ENET_RXB | FEC_ENET_TXF) +-#define FEC_EVENT (FEC_ENET_RXF | FEC_ENET_TXF) ++#define FEC_NAPI_RX_EVENT_MSK (FEC_ENET_RXF | FEC_ENET_RXB) ++#define FEC_NAPI_TX_EVENT_MSK (FEC_ENET_TXF | FEC_ENET_TXB) ++#define FEC_RX_EVENT (FEC_ENET_RXF) ++#define FEC_TX_EVENT (FEC_ENET_TXF) + #define FEC_ERR_EVENT_MSK (FEC_ENET_HBERR | FEC_ENET_BABR | \ + FEC_ENET_BABT | FEC_ENET_EBERR) + +@@ -124,8 +126,10 @@ static int setup_data(struct net_device *dev) + fep->fec.hthi = 0; + fep->fec.htlo = 0; + +- fep->ev_napi = FEC_NAPI_EVENT_MSK; +- fep->ev = FEC_EVENT; ++ fep->ev_napi_rx = FEC_NAPI_RX_EVENT_MSK; ++ fep->ev_napi_tx = FEC_NAPI_TX_EVENT_MSK; ++ fep->ev_rx = FEC_RX_EVENT; ++ fep->ev_tx = FEC_TX_EVENT; + fep->ev_err = FEC_ERR_EVENT_MSK; + + return 0; +@@ -250,7 +254,7 @@ static void restart(struct net_device *dev) + int r; + u32 addrhi, addrlo; + +- struct mii_bus *mii = dev->phydev->mdio.bus; ++ struct mii_bus* mii = fep->phydev->bus; + struct fec_info* fec_inf = mii->priv; + + r = whack_reset(fep->fec.fecp); +@@ -329,7 +333,7 @@ static void restart(struct net_device *dev) + /* + * adjust to duplex mode + */ +- if (dev->phydev->duplex) { ++ if (fep->phydev->duplex) { + FC(fecp, r_cntrl, FEC_RCNTRL_DRT); + FS(fecp, x_cntrl, FEC_TCNTRL_FDEN); /* FD enable */ + } else { +@@ -359,7 +363,7 @@ static void stop(struct net_device *dev) + const struct fs_platform_info *fpi = fep->fpi; + struct fec __iomem *fecp = fep->fec.fecp; + +- struct fec_info *feci = dev->phydev->mdio.bus->priv; ++ struct fec_info* feci= fep->phydev->bus->priv; + + int i; + +@@ -392,28 +396,52 @@ static void stop(struct net_device *dev) + } + } + +-static void napi_clear_event_fs(struct net_device *dev) ++static void napi_clear_rx_event(struct net_device *dev) + { + struct fs_enet_private *fep = netdev_priv(dev); + struct fec __iomem *fecp = fep->fec.fecp; + +- FW(fecp, ievent, FEC_NAPI_EVENT_MSK); ++ FW(fecp, ievent, FEC_NAPI_RX_EVENT_MSK); + } + +-static void napi_enable_fs(struct net_device *dev) ++static void napi_enable_rx(struct net_device *dev) + { + struct fs_enet_private *fep = netdev_priv(dev); + struct fec __iomem *fecp = fep->fec.fecp; + +- FS(fecp, imask, FEC_NAPI_EVENT_MSK); ++ FS(fecp, imask, FEC_NAPI_RX_EVENT_MSK); + } + +-static void napi_disable_fs(struct net_device *dev) ++static void napi_disable_rx(struct net_device *dev) + { + struct fs_enet_private *fep = netdev_priv(dev); + struct fec __iomem *fecp = fep->fec.fecp; + +- FC(fecp, imask, FEC_NAPI_EVENT_MSK); ++ FC(fecp, imask, FEC_NAPI_RX_EVENT_MSK); ++} ++ ++static void napi_clear_tx_event(struct net_device *dev) ++{ ++ struct fs_enet_private *fep = netdev_priv(dev); ++ struct fec __iomem *fecp = fep->fec.fecp; ++ ++ FW(fecp, ievent, FEC_NAPI_TX_EVENT_MSK); ++} ++ ++static void napi_enable_tx(struct net_device *dev) ++{ ++ struct fs_enet_private *fep = netdev_priv(dev); ++ struct fec __iomem *fecp = fep->fec.fecp; ++ ++ FS(fecp, imask, FEC_NAPI_TX_EVENT_MSK); ++} ++ ++static void napi_disable_tx(struct net_device *dev) ++{ ++ struct fs_enet_private *fep = netdev_priv(dev); ++ struct fec __iomem *fecp = fep->fec.fecp; ++ ++ FC(fecp, imask, FEC_NAPI_TX_EVENT_MSK); + } + + static void rx_bd_done(struct net_device *dev) +@@ -485,9 +513,12 @@ const struct fs_ops fs_fec_ops = { + .set_multicast_list = set_multicast_list, + .restart = restart, + .stop = stop, +- .napi_clear_event = napi_clear_event_fs, +- .napi_enable = napi_enable_fs, +- .napi_disable = napi_disable_fs, ++ .napi_clear_rx_event = napi_clear_rx_event, ++ .napi_enable_rx = napi_enable_rx, ++ .napi_disable_rx = napi_disable_rx, ++ .napi_clear_tx_event = napi_clear_tx_event, ++ .napi_enable_tx = napi_enable_tx, ++ .napi_disable_tx = napi_disable_tx, + .rx_bd_done = rx_bd_done, + .tx_kickstart = tx_kickstart, + .get_int_events = get_int_events, +diff --git a/drivers/net/ethernet/freescale/fs_enet/mac-scc.c b/drivers/net/ethernet/freescale/fs_enet/mac-scc.c +index 15abd37..7a184e8 100644 +--- a/drivers/net/ethernet/freescale/fs_enet/mac-scc.c ++++ b/drivers/net/ethernet/freescale/fs_enet/mac-scc.c +@@ -99,7 +99,7 @@ static int do_pd_setup(struct fs_enet_private *fep) + struct platform_device *ofdev = to_platform_device(fep->dev); + + fep->interrupt = irq_of_parse_and_map(ofdev->dev.of_node, 0); +- if (!fep->interrupt) ++ if (fep->interrupt == NO_IRQ) + return -EINVAL; + + fep->scc.sccp = of_iomap(ofdev->dev.of_node, 0); +@@ -115,8 +115,10 @@ static int do_pd_setup(struct fs_enet_private *fep) + return 0; + } + +-#define SCC_NAPI_EVENT_MSK (SCCE_ENET_RXF | SCCE_ENET_RXB | SCCE_ENET_TXB) +-#define SCC_EVENT (SCCE_ENET_RXF | SCCE_ENET_TXB) ++#define SCC_NAPI_RX_EVENT_MSK (SCCE_ENET_RXF | SCCE_ENET_RXB) ++#define SCC_NAPI_TX_EVENT_MSK (SCCE_ENET_TXB) ++#define SCC_RX_EVENT (SCCE_ENET_RXF) ++#define SCC_TX_EVENT (SCCE_ENET_TXB) + #define SCC_ERR_EVENT_MSK (SCCE_ENET_TXE | SCCE_ENET_BSY) + + static int setup_data(struct net_device *dev) +@@ -128,8 +130,10 @@ static int setup_data(struct net_device *dev) + fep->scc.hthi = 0; + fep->scc.htlo = 0; + +- fep->ev_napi = SCC_NAPI_EVENT_MSK; +- fep->ev = SCC_EVENT | SCCE_ENET_TXE; ++ fep->ev_napi_rx = SCC_NAPI_RX_EVENT_MSK; ++ fep->ev_napi_tx = SCC_NAPI_TX_EVENT_MSK; ++ fep->ev_rx = SCC_RX_EVENT; ++ fep->ev_tx = SCC_TX_EVENT | SCCE_ENET_TXE; + fep->ev_err = SCC_ERR_EVENT_MSK; + + return 0; +@@ -348,7 +352,7 @@ static void restart(struct net_device *dev) + W16(sccp, scc_psmr, SCC_PSMR_ENCRC | SCC_PSMR_NIB22); + + /* Set full duplex mode if needed */ +- if (dev->phydev->duplex) ++ if (fep->phydev->duplex) + S16(sccp, scc_psmr, SCC_PSMR_LPB | SCC_PSMR_FDE); + + /* Restore multicast and promiscuous settings */ +@@ -375,28 +379,52 @@ static void stop(struct net_device *dev) + fs_cleanup_bds(dev); + } + +-static void napi_clear_event_fs(struct net_device *dev) ++static void napi_clear_rx_event(struct net_device *dev) + { + struct fs_enet_private *fep = netdev_priv(dev); + scc_t __iomem *sccp = fep->scc.sccp; + +- W16(sccp, scc_scce, SCC_NAPI_EVENT_MSK); ++ W16(sccp, scc_scce, SCC_NAPI_RX_EVENT_MSK); + } + +-static void napi_enable_fs(struct net_device *dev) ++static void napi_enable_rx(struct net_device *dev) + { + struct fs_enet_private *fep = netdev_priv(dev); + scc_t __iomem *sccp = fep->scc.sccp; + +- S16(sccp, scc_sccm, SCC_NAPI_EVENT_MSK); ++ S16(sccp, scc_sccm, SCC_NAPI_RX_EVENT_MSK); + } + +-static void napi_disable_fs(struct net_device *dev) ++static void napi_disable_rx(struct net_device *dev) + { + struct fs_enet_private *fep = netdev_priv(dev); + scc_t __iomem *sccp = fep->scc.sccp; + +- C16(sccp, scc_sccm, SCC_NAPI_EVENT_MSK); ++ C16(sccp, scc_sccm, SCC_NAPI_RX_EVENT_MSK); ++} ++ ++static void napi_clear_tx_event(struct net_device *dev) ++{ ++ struct fs_enet_private *fep = netdev_priv(dev); ++ scc_t __iomem *sccp = fep->scc.sccp; ++ ++ W16(sccp, scc_scce, SCC_NAPI_TX_EVENT_MSK); ++} ++ ++static void napi_enable_tx(struct net_device *dev) ++{ ++ struct fs_enet_private *fep = netdev_priv(dev); ++ scc_t __iomem *sccp = fep->scc.sccp; ++ ++ S16(sccp, scc_sccm, SCC_NAPI_TX_EVENT_MSK); ++} ++ ++static void napi_disable_tx(struct net_device *dev) ++{ ++ struct fs_enet_private *fep = netdev_priv(dev); ++ scc_t __iomem *sccp = fep->scc.sccp; ++ ++ C16(sccp, scc_sccm, SCC_NAPI_TX_EVENT_MSK); + } + + static void rx_bd_done(struct net_device *dev) +@@ -469,9 +497,12 @@ const struct fs_ops fs_scc_ops = { + .set_multicast_list = set_multicast_list, + .restart = restart, + .stop = stop, +- .napi_clear_event = napi_clear_event_fs, +- .napi_enable = napi_enable_fs, +- .napi_disable = napi_disable_fs, ++ .napi_clear_rx_event = napi_clear_rx_event, ++ .napi_enable_rx = napi_enable_rx, ++ .napi_disable_rx = napi_disable_rx, ++ .napi_clear_tx_event = napi_clear_tx_event, ++ .napi_enable_tx = napi_enable_tx, ++ .napi_disable_tx = napi_disable_tx, + .rx_bd_done = rx_bd_done, + .tx_kickstart = tx_kickstart, + .get_int_events = get_int_events, +diff --git a/drivers/net/ethernet/freescale/fs_enet/mii-bitbang.c b/drivers/net/ethernet/freescale/fs_enet/mii-bitbang.c +index 1f015ed..68a428d 100644 +--- a/drivers/net/ethernet/freescale/fs_enet/mii-bitbang.c ++++ b/drivers/net/ethernet/freescale/fs_enet/mii-bitbang.c +@@ -172,16 +172,23 @@ static int fs_enet_mdio_probe(struct platform_device *ofdev) + goto out_free_bus; + + new_bus->phy_mask = ~0; ++ new_bus->irq = kmalloc(sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL); ++ if (!new_bus->irq) { ++ ret = -ENOMEM; ++ goto out_unmap_regs; ++ } + + new_bus->parent = &ofdev->dev; + platform_set_drvdata(ofdev, new_bus); + + ret = of_mdiobus_register(new_bus, ofdev->dev.of_node); + if (ret) +- goto out_unmap_regs; ++ goto out_free_irqs; + + return 0; + ++out_free_irqs: ++ kfree(new_bus->irq); + out_unmap_regs: + iounmap(bitbang->dir); + out_free_bus: +@@ -198,6 +205,7 @@ static int fs_enet_mdio_remove(struct platform_device *ofdev) + struct bb_info *bitbang = bus->priv; + + mdiobus_unregister(bus); ++ kfree(bus->irq); + free_mdio_bitbang(bus); + iounmap(bitbang->dir); + kfree(bitbang); +diff --git a/drivers/net/ethernet/freescale/fs_enet/mii-fec.c b/drivers/net/ethernet/freescale/fs_enet/mii-fec.c +index a89267b..2be383e 100644 +--- a/drivers/net/ethernet/freescale/fs_enet/mii-fec.c ++++ b/drivers/net/ethernet/freescale/fs_enet/mii-fec.c +@@ -166,16 +166,23 @@ static int fs_enet_mdio_probe(struct platform_device *ofdev) + clrsetbits_be32(&fec->fecp->fec_mii_speed, 0x7E, fec->mii_speed); + + new_bus->phy_mask = ~0; ++ new_bus->irq = kmalloc(sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL); ++ if (!new_bus->irq) { ++ ret = -ENOMEM; ++ goto out_unmap_regs; ++ } + + new_bus->parent = &ofdev->dev; + platform_set_drvdata(ofdev, new_bus); + + ret = of_mdiobus_register(new_bus, ofdev->dev.of_node); + if (ret) +- goto out_unmap_regs; ++ goto out_free_irqs; + + return 0; + ++out_free_irqs: ++ kfree(new_bus->irq); + out_unmap_regs: + iounmap(fec->fecp); + out_res: +@@ -193,6 +200,7 @@ static int fs_enet_mdio_remove(struct platform_device *ofdev) + struct fec_info *fec = bus->priv; + + mdiobus_unregister(bus); ++ kfree(bus->irq); + iounmap(fec->fecp); + kfree(fec); + mdiobus_free(bus); +diff --git a/drivers/net/ethernet/freescale/fsl_pq_mdio.c b/drivers/net/ethernet/freescale/fsl_pq_mdio.c +index 446c7b3..3c40f6b 100644 +--- a/drivers/net/ethernet/freescale/fsl_pq_mdio.c ++++ b/drivers/net/ethernet/freescale/fsl_pq_mdio.c +@@ -29,7 +29,7 @@ + + #include + #if IS_ENABLED(CONFIG_UCC_GETH) +-#include ++#include /* for ucc_set_qe_mux_mii_mng() */ + #endif + + #include "gianfar.h" +@@ -69,6 +69,7 @@ struct fsl_pq_mdio { + struct fsl_pq_mdio_priv { + void __iomem *map; + struct fsl_pq_mii __iomem *regs; ++ int irqs[PHY_MAX_ADDR]; + }; + + /* +@@ -195,15 +196,13 @@ static int fsl_pq_mdio_reset(struct mii_bus *bus) + return 0; + } + +-#if IS_ENABLED(CONFIG_GIANFAR) ++#if defined(CONFIG_GIANFAR) || defined(CONFIG_GIANFAR_MODULE) + /* +- * Return the TBIPA address, starting from the address +- * of the mapped GFAR MDIO registers (struct gfar) + * This is mildly evil, but so is our hardware for doing this. + * Also, we have to cast back to struct gfar because of + * definition weirdness done in gianfar.h. + */ +-static uint32_t __iomem *get_gfar_tbipa_from_mdio(void __iomem *p) ++static uint32_t __iomem *get_gfar_tbipa(void __iomem *p) + { + struct gfar __iomem *enet_regs = p; + +@@ -211,15 +210,6 @@ static uint32_t __iomem *get_gfar_tbipa_from_mdio(void __iomem *p) + } + + /* +- * Return the TBIPA address, starting from the address +- * of the mapped GFAR MII registers (gfar_mii_regs[] within struct gfar) +- */ +-static uint32_t __iomem *get_gfar_tbipa_from_mii(void __iomem *p) +-{ +- return get_gfar_tbipa_from_mdio(container_of(p, struct gfar, gfar_mii_regs)); +-} +- +-/* + * Return the TBIPAR address for an eTSEC2 node + */ + static uint32_t __iomem *get_etsec_tbipa(void __iomem *p) +@@ -228,14 +218,13 @@ static uint32_t __iomem *get_etsec_tbipa(void __iomem *p) + } + #endif + +-#if IS_ENABLED(CONFIG_UCC_GETH) ++#if defined(CONFIG_UCC_GETH) || defined(CONFIG_UCC_GETH_MODULE) + /* +- * Return the TBIPAR address for a QE MDIO node, starting from the address +- * of the mapped MII registers (struct fsl_pq_mii) ++ * Return the TBIPAR address for a QE MDIO node + */ + static uint32_t __iomem *get_ucc_tbipa(void __iomem *p) + { +- struct fsl_pq_mdio __iomem *mdio = container_of(p, struct fsl_pq_mdio, mii); ++ struct fsl_pq_mdio __iomem *mdio = p; + + return &mdio->utbipar; + } +@@ -306,19 +295,19 @@ static void ucc_configure(phys_addr_t start, phys_addr_t end) + #endif + + static const struct of_device_id fsl_pq_mdio_match[] = { +-#if IS_ENABLED(CONFIG_GIANFAR) ++#if defined(CONFIG_GIANFAR) || defined(CONFIG_GIANFAR_MODULE) + { + .compatible = "fsl,gianfar-tbi", + .data = &(struct fsl_pq_mdio_data) { + .mii_offset = 0, +- .get_tbipa = get_gfar_tbipa_from_mii, ++ .get_tbipa = get_gfar_tbipa, + }, + }, + { + .compatible = "fsl,gianfar-mdio", + .data = &(struct fsl_pq_mdio_data) { + .mii_offset = 0, +- .get_tbipa = get_gfar_tbipa_from_mii, ++ .get_tbipa = get_gfar_tbipa, + }, + }, + { +@@ -326,7 +315,7 @@ static const struct of_device_id fsl_pq_mdio_match[] = { + .compatible = "gianfar", + .data = &(struct fsl_pq_mdio_data) { + .mii_offset = offsetof(struct fsl_pq_mdio, mii), +- .get_tbipa = get_gfar_tbipa_from_mdio, ++ .get_tbipa = get_gfar_tbipa, + }, + }, + { +@@ -344,7 +333,7 @@ static const struct of_device_id fsl_pq_mdio_match[] = { + }, + }, + #endif +-#if IS_ENABLED(CONFIG_UCC_GETH) ++#if defined(CONFIG_UCC_GETH) || defined(CONFIG_UCC_GETH_MODULE) + { + .compatible = "fsl,ucc-mdio", + .data = &(struct fsl_pq_mdio_data) { +@@ -400,6 +389,7 @@ static int fsl_pq_mdio_probe(struct platform_device *pdev) + new_bus->read = &fsl_pq_mdio_read; + new_bus->write = &fsl_pq_mdio_write; + new_bus->reset = &fsl_pq_mdio_reset; ++ new_bus->irq = priv->irqs; + + err = of_address_to_resource(np, 0, &res); + if (err < 0) { +@@ -455,16 +445,6 @@ static int fsl_pq_mdio_probe(struct platform_device *pdev) + + tbipa = data->get_tbipa(priv->map); + +- /* +- * Add consistency check to make sure TBI is contained +- * within the mapped range (not because we would get a +- * segfault, rather to catch bugs in computing TBI +- * address). Print error message but continue anyway. +- */ +- if ((void *)tbipa > priv->map + resource_size(&res) - 4) +- dev_err(&pdev->dev, "invalid register map (should be at least 0x%04zx to contain TBI address)\n", +- ((void *)tbipa - priv->map) + 4); +- + iowrite32be(be32_to_cpup(prop), tbipa); + } + } +diff --git a/drivers/net/ethernet/freescale/gianfar.c b/drivers/net/ethernet/freescale/gianfar.c +index 9061c2f..4ee080d 100644 +--- a/drivers/net/ethernet/freescale/gianfar.c ++++ b/drivers/net/ethernet/freescale/gianfar.c +@@ -107,17 +107,17 @@ + + #include "gianfar.h" + +-#define TX_TIMEOUT (5*HZ) ++#define TX_TIMEOUT (1*HZ) + +-const char gfar_driver_version[] = "2.0"; ++const char gfar_driver_version[] = "1.3"; + + static int gfar_enet_open(struct net_device *dev); + static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev); + static void gfar_reset_task(struct work_struct *work); + static void gfar_timeout(struct net_device *dev); + static int gfar_close(struct net_device *dev); +-static void gfar_alloc_rx_buffs(struct gfar_priv_rx_q *rx_queue, +- int alloc_cnt); ++static struct sk_buff *gfar_new_skb(struct net_device *dev, ++ dma_addr_t *bufaddr); + static int gfar_set_mac_address(struct net_device *dev); + static int gfar_change_mtu(struct net_device *dev, int new_mtu); + static irqreturn_t gfar_error(int irq, void *dev_id); +@@ -141,7 +141,8 @@ static void gfar_netpoll(struct net_device *dev); + #endif + int gfar_clean_rx_ring(struct gfar_priv_rx_q *rx_queue, int rx_work_limit); + static void gfar_clean_tx_ring(struct gfar_priv_tx_q *tx_queue); +-static void gfar_process_frame(struct net_device *ndev, struct sk_buff *skb); ++static void gfar_process_frame(struct net_device *dev, struct sk_buff *skb, ++ int amount_pull, struct napi_struct *napi); + static void gfar_halt_nodisable(struct gfar_private *priv); + static void gfar_clear_exact_match(struct net_device *dev); + static void gfar_set_mac_for_addr(struct net_device *dev, int num, +@@ -168,15 +169,17 @@ static void gfar_init_rxbdp(struct gfar_priv_rx_q *rx_queue, struct rxbd8 *bdp, + bdp->lstatus = cpu_to_be32(lstatus); + } + +-static void gfar_init_bds(struct net_device *ndev) ++static int gfar_init_bds(struct net_device *ndev) + { + struct gfar_private *priv = netdev_priv(ndev); + struct gfar __iomem *regs = priv->gfargrp[0].regs; + struct gfar_priv_tx_q *tx_queue = NULL; + struct gfar_priv_rx_q *rx_queue = NULL; + struct txbd8 *txbdp; ++ struct rxbd8 *rxbdp; + u32 __iomem *rfbptr; + int i, j; ++ dma_addr_t bufaddr; + + for (i = 0; i < priv->num_tx_queues; i++) { + tx_queue = priv->tx_queue[i]; +@@ -204,26 +207,40 @@ static void gfar_init_bds(struct net_device *ndev) + rfbptr = ®s->rfbptr0; + for (i = 0; i < priv->num_rx_queues; i++) { + rx_queue = priv->rx_queue[i]; ++ rx_queue->cur_rx = rx_queue->rx_bd_base; ++ rx_queue->skb_currx = 0; ++ rxbdp = rx_queue->rx_bd_base; + +- rx_queue->next_to_clean = 0; +- rx_queue->next_to_use = 0; +- rx_queue->next_to_alloc = 0; ++ for (j = 0; j < rx_queue->rx_ring_size; j++) { ++ struct sk_buff *skb = rx_queue->rx_skbuff[j]; + +- /* make sure next_to_clean != next_to_use after this +- * by leaving at least 1 unused descriptor +- */ +- gfar_alloc_rx_buffs(rx_queue, gfar_rxbd_unused(rx_queue)); ++ if (skb) { ++ bufaddr = be32_to_cpu(rxbdp->bufPtr); ++ } else { ++ skb = gfar_new_skb(ndev, &bufaddr); ++ if (!skb) { ++ netdev_err(ndev, "Can't allocate RX buffers\n"); ++ return -ENOMEM; ++ } ++ rx_queue->rx_skbuff[j] = skb; ++ } ++ ++ gfar_init_rxbdp(rx_queue, rxbdp, bufaddr); ++ rxbdp++; ++ } + + rx_queue->rfbptr = rfbptr; + rfbptr += 2; + } ++ ++ return 0; + } + + static int gfar_alloc_skb_resources(struct net_device *ndev) + { + void *vaddr; + dma_addr_t addr; +- int i, j; ++ int i, j, k; + struct gfar_private *priv = netdev_priv(ndev); + struct device *dev = priv->dev; + struct gfar_priv_tx_q *tx_queue = NULL; +@@ -262,8 +279,7 @@ static int gfar_alloc_skb_resources(struct net_device *ndev) + rx_queue = priv->rx_queue[i]; + rx_queue->rx_bd_base = vaddr; + rx_queue->rx_bd_dma_base = addr; +- rx_queue->ndev = ndev; +- rx_queue->dev = dev; ++ rx_queue->dev = ndev; + addr += sizeof(struct rxbd8) * rx_queue->rx_ring_size; + vaddr += sizeof(struct rxbd8) * rx_queue->rx_ring_size; + } +@@ -278,20 +294,25 @@ static int gfar_alloc_skb_resources(struct net_device *ndev) + if (!tx_queue->tx_skbuff) + goto cleanup; + +- for (j = 0; j < tx_queue->tx_ring_size; j++) +- tx_queue->tx_skbuff[j] = NULL; ++ for (k = 0; k < tx_queue->tx_ring_size; k++) ++ tx_queue->tx_skbuff[k] = NULL; + } + + for (i = 0; i < priv->num_rx_queues; i++) { + rx_queue = priv->rx_queue[i]; +- rx_queue->rx_buff = kcalloc(rx_queue->rx_ring_size, +- sizeof(*rx_queue->rx_buff), +- GFP_KERNEL); +- if (!rx_queue->rx_buff) ++ rx_queue->rx_skbuff = ++ kmalloc_array(rx_queue->rx_ring_size, ++ sizeof(*rx_queue->rx_skbuff), ++ GFP_KERNEL); ++ if (!rx_queue->rx_skbuff) + goto cleanup; ++ ++ for (j = 0; j < rx_queue->rx_ring_size; j++) ++ rx_queue->rx_skbuff[j] = NULL; + } + +- gfar_init_bds(ndev); ++ if (gfar_init_bds(ndev)) ++ goto cleanup; + + return 0; + +@@ -333,16 +354,28 @@ static void gfar_init_rqprm(struct gfar_private *priv) + } + } + +-static void gfar_rx_offload_en(struct gfar_private *priv) ++static void gfar_rx_buff_size_config(struct gfar_private *priv) + { ++ int frame_size = priv->ndev->mtu + ETH_HLEN + ETH_FCS_LEN; ++ + /* set this when rx hw offload (TOE) functions are being used */ + priv->uses_rxfcb = 0; + + if (priv->ndev->features & (NETIF_F_RXCSUM | NETIF_F_HW_VLAN_CTAG_RX)) + priv->uses_rxfcb = 1; + +- if (priv->hwts_rx_en || priv->rx_filer_enable) ++ if (priv->hwts_rx_en) + priv->uses_rxfcb = 1; ++ ++ if (priv->uses_rxfcb) ++ frame_size += GMAC_FCB_LEN; ++ ++ frame_size += priv->padding; ++ ++ frame_size = (frame_size & ~(INCREMENTAL_BUFFER_SIZE - 1)) + ++ INCREMENTAL_BUFFER_SIZE; ++ ++ priv->rx_buffer_size = frame_size; + } + + static void gfar_mac_rx_config(struct gfar_private *priv) +@@ -351,7 +384,7 @@ static void gfar_mac_rx_config(struct gfar_private *priv) + u32 rctrl = 0; + + if (priv->rx_filer_enable) { +- rctrl |= RCTRL_FILREN | RCTRL_PRSDEP_INIT; ++ rctrl |= RCTRL_FILREN; + /* Program the RIR0 reg with the required distribution */ + if (priv->poll_mode == GFAR_SQ_POLLING) + gfar_write(®s->rir0, DEFAULT_2RXQ_RIR0); +@@ -483,15 +516,6 @@ static struct net_device_stats *gfar_get_stats(struct net_device *dev) + return &dev->stats; + } + +-static int gfar_set_mac_addr(struct net_device *dev, void *p) +-{ +- eth_mac_addr(dev, p); +- +- gfar_set_mac_for_addr(dev, 0, dev->dev_addr); +- +- return 0; +-} +- + static const struct net_device_ops gfar_netdev_ops = { + .ndo_open = gfar_enet_open, + .ndo_start_xmit = gfar_start_xmit, +@@ -502,7 +526,7 @@ static const struct net_device_ops gfar_netdev_ops = { + .ndo_tx_timeout = gfar_timeout, + .ndo_do_ioctl = gfar_ioctl, + .ndo_get_stats = gfar_get_stats, +- .ndo_set_mac_address = gfar_set_mac_addr, ++ .ndo_set_mac_address = eth_mac_addr, + .ndo_validate_addr = eth_validate_addr, + #ifdef CONFIG_NET_POLL_CONTROLLER + .ndo_poll_controller = gfar_netpoll, +@@ -532,6 +556,22 @@ static void gfar_ints_enable(struct gfar_private *priv) + } + } + ++static void lock_tx_qs(struct gfar_private *priv) ++{ ++ int i; ++ ++ for (i = 0; i < priv->num_tx_queues; i++) ++ spin_lock(&priv->tx_queue[i]->txlock); ++} ++ ++static void unlock_tx_qs(struct gfar_private *priv) ++{ ++ int i; ++ ++ for (i = 0; i < priv->num_tx_queues; i++) ++ spin_unlock(&priv->tx_queue[i]->txlock); ++} ++ + static int gfar_alloc_tx_queues(struct gfar_private *priv) + { + int i; +@@ -560,8 +600,9 @@ static int gfar_alloc_rx_queues(struct gfar_private *priv) + if (!priv->rx_queue[i]) + return -ENOMEM; + ++ priv->rx_queue[i]->rx_skbuff = NULL; + priv->rx_queue[i]->qindex = i; +- priv->rx_queue[i]->ndev = priv->ndev; ++ priv->rx_queue[i]->dev = priv->ndev; + } + return 0; + } +@@ -647,9 +688,9 @@ static int gfar_parse_group(struct device_node *np, + if (model && strcasecmp(model, "FEC")) { + gfar_irq(grp, RX)->irq = irq_of_parse_and_map(np, 1); + gfar_irq(grp, ER)->irq = irq_of_parse_and_map(np, 2); +- if (!gfar_irq(grp, TX)->irq || +- !gfar_irq(grp, RX)->irq || +- !gfar_irq(grp, ER)->irq) ++ if (gfar_irq(grp, TX)->irq == NO_IRQ || ++ gfar_irq(grp, RX)->irq == NO_IRQ || ++ gfar_irq(grp, ER)->irq == NO_IRQ) + return -EINVAL; + } + +@@ -738,6 +779,7 @@ static int gfar_of_init(struct platform_device *ofdev, struct net_device **pdev) + struct gfar_private *priv = NULL; + struct device_node *np = ofdev->dev.of_node; + struct device_node *child = NULL; ++ struct property *stash; + u32 stash_len = 0; + u32 stash_idx = 0; + unsigned int num_tx_qs, num_rx_qs; +@@ -853,7 +895,9 @@ static int gfar_of_init(struct platform_device *ofdev, struct net_device **pdev) + goto err_grp_init; + } + +- if (of_property_read_bool(np, "bd-stash")) { ++ stash = of_find_property(np, "bd-stash", NULL); ++ ++ if (stash) { + priv->device_flags |= FSL_GIANFAR_DEV_HAS_BD_STASHING; + priv->bd_stash_en = 1; + } +@@ -891,8 +935,7 @@ static int gfar_of_init(struct platform_device *ofdev, struct net_device **pdev) + FSL_GIANFAR_DEV_HAS_VLAN | + FSL_GIANFAR_DEV_HAS_MAGIC_PACKET | + FSL_GIANFAR_DEV_HAS_EXTENDED_HASH | +- FSL_GIANFAR_DEV_HAS_TIMER | +- FSL_GIANFAR_DEV_HAS_RX_FILER; ++ FSL_GIANFAR_DEV_HAS_TIMER; + + err = of_property_read_string(np, "phy-connection-type", &ctype); + +@@ -905,9 +948,6 @@ static int gfar_of_init(struct platform_device *ofdev, struct net_device **pdev) + if (of_find_property(np, "fsl,magic-packet", NULL)) + priv->device_flags |= FSL_GIANFAR_DEV_HAS_MAGIC_PACKET; + +- if (of_get_property(np, "fsl,wake-on-filer", NULL)) +- priv->device_flags |= FSL_GIANFAR_DEV_HAS_WAKE_ON_FILER; +- + priv->phy_node = of_parse_phandle(np, "phy-handle", 0); + + /* In the case of a fixed PHY, the DT node associated +@@ -999,7 +1039,7 @@ static int gfar_hwtstamp_get(struct net_device *netdev, struct ifreq *ifr) + + static int gfar_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) + { +- struct phy_device *phydev = dev->phydev; ++ struct gfar_private *priv = netdev_priv(dev); + + if (!netif_running(dev)) + return -EINVAL; +@@ -1009,10 +1049,10 @@ static int gfar_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) + if (cmd == SIOCGHWTSTAMP) + return gfar_hwtstamp_get(dev, rq); + +- if (!phydev) ++ if (!priv->phydev) + return -ENODEV; + +- return phy_mii_ioctl(phydev, rq, cmd); ++ return phy_mii_ioctl(priv->phydev, rq, cmd); + } + + static u32 cluster_entry_per_class(struct gfar_private *priv, u32 rqfar, +@@ -1111,10 +1151,8 @@ static void __gfar_detect_errata_85xx(struct gfar_private *priv) + + if ((SVR_SOC_VER(svr) == SVR_8548) && (SVR_REV(svr) == 0x20)) + priv->errata |= GFAR_ERRATA_12; +- /* P2020/P1010 Rev 1; MPC8548 Rev 2 */ + if (((SVR_SOC_VER(svr) == SVR_P2020) && (SVR_REV(svr) < 0x20)) || +- ((SVR_SOC_VER(svr) == SVR_P2010) && (SVR_REV(svr) < 0x20)) || +- ((SVR_SOC_VER(svr) == SVR_8548) && (SVR_REV(svr) < 0x31))) ++ ((SVR_SOC_VER(svr) == SVR_P2010) && (SVR_REV(svr) < 0x20))) + priv->errata |= GFAR_ERRATA_76; /* aka eTSEC 20 */ + } + #endif +@@ -1156,11 +1194,12 @@ void gfar_mac_reset(struct gfar_private *priv) + + udelay(3); + +- gfar_rx_offload_en(priv); ++ /* Compute rx_buff_size based on config flags */ ++ gfar_rx_buff_size_config(priv); + + /* Initialize the max receive frame/buffer lengths */ +- gfar_write(®s->maxfrm, GFAR_JUMBO_FRAME_SIZE); +- gfar_write(®s->mrblr, GFAR_RXB_SIZE); ++ gfar_write(®s->maxfrm, priv->rx_buffer_size); ++ gfar_write(®s->mrblr, priv->rx_buffer_size); + + /* Initialize the Minimum Frame Length Register */ + gfar_write(®s->minflr, MINFLR_INIT_SETTINGS); +@@ -1168,11 +1207,12 @@ void gfar_mac_reset(struct gfar_private *priv) + /* Initialize MACCFG2. */ + tempval = MACCFG2_INIT_SETTINGS; + +- /* eTSEC74 erratum: Rx frames of length MAXFRM or MAXFRM-1 +- * are marked as truncated. Avoid this by MACCFG2[Huge Frame]=1, +- * and by checking RxBD[LG] and discarding larger than MAXFRM. ++ /* If the mtu is larger than the max size for standard ++ * ethernet frames (ie, a jumbo frame), then set maccfg2 ++ * to allow huge frames, and to check the length + */ +- if (gfar_has_errata(priv, GFAR_ERRATA_74)) ++ if (priv->rx_buffer_size > DEFAULT_RX_BUFFER_SIZE || ++ gfar_has_errata(priv, GFAR_ERRATA_74)) + tempval |= MACCFG2_HUGEFRAME | MACCFG2_LENGTHCHECK; + + gfar_write(®s->maccfg2, tempval); +@@ -1312,7 +1352,6 @@ static void gfar_init_addr_hash_table(struct gfar_private *priv) + */ + static int gfar_probe(struct platform_device *ofdev) + { +- struct device_node *np = ofdev->dev.of_node; + struct net_device *dev = NULL; + struct gfar_private *priv = NULL; + int err = 0, i; +@@ -1328,6 +1367,7 @@ static int gfar_probe(struct platform_device *ofdev) + priv->dev = &ofdev->dev; + SET_NETDEV_DEV(dev, &ofdev->dev); + ++ spin_lock_init(&priv->bflock); + INIT_WORK(&priv->reset_task, gfar_reset_task); + + platform_set_drvdata(ofdev, priv); +@@ -1348,12 +1388,12 @@ static int gfar_probe(struct platform_device *ofdev) + if (priv->poll_mode == GFAR_SQ_POLLING) { + netif_napi_add(dev, &priv->gfargrp[i].napi_rx, + gfar_poll_rx_sq, GFAR_DEV_WEIGHT); +- netif_tx_napi_add(dev, &priv->gfargrp[i].napi_tx, ++ netif_napi_add(dev, &priv->gfargrp[i].napi_tx, + gfar_poll_tx_sq, 2); + } else { + netif_napi_add(dev, &priv->gfargrp[i].napi_rx, + gfar_poll_rx, GFAR_DEV_WEIGHT); +- netif_tx_napi_add(dev, &priv->gfargrp[i].napi_tx, ++ netif_napi_add(dev, &priv->gfargrp[i].napi_tx, + gfar_poll_tx, 2); + } + } +@@ -1371,8 +1411,6 @@ static int gfar_probe(struct platform_device *ofdev) + dev->features |= NETIF_F_HW_VLAN_CTAG_RX; + } + +- dev->priv_flags |= IFF_LIVE_ADDR_CHANGE; +- + gfar_init_addr_hash_table(priv); + + /* Insert receive time stamps into padding alignment bytes */ +@@ -1383,6 +1421,8 @@ static int gfar_probe(struct platform_device *ofdev) + priv->device_flags & FSL_GIANFAR_DEV_HAS_TIMER) + dev->needed_headroom = GMAC_FCB_LEN; + ++ priv->rx_buffer_size = DEFAULT_RX_BUFFER_SIZE; ++ + /* Initializing some of the rx/tx queue level parameters */ + for (i = 0; i < priv->num_tx_queues; i++) { + priv->tx_queue[i]->tx_ring_size = DEFAULT_TX_RING_SIZE; +@@ -1397,9 +1437,8 @@ static int gfar_probe(struct platform_device *ofdev) + priv->rx_queue[i]->rxic = DEFAULT_RXIC; + } + +- /* Always enable rx filer if available */ +- priv->rx_filer_enable = +- (priv->device_flags & FSL_GIANFAR_DEV_HAS_RX_FILER) ? 1 : 0; ++ /* always enable rx filer */ ++ priv->rx_filer_enable = 1; + /* Enable most messages by default */ + priv->msg_enable = (NETIF_MSG_IFUP << 1 ) - 1; + /* use pritority h/w tx queue scheduling for single queue devices */ +@@ -1420,14 +1459,9 @@ static int gfar_probe(struct platform_device *ofdev) + goto register_fail; + } + +- if (priv->device_flags & FSL_GIANFAR_DEV_HAS_MAGIC_PACKET) +- priv->wol_supported |= GFAR_WOL_MAGIC; +- +- if ((priv->device_flags & FSL_GIANFAR_DEV_HAS_WAKE_ON_FILER) && +- priv->rx_filer_enable) +- priv->wol_supported |= GFAR_WOL_FILER_UCAST; +- +- device_set_wakeup_capable(&ofdev->dev, priv->wol_supported); ++ device_init_wakeup(&dev->dev, ++ priv->device_flags & ++ FSL_GIANFAR_DEV_HAS_MAGIC_PACKET); + + /* fill out IRQ number and name fields */ + for (i = 0; i < priv->num_grps; i++) { +@@ -1463,8 +1497,6 @@ static int gfar_probe(struct platform_device *ofdev) + return 0; + + register_fail: +- if (of_phy_is_fixed_link(np)) +- of_phy_deregister_fixed_link(np); + unmap_group_regs(priv); + gfar_free_rx_queues(priv); + gfar_free_tx_queues(priv); +@@ -1477,16 +1509,11 @@ static int gfar_probe(struct platform_device *ofdev) + static int gfar_remove(struct platform_device *ofdev) + { + struct gfar_private *priv = platform_get_drvdata(ofdev); +- struct device_node *np = ofdev->dev.of_node; + + of_node_put(priv->phy_node); + of_node_put(priv->tbi_node); + + unregister_netdev(priv->ndev); +- +- if (of_phy_is_fixed_link(np)) +- of_phy_deregister_fixed_link(np); +- + unmap_group_regs(priv); + gfar_free_rx_queues(priv); + gfar_free_tx_queues(priv); +@@ -1497,153 +1524,53 @@ static int gfar_remove(struct platform_device *ofdev) + + #ifdef CONFIG_PM + +-static void __gfar_filer_disable(struct gfar_private *priv) +-{ +- struct gfar __iomem *regs = priv->gfargrp[0].regs; +- u32 temp; +- +- temp = gfar_read(®s->rctrl); +- temp &= ~(RCTRL_FILREN | RCTRL_PRSDEP_INIT); +- gfar_write(®s->rctrl, temp); +-} +- +-static void __gfar_filer_enable(struct gfar_private *priv) +-{ +- struct gfar __iomem *regs = priv->gfargrp[0].regs; +- u32 temp; +- +- temp = gfar_read(®s->rctrl); +- temp |= RCTRL_FILREN | RCTRL_PRSDEP_INIT; +- gfar_write(®s->rctrl, temp); +-} +- +-/* Filer rules implementing wol capabilities */ +-static void gfar_filer_config_wol(struct gfar_private *priv) +-{ +- unsigned int i; +- u32 rqfcr; +- +- __gfar_filer_disable(priv); +- +- /* clear the filer table, reject any packet by default */ +- rqfcr = RQFCR_RJE | RQFCR_CMP_MATCH; +- for (i = 0; i <= MAX_FILER_IDX; i++) +- gfar_write_filer(priv, i, rqfcr, 0); +- +- i = 0; +- if (priv->wol_opts & GFAR_WOL_FILER_UCAST) { +- /* unicast packet, accept it */ +- struct net_device *ndev = priv->ndev; +- /* get the default rx queue index */ +- u8 qindex = (u8)priv->gfargrp[0].rx_queue->qindex; +- u32 dest_mac_addr = (ndev->dev_addr[0] << 16) | +- (ndev->dev_addr[1] << 8) | +- ndev->dev_addr[2]; +- +- rqfcr = (qindex << 10) | RQFCR_AND | +- RQFCR_CMP_EXACT | RQFCR_PID_DAH; +- +- gfar_write_filer(priv, i++, rqfcr, dest_mac_addr); +- +- dest_mac_addr = (ndev->dev_addr[3] << 16) | +- (ndev->dev_addr[4] << 8) | +- ndev->dev_addr[5]; +- rqfcr = (qindex << 10) | RQFCR_GPI | +- RQFCR_CMP_EXACT | RQFCR_PID_DAL; +- gfar_write_filer(priv, i++, rqfcr, dest_mac_addr); +- } +- +- __gfar_filer_enable(priv); +-} +- +-static void gfar_filer_restore_table(struct gfar_private *priv) +-{ +- u32 rqfcr, rqfpr; +- unsigned int i; +- +- __gfar_filer_disable(priv); +- +- for (i = 0; i <= MAX_FILER_IDX; i++) { +- rqfcr = priv->ftp_rqfcr[i]; +- rqfpr = priv->ftp_rqfpr[i]; +- gfar_write_filer(priv, i, rqfcr, rqfpr); +- } +- +- __gfar_filer_enable(priv); +-} +- +-/* gfar_start() for Rx only and with the FGPI filer interrupt enabled */ +-static void gfar_start_wol_filer(struct gfar_private *priv) +-{ +- struct gfar __iomem *regs = priv->gfargrp[0].regs; +- u32 tempval; +- int i = 0; +- +- /* Enable Rx hw queues */ +- gfar_write(®s->rqueue, priv->rqueue); +- +- /* Initialize DMACTRL to have WWR and WOP */ +- tempval = gfar_read(®s->dmactrl); +- tempval |= DMACTRL_INIT_SETTINGS; +- gfar_write(®s->dmactrl, tempval); +- +- /* Make sure we aren't stopped */ +- tempval = gfar_read(®s->dmactrl); +- tempval &= ~DMACTRL_GRS; +- gfar_write(®s->dmactrl, tempval); +- +- for (i = 0; i < priv->num_grps; i++) { +- regs = priv->gfargrp[i].regs; +- /* Clear RHLT, so that the DMA starts polling now */ +- gfar_write(®s->rstat, priv->gfargrp[i].rstat); +- /* enable the Filer General Purpose Interrupt */ +- gfar_write(®s->imask, IMASK_FGPI); +- } +- +- /* Enable Rx DMA */ +- tempval = gfar_read(®s->maccfg1); +- tempval |= MACCFG1_RX_EN; +- gfar_write(®s->maccfg1, tempval); +-} +- + static int gfar_suspend(struct device *dev) + { + struct gfar_private *priv = dev_get_drvdata(dev); + struct net_device *ndev = priv->ndev; + struct gfar __iomem *regs = priv->gfargrp[0].regs; ++ unsigned long flags; + u32 tempval; +- u16 wol = priv->wol_opts; + +- if (!netif_running(ndev)) +- return 0; ++ int magic_packet = priv->wol_en && ++ (priv->device_flags & ++ FSL_GIANFAR_DEV_HAS_MAGIC_PACKET); + +- disable_napi(priv); +- netif_tx_lock(ndev); + netif_device_detach(ndev); +- netif_tx_unlock(ndev); + +- gfar_halt(priv); ++ if (netif_running(ndev)) { + +- if (wol & GFAR_WOL_MAGIC) { +- /* Enable interrupt on Magic Packet */ +- gfar_write(®s->imask, IMASK_MAG); ++ local_irq_save(flags); ++ lock_tx_qs(priv); + +- /* Enable Magic Packet mode */ +- tempval = gfar_read(®s->maccfg2); +- tempval |= MACCFG2_MPEN; +- gfar_write(®s->maccfg2, tempval); ++ gfar_halt_nodisable(priv); + +- /* re-enable the Rx block */ ++ /* Disable Tx, and Rx if wake-on-LAN is disabled. */ + tempval = gfar_read(®s->maccfg1); +- tempval |= MACCFG1_RX_EN; ++ ++ tempval &= ~MACCFG1_TX_EN; ++ ++ if (!magic_packet) ++ tempval &= ~MACCFG1_RX_EN; ++ + gfar_write(®s->maccfg1, tempval); + +- } else if (wol & GFAR_WOL_FILER_UCAST) { +- gfar_filer_config_wol(priv); +- gfar_start_wol_filer(priv); ++ unlock_tx_qs(priv); ++ local_irq_restore(flags); + +- } else { +- phy_stop(ndev->phydev); ++ disable_napi(priv); ++ ++ if (magic_packet) { ++ /* Enable interrupt on Magic Packet */ ++ gfar_write(®s->imask, IMASK_MAG); ++ ++ /* Enable Magic Packet mode */ ++ tempval = gfar_read(®s->maccfg2); ++ tempval |= MACCFG2_MPEN; ++ gfar_write(®s->maccfg2, tempval); ++ } else { ++ phy_stop(priv->phydev); ++ } + } + + return 0; +@@ -1654,30 +1581,37 @@ static int gfar_resume(struct device *dev) + struct gfar_private *priv = dev_get_drvdata(dev); + struct net_device *ndev = priv->ndev; + struct gfar __iomem *regs = priv->gfargrp[0].regs; ++ unsigned long flags; + u32 tempval; +- u16 wol = priv->wol_opts; ++ int magic_packet = priv->wol_en && ++ (priv->device_flags & ++ FSL_GIANFAR_DEV_HAS_MAGIC_PACKET); + +- if (!netif_running(ndev)) ++ if (!netif_running(ndev)) { ++ netif_device_attach(ndev); + return 0; ++ } + +- if (wol & GFAR_WOL_MAGIC) { +- /* Disable Magic Packet mode */ +- tempval = gfar_read(®s->maccfg2); +- tempval &= ~MACCFG2_MPEN; +- gfar_write(®s->maccfg2, tempval); ++ if (!magic_packet && priv->phydev) ++ phy_start(priv->phydev); + +- } else if (wol & GFAR_WOL_FILER_UCAST) { +- /* need to stop rx only, tx is already down */ +- gfar_halt(priv); +- gfar_filer_restore_table(priv); ++ /* Disable Magic Packet mode, in case something ++ * else woke us up. ++ */ ++ local_irq_save(flags); ++ lock_tx_qs(priv); + +- } else { +- phy_start(ndev->phydev); +- } ++ tempval = gfar_read(®s->maccfg2); ++ tempval &= ~MACCFG2_MPEN; ++ gfar_write(®s->maccfg2, tempval); + + gfar_start(priv); + ++ unlock_tx_qs(priv); ++ local_irq_restore(flags); ++ + netif_device_attach(ndev); ++ + enable_napi(priv); + + return 0; +@@ -1694,7 +1628,10 @@ static int gfar_restore(struct device *dev) + return 0; + } + +- gfar_init_bds(ndev); ++ if (gfar_init_bds(ndev)) { ++ free_skb_resources(priv); ++ return -ENOMEM; ++ } + + gfar_mac_reset(priv); + +@@ -1706,8 +1643,8 @@ static int gfar_restore(struct device *dev) + priv->oldspeed = 0; + priv->oldduplex = -1; + +- if (ndev->phydev) +- phy_start(ndev->phydev); ++ if (priv->phydev) ++ phy_start(priv->phydev); + + netif_device_attach(ndev); + enable_napi(priv); +@@ -1786,7 +1723,6 @@ static int init_phy(struct net_device *dev) + priv->device_flags & FSL_GIANFAR_DEV_HAS_GIGABIT ? + GFAR_SUPPORTED_GBIT : 0; + phy_interface_t interface; +- struct phy_device *phydev; + + priv->oldlink = 0; + priv->oldspeed = 0; +@@ -1794,9 +1730,9 @@ static int init_phy(struct net_device *dev) + + interface = gfar_get_interface(dev); + +- phydev = of_phy_connect(dev, priv->phy_node, &adjust_link, 0, +- interface); +- if (!phydev) { ++ priv->phydev = of_phy_connect(dev, priv->phy_node, &adjust_link, 0, ++ interface); ++ if (!priv->phydev) { + dev_err(&dev->dev, "could not attach to PHY\n"); + return -ENODEV; + } +@@ -1805,11 +1741,11 @@ static int init_phy(struct net_device *dev) + gfar_configure_serdes(dev); + + /* Remove any features not supported by the controller */ +- phydev->supported &= (GFAR_SUPPORTED | gigabit_support); +- phydev->advertising = phydev->supported; ++ priv->phydev->supported &= (GFAR_SUPPORTED | gigabit_support); ++ priv->phydev->advertising = priv->phydev->supported; + + /* Add support for flow control, but don't advertise it by default */ +- phydev->supported |= (SUPPORTED_Pause | SUPPORTED_Asym_Pause); ++ priv->phydev->supported |= (SUPPORTED_Pause | SUPPORTED_Asym_Pause); + + return 0; + } +@@ -1844,10 +1780,8 @@ static void gfar_configure_serdes(struct net_device *dev) + * everything for us? Resetting it takes the link down and requires + * several seconds for it to come back. + */ +- if (phy_read(tbiphy, MII_BMSR) & BMSR_LSTATUS) { +- put_device(&tbiphy->mdio.dev); ++ if (phy_read(tbiphy, MII_BMSR) & BMSR_LSTATUS) + return; +- } + + /* Single clk mode, mii mode off(for serdes communication) */ + phy_write(tbiphy, MII_TBICON, TBICON_CLK_SELECT); +@@ -1859,8 +1793,6 @@ static void gfar_configure_serdes(struct net_device *dev) + phy_write(tbiphy, MII_BMCR, + BMCR_ANENABLE | BMCR_ANRESTART | BMCR_FULLDPLX | + BMCR_SPEED1000); +- +- put_device(&tbiphy->mdio.dev); + } + + static int __gfar_is_rx_idle(struct gfar_private *priv) +@@ -1953,7 +1885,7 @@ void stop_gfar(struct net_device *dev) + /* disable ints and gracefully shut down Rx/Tx DMA */ + gfar_halt(priv); + +- phy_stop(dev->phydev); ++ phy_stop(priv->phydev); + + free_skb_resources(priv); + } +@@ -1990,32 +1922,26 @@ static void free_skb_tx_queue(struct gfar_priv_tx_q *tx_queue) + + static void free_skb_rx_queue(struct gfar_priv_rx_q *rx_queue) + { ++ struct rxbd8 *rxbdp; ++ struct gfar_private *priv = netdev_priv(rx_queue->dev); + int i; + +- struct rxbd8 *rxbdp = rx_queue->rx_bd_base; +- +- if (rx_queue->skb) +- dev_kfree_skb(rx_queue->skb); ++ rxbdp = rx_queue->rx_bd_base; + + for (i = 0; i < rx_queue->rx_ring_size; i++) { +- struct gfar_rx_buff *rxb = &rx_queue->rx_buff[i]; +- ++ if (rx_queue->rx_skbuff[i]) { ++ dma_unmap_single(priv->dev, be32_to_cpu(rxbdp->bufPtr), ++ priv->rx_buffer_size, ++ DMA_FROM_DEVICE); ++ dev_kfree_skb_any(rx_queue->rx_skbuff[i]); ++ rx_queue->rx_skbuff[i] = NULL; ++ } + rxbdp->lstatus = 0; + rxbdp->bufPtr = 0; + rxbdp++; +- +- if (!rxb->page) +- continue; +- +- dma_unmap_single(rx_queue->dev, rxb->dma, +- PAGE_SIZE, DMA_FROM_DEVICE); +- __free_page(rxb->page); +- +- rxb->page = NULL; + } +- +- kfree(rx_queue->rx_buff); +- rx_queue->rx_buff = NULL; ++ kfree(rx_queue->rx_skbuff); ++ rx_queue->rx_skbuff = NULL; + } + + /* If there are any tx skbs or rx skbs still around, free them. +@@ -2040,7 +1966,7 @@ static void free_skb_resources(struct gfar_private *priv) + + for (i = 0; i < priv->num_rx_queues; i++) { + rx_queue = priv->rx_queue[i]; +- if (rx_queue->rx_buff) ++ if (rx_queue->rx_skbuff) + free_skb_rx_queue(rx_queue); + } + +@@ -2085,7 +2011,7 @@ void gfar_start(struct gfar_private *priv) + + gfar_ints_enable(priv); + +- netif_trans_update(priv->ndev); /* prevent tx timeout */ ++ priv->ndev->trans_start = jiffies; /* prevent tx timeout */ + } + + static void free_grp_irqs(struct gfar_priv_grp *grp) +@@ -2116,8 +2042,6 @@ static int register_grp_irqs(struct gfar_priv_grp *grp) + + goto err_irq_fail; + } +- enable_irq_wake(gfar_irq(grp, ER)->irq); +- + err = request_irq(gfar_irq(grp, TX)->irq, gfar_transmit, 0, + gfar_irq(grp, TX)->name, grp); + if (err < 0) { +@@ -2132,8 +2056,6 @@ static int register_grp_irqs(struct gfar_priv_grp *grp) + gfar_irq(grp, RX)->irq); + goto rx_irq_fail; + } +- enable_irq_wake(gfar_irq(grp, RX)->irq); +- + } else { + err = request_irq(gfar_irq(grp, TX)->irq, gfar_interrupt, 0, + gfar_irq(grp, TX)->name, grp); +@@ -2142,7 +2064,6 @@ static int register_grp_irqs(struct gfar_priv_grp *grp) + gfar_irq(grp, TX)->irq); + goto err_irq_fail; + } +- enable_irq_wake(gfar_irq(grp, TX)->irq); + } + + return 0; +@@ -2208,12 +2129,7 @@ int startup_gfar(struct net_device *ndev) + /* Start Rx/Tx DMA and enable the interrupts */ + gfar_start(priv); + +- /* force link state update after mac reset */ +- priv->oldlink = 0; +- priv->oldspeed = 0; +- priv->oldduplex = -1; +- +- phy_start(ndev->phydev); ++ phy_start(priv->phydev); + + enable_napi(priv); + +@@ -2242,6 +2158,8 @@ static int gfar_enet_open(struct net_device *dev) + if (err) + return err; + ++ device_set_wakeup_enable(&dev->dev, priv->wol_en); ++ + return err; + } + +@@ -2283,7 +2201,7 @@ static inline void gfar_tx_checksum(struct sk_buff *skb, struct txfcb *fcb, + fcb->flags = flags; + } + +-static inline void gfar_tx_vlan(struct sk_buff *skb, struct txfcb *fcb) ++void inline gfar_tx_vlan(struct sk_buff *skb, struct txfcb *fcb) + { + fcb->flags |= TXFCB_VLN; + fcb->vlctl = cpu_to_be16(skb_vlan_tag_get(skb)); +@@ -2333,10 +2251,10 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev) + struct txfcb *fcb = NULL; + struct txbd8 *txbdp, *txbdp_start, *base, *txbdp_tstamp = NULL; + u32 lstatus; +- skb_frag_t *frag; + int i, rq = 0; + int do_tstamp, do_csum, do_vlan; + u32 bufaddr; ++ unsigned long flags; + unsigned int nr_frags, nr_txbds, bytes_sent, fcb_len = 0; + + rq = skb->queue_mapping; +@@ -2401,6 +2319,52 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev) + txbdp = txbdp_start = tx_queue->cur_tx; + lstatus = be32_to_cpu(txbdp->lstatus); + ++ /* Time stamp insertion requires one additional TxBD */ ++ if (unlikely(do_tstamp)) ++ txbdp_tstamp = txbdp = next_txbd(txbdp, base, ++ tx_queue->tx_ring_size); ++ ++ if (nr_frags == 0) { ++ if (unlikely(do_tstamp)) { ++ u32 lstatus_ts = be32_to_cpu(txbdp_tstamp->lstatus); ++ ++ lstatus_ts |= BD_LFLAG(TXBD_LAST | TXBD_INTERRUPT); ++ txbdp_tstamp->lstatus = cpu_to_be32(lstatus_ts); ++ } else { ++ lstatus |= BD_LFLAG(TXBD_LAST | TXBD_INTERRUPT); ++ } ++ } else { ++ /* Place the fragment addresses and lengths into the TxBDs */ ++ for (i = 0; i < nr_frags; i++) { ++ unsigned int frag_len; ++ /* Point at the next BD, wrapping as needed */ ++ txbdp = next_txbd(txbdp, base, tx_queue->tx_ring_size); ++ ++ frag_len = skb_shinfo(skb)->frags[i].size; ++ ++ lstatus = be32_to_cpu(txbdp->lstatus) | frag_len | ++ BD_LFLAG(TXBD_READY); ++ ++ /* Handle the last BD specially */ ++ if (i == nr_frags - 1) ++ lstatus |= BD_LFLAG(TXBD_LAST | TXBD_INTERRUPT); ++ ++ bufaddr = skb_frag_dma_map(priv->dev, ++ &skb_shinfo(skb)->frags[i], ++ 0, ++ frag_len, ++ DMA_TO_DEVICE); ++ if (unlikely(dma_mapping_error(priv->dev, bufaddr))) ++ goto dma_map_err; ++ ++ /* set the TxBD length and buffer pointer */ ++ txbdp->bufPtr = cpu_to_be32(bufaddr); ++ txbdp->lstatus = cpu_to_be32(lstatus); ++ } ++ ++ lstatus = be32_to_cpu(txbdp_start->lstatus); ++ } ++ + /* Add TxPAL between FCB and frame if required */ + if (unlikely(do_tstamp)) { + skb_push(skb, GMAC_TXPAL_LEN); +@@ -2435,6 +2399,12 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev) + if (do_vlan) + gfar_tx_vlan(skb, fcb); + ++ /* Setup tx hardware time stamping if requested */ ++ if (unlikely(do_tstamp)) { ++ skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS; ++ fcb->ptp = 1; ++ } ++ + bufaddr = dma_map_single(priv->dev, skb->data, skb_headlen(skb), + DMA_TO_DEVICE); + if (unlikely(dma_mapping_error(priv->dev, bufaddr))) +@@ -2442,47 +2412,6 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev) + + txbdp_start->bufPtr = cpu_to_be32(bufaddr); + +- /* Time stamp insertion requires one additional TxBD */ +- if (unlikely(do_tstamp)) +- txbdp_tstamp = txbdp = next_txbd(txbdp, base, +- tx_queue->tx_ring_size); +- +- if (likely(!nr_frags)) { +- if (likely(!do_tstamp)) +- lstatus |= BD_LFLAG(TXBD_LAST | TXBD_INTERRUPT); +- } else { +- u32 lstatus_start = lstatus; +- +- /* Place the fragment addresses and lengths into the TxBDs */ +- frag = &skb_shinfo(skb)->frags[0]; +- for (i = 0; i < nr_frags; i++, frag++) { +- unsigned int size; +- +- /* Point at the next BD, wrapping as needed */ +- txbdp = next_txbd(txbdp, base, tx_queue->tx_ring_size); +- +- size = skb_frag_size(frag); +- +- lstatus = be32_to_cpu(txbdp->lstatus) | size | +- BD_LFLAG(TXBD_READY); +- +- /* Handle the last BD specially */ +- if (i == nr_frags - 1) +- lstatus |= BD_LFLAG(TXBD_LAST | TXBD_INTERRUPT); +- +- bufaddr = skb_frag_dma_map(priv->dev, frag, 0, +- size, DMA_TO_DEVICE); +- if (unlikely(dma_mapping_error(priv->dev, bufaddr))) +- goto dma_map_err; +- +- /* set the TxBD length and buffer pointer */ +- txbdp->bufPtr = cpu_to_be32(bufaddr); +- txbdp->lstatus = cpu_to_be32(lstatus); +- } +- +- lstatus = lstatus_start; +- } +- + /* If time stamping is requested one additional TxBD must be set up. The + * first TxBD points to the FCB and must have a data length of + * GMAC_FCB_LEN. The second TxBD points to the actual frame data with +@@ -2493,25 +2422,31 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev) + + bufaddr = be32_to_cpu(txbdp_start->bufPtr); + bufaddr += fcb_len; +- + lstatus_ts |= BD_LFLAG(TXBD_READY) | + (skb_headlen(skb) - fcb_len); +- if (!nr_frags) +- lstatus_ts |= BD_LFLAG(TXBD_LAST | TXBD_INTERRUPT); + + txbdp_tstamp->bufPtr = cpu_to_be32(bufaddr); + txbdp_tstamp->lstatus = cpu_to_be32(lstatus_ts); + lstatus |= BD_LFLAG(TXBD_CRC | TXBD_READY) | GMAC_FCB_LEN; +- +- /* Setup tx hardware time stamping */ +- skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS; +- fcb->ptp = 1; + } else { + lstatus |= BD_LFLAG(TXBD_CRC | TXBD_READY) | skb_headlen(skb); + } + + netdev_tx_sent_queue(txq, bytes_sent); + ++ /* We can work in parallel with gfar_clean_tx_ring(), except ++ * when modifying num_txbdfree. Note that we didn't grab the lock ++ * when we were reading the num_txbdfree and checking for available ++ * space, that's because outside of this function it can only grow, ++ * and once we've got needed space, it cannot suddenly disappear. ++ * ++ * The lock also protects us from gfar_error(), which can modify ++ * regs->tstat and thus retrigger the transfers, which is why we ++ * also must grab the lock before setting ready bit for the first ++ * to be transmitted BD. ++ */ ++ spin_lock_irqsave(&tx_queue->txlock, flags); ++ + gfar_wmb(); + + txbdp_start->lstatus = cpu_to_be32(lstatus); +@@ -2528,15 +2463,8 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev) + + tx_queue->cur_tx = next_txbd(txbdp, base, tx_queue->tx_ring_size); + +- /* We can work in parallel with gfar_clean_tx_ring(), except +- * when modifying num_txbdfree. Note that we didn't grab the lock +- * when we were reading the num_txbdfree and checking for available +- * space, that's because outside of this function it can only grow. +- */ +- spin_lock_bh(&tx_queue->txlock); + /* reduce TxBD free count */ + tx_queue->num_txbdfree -= (nr_txbds); +- spin_unlock_bh(&tx_queue->txlock); + + /* If the next BD still needs to be cleaned up, then the bds + * are full. We need to tell the kernel to stop sending us stuff. +@@ -2550,6 +2478,9 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev) + /* Tell the DMA to go go go */ + gfar_write(®s->tstat, TSTAT_CLEAR_THALT >> tx_queue->qindex); + ++ /* Unlock priv */ ++ spin_unlock_irqrestore(&tx_queue->txlock, flags); ++ + return NETDEV_TX_OK; + + dma_map_err: +@@ -2582,7 +2513,8 @@ static int gfar_close(struct net_device *dev) + stop_gfar(dev); + + /* Disconnect from the PHY */ +- phy_disconnect(dev->phydev); ++ phy_disconnect(priv->phydev); ++ priv->phydev = NULL; + + gfar_free_irq(priv); + +@@ -2602,7 +2534,7 @@ static int gfar_change_mtu(struct net_device *dev, int new_mtu) + struct gfar_private *priv = netdev_priv(dev); + int frame_size = new_mtu + ETH_HLEN; + +- if ((frame_size < 64) || (frame_size > GFAR_JUMBO_FRAME_SIZE)) { ++ if ((frame_size < 64) || (frame_size > JUMBO_FRAME_SIZE)) { + netif_err(priv, drv, dev, "Invalid MTU setting\n"); + return -EINVAL; + } +@@ -2656,6 +2588,15 @@ static void gfar_timeout(struct net_device *dev) + schedule_work(&priv->reset_task); + } + ++static void gfar_align_skb(struct sk_buff *skb) ++{ ++ /* We need the data buffer to be aligned properly. We will reserve ++ * as many bytes as needed to align the data properly ++ */ ++ skb_reserve(skb, RXBUF_ALIGNMENT - ++ (((unsigned long) skb->data) & (RXBUF_ALIGNMENT - 1))); ++} ++ + /* Interrupt Handler for Transmit complete */ + static void gfar_clean_tx_ring(struct gfar_priv_tx_q *tx_queue) + { +@@ -2681,6 +2622,7 @@ static void gfar_clean_tx_ring(struct gfar_priv_tx_q *tx_queue) + skb_dirtytx = tx_queue->skb_dirtytx; + + while ((skb = tx_queue->tx_skbuff[skb_dirtytx])) { ++ unsigned long flags; + + frags = skb_shinfo(skb)->nr_frags; + +@@ -2713,11 +2655,10 @@ static void gfar_clean_tx_ring(struct gfar_priv_tx_q *tx_queue) + + if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS)) { + struct skb_shared_hwtstamps shhwtstamps; +- u64 *ns = (u64 *)(((uintptr_t)skb->data + 0x10) & +- ~0x7UL); ++ u64 *ns = (u64*) (((u32)skb->data + 0x10) & ~0x7); + + memset(&shhwtstamps, 0, sizeof(shhwtstamps)); +- shhwtstamps.hwtstamp = ns_to_ktime(be64_to_cpu(*ns)); ++ shhwtstamps.hwtstamp = ns_to_ktime(*ns); + skb_pull(skb, GMAC_FCB_LEN + GMAC_TXPAL_LEN); + skb_tstamp_tx(skb, &shhwtstamps); + gfar_clear_txbd_status(bdp); +@@ -2745,9 +2686,9 @@ static void gfar_clean_tx_ring(struct gfar_priv_tx_q *tx_queue) + TX_RING_MOD_MASK(tx_ring_size); + + howmany++; +- spin_lock(&tx_queue->txlock); ++ spin_lock_irqsave(&tx_queue->txlock, flags); + tx_queue->num_txbdfree += nr_txbds; +- spin_unlock(&tx_queue->txlock); ++ spin_unlock_irqrestore(&tx_queue->txlock, flags); + } + + /* If we freed a buffer, we can restart transmission, if necessary */ +@@ -2763,85 +2704,49 @@ static void gfar_clean_tx_ring(struct gfar_priv_tx_q *tx_queue) + netdev_tx_completed_queue(txq, howmany, bytes_sent); + } + +-static bool gfar_new_page(struct gfar_priv_rx_q *rxq, struct gfar_rx_buff *rxb) ++static struct sk_buff *gfar_alloc_skb(struct net_device *dev) + { +- struct page *page; +- dma_addr_t addr; +- +- page = dev_alloc_page(); +- if (unlikely(!page)) +- return false; +- +- addr = dma_map_page(rxq->dev, page, 0, PAGE_SIZE, DMA_FROM_DEVICE); +- if (unlikely(dma_mapping_error(rxq->dev, addr))) { +- __free_page(page); +- +- return false; +- } ++ struct gfar_private *priv = netdev_priv(dev); ++ struct sk_buff *skb; + +- rxb->dma = addr; +- rxb->page = page; +- rxb->page_offset = 0; ++ skb = netdev_alloc_skb(dev, priv->rx_buffer_size + RXBUF_ALIGNMENT); ++ if (!skb) ++ return NULL; + +- return true; +-} ++ gfar_align_skb(skb); + +-static void gfar_rx_alloc_err(struct gfar_priv_rx_q *rx_queue) +-{ +- struct gfar_private *priv = netdev_priv(rx_queue->ndev); +- struct gfar_extra_stats *estats = &priv->extra_stats; +- +- netdev_err(rx_queue->ndev, "Can't alloc RX buffers\n"); +- atomic64_inc(&estats->rx_alloc_err); ++ return skb; + } + +-static void gfar_alloc_rx_buffs(struct gfar_priv_rx_q *rx_queue, +- int alloc_cnt) ++static struct sk_buff *gfar_new_skb(struct net_device *dev, dma_addr_t *bufaddr) + { +- struct rxbd8 *bdp; +- struct gfar_rx_buff *rxb; +- int i; +- +- i = rx_queue->next_to_use; +- bdp = &rx_queue->rx_bd_base[i]; +- rxb = &rx_queue->rx_buff[i]; +- +- while (alloc_cnt--) { +- /* try reuse page */ +- if (unlikely(!rxb->page)) { +- if (unlikely(!gfar_new_page(rx_queue, rxb))) { +- gfar_rx_alloc_err(rx_queue); +- break; +- } +- } ++ struct gfar_private *priv = netdev_priv(dev); ++ struct sk_buff *skb; ++ dma_addr_t addr; + +- /* Setup the new RxBD */ +- gfar_init_rxbdp(rx_queue, bdp, +- rxb->dma + rxb->page_offset + RXBUF_ALIGNMENT); ++ skb = gfar_alloc_skb(dev); ++ if (!skb) ++ return NULL; + +- /* Update to the next pointer */ +- bdp++; +- rxb++; +- +- if (unlikely(++i == rx_queue->rx_ring_size)) { +- i = 0; +- bdp = rx_queue->rx_bd_base; +- rxb = rx_queue->rx_buff; +- } ++ addr = dma_map_single(priv->dev, skb->data, ++ priv->rx_buffer_size, DMA_FROM_DEVICE); ++ if (unlikely(dma_mapping_error(priv->dev, addr))) { ++ dev_kfree_skb_any(skb); ++ return NULL; + } + +- rx_queue->next_to_use = i; +- rx_queue->next_to_alloc = i; ++ *bufaddr = addr; ++ return skb; + } + +-static void count_errors(u32 lstatus, struct net_device *ndev) ++static inline void count_errors(unsigned short status, struct net_device *dev) + { +- struct gfar_private *priv = netdev_priv(ndev); +- struct net_device_stats *stats = &ndev->stats; ++ struct gfar_private *priv = netdev_priv(dev); ++ struct net_device_stats *stats = &dev->stats; + struct gfar_extra_stats *estats = &priv->extra_stats; + + /* If the packet was truncated, none of the other errors matter */ +- if (lstatus & BD_LFLAG(RXBD_TRUNCATED)) { ++ if (status & RXBD_TRUNCATED) { + stats->rx_length_errors++; + + atomic64_inc(&estats->rx_trunc); +@@ -2849,25 +2754,25 @@ static void count_errors(u32 lstatus, struct net_device *ndev) + return; + } + /* Count the errors, if there were any */ +- if (lstatus & BD_LFLAG(RXBD_LARGE | RXBD_SHORT)) { ++ if (status & (RXBD_LARGE | RXBD_SHORT)) { + stats->rx_length_errors++; + +- if (lstatus & BD_LFLAG(RXBD_LARGE)) ++ if (status & RXBD_LARGE) + atomic64_inc(&estats->rx_large); + else + atomic64_inc(&estats->rx_short); + } +- if (lstatus & BD_LFLAG(RXBD_NONOCTET)) { ++ if (status & RXBD_NONOCTET) { + stats->rx_frame_errors++; + atomic64_inc(&estats->rx_nonoctet); + } +- if (lstatus & BD_LFLAG(RXBD_CRCERR)) { ++ if (status & RXBD_CRCERR) { + atomic64_inc(&estats->rx_crcerr); + stats->rx_crc_errors++; + } +- if (lstatus & BD_LFLAG(RXBD_OVERRUN)) { ++ if (status & RXBD_OVERRUN) { + atomic64_inc(&estats->rx_overrun); +- stats->rx_over_errors++; ++ stats->rx_crc_errors++; + } + } + +@@ -2875,14 +2780,7 @@ irqreturn_t gfar_receive(int irq, void *grp_id) + { + struct gfar_priv_grp *grp = (struct gfar_priv_grp *)grp_id; + unsigned long flags; +- u32 imask, ievent; +- +- ievent = gfar_read(&grp->regs->ievent); +- +- if (unlikely(ievent & IEVENT_FGPI)) { +- gfar_write(&grp->regs->ievent, IEVENT_FGPI); +- return IRQ_HANDLED; +- } ++ u32 imask; + + if (likely(napi_schedule_prep(&grp->napi_rx))) { + spin_lock_irqsave(&grp->grplock, flags); +@@ -2925,101 +2823,6 @@ static irqreturn_t gfar_transmit(int irq, void *grp_id) + return IRQ_HANDLED; + } + +-static bool gfar_add_rx_frag(struct gfar_rx_buff *rxb, u32 lstatus, +- struct sk_buff *skb, bool first) +-{ +- unsigned int size = lstatus & BD_LENGTH_MASK; +- struct page *page = rxb->page; +- bool last = !!(lstatus & BD_LFLAG(RXBD_LAST)); +- +- /* Remove the FCS from the packet length */ +- if (last) +- size -= ETH_FCS_LEN; +- +- if (likely(first)) { +- skb_put(skb, size); +- } else { +- /* the last fragments' length contains the full frame length */ +- if (last) +- size -= skb->len; +- +- /* in case the last fragment consisted only of the FCS */ +- if (size > 0) +- skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, page, +- rxb->page_offset + RXBUF_ALIGNMENT, +- size, GFAR_RXB_TRUESIZE); +- } +- +- /* try reuse page */ +- if (unlikely(page_count(page) != 1)) +- return false; +- +- /* change offset to the other half */ +- rxb->page_offset ^= GFAR_RXB_TRUESIZE; +- +- page_ref_inc(page); +- +- return true; +-} +- +-static void gfar_reuse_rx_page(struct gfar_priv_rx_q *rxq, +- struct gfar_rx_buff *old_rxb) +-{ +- struct gfar_rx_buff *new_rxb; +- u16 nta = rxq->next_to_alloc; +- +- new_rxb = &rxq->rx_buff[nta]; +- +- /* find next buf that can reuse a page */ +- nta++; +- rxq->next_to_alloc = (nta < rxq->rx_ring_size) ? nta : 0; +- +- /* copy page reference */ +- *new_rxb = *old_rxb; +- +- /* sync for use by the device */ +- dma_sync_single_range_for_device(rxq->dev, old_rxb->dma, +- old_rxb->page_offset, +- GFAR_RXB_TRUESIZE, DMA_FROM_DEVICE); +-} +- +-static struct sk_buff *gfar_get_next_rxbuff(struct gfar_priv_rx_q *rx_queue, +- u32 lstatus, struct sk_buff *skb) +-{ +- struct gfar_rx_buff *rxb = &rx_queue->rx_buff[rx_queue->next_to_clean]; +- struct page *page = rxb->page; +- bool first = false; +- +- if (likely(!skb)) { +- void *buff_addr = page_address(page) + rxb->page_offset; +- +- skb = build_skb(buff_addr, GFAR_SKBFRAG_SIZE); +- if (unlikely(!skb)) { +- gfar_rx_alloc_err(rx_queue); +- return NULL; +- } +- skb_reserve(skb, RXBUF_ALIGNMENT); +- first = true; +- } +- +- dma_sync_single_range_for_cpu(rx_queue->dev, rxb->dma, rxb->page_offset, +- GFAR_RXB_TRUESIZE, DMA_FROM_DEVICE); +- +- if (gfar_add_rx_frag(rxb, lstatus, skb, first)) { +- /* reuse the free half of the page */ +- gfar_reuse_rx_page(rx_queue, rxb); +- } else { +- /* page cannot be reused, unmap it */ +- dma_unmap_page(rx_queue->dev, rxb->dma, +- PAGE_SIZE, DMA_FROM_DEVICE); +- } +- +- /* clear rxb content */ +- rxb->page = NULL; +- +- return skb; +-} +- + static inline void gfar_rx_checksum(struct sk_buff *skb, struct rxfcb *fcb) + { + /* If valid headers were found, and valid sums +@@ -3034,9 +2837,10 @@ static inline void gfar_rx_checksum(struct sk_buff *skb, struct rxfcb *fcb) + } + + /* gfar_process_frame() -- handle one incoming packet if skb isn't NULL. */ +-static void gfar_process_frame(struct net_device *ndev, struct sk_buff *skb) ++static void gfar_process_frame(struct net_device *dev, struct sk_buff *skb, ++ int amount_pull, struct napi_struct *napi) + { +- struct gfar_private *priv = netdev_priv(ndev); ++ struct gfar_private *priv = netdev_priv(dev); + struct rxfcb *fcb = NULL; + + /* fcb is at the beginning if exists */ +@@ -3045,8 +2849,10 @@ static void gfar_process_frame(struct net_device *ndev, struct sk_buff *skb) + /* Remove the FCB from the skb + * Remove the padded bytes, if there are any + */ +- if (priv->uses_rxfcb) +- skb_pull(skb, GMAC_FCB_LEN); ++ if (amount_pull) { ++ skb_record_rx_queue(skb, fcb->rq); ++ skb_pull(skb, amount_pull); ++ } + + /* Get receive timestamp from the skb */ + if (priv->hwts_rx_en) { +@@ -3054,26 +2860,30 @@ static void gfar_process_frame(struct net_device *ndev, struct sk_buff *skb) + u64 *ns = (u64 *) skb->data; + + memset(shhwtstamps, 0, sizeof(*shhwtstamps)); +- shhwtstamps->hwtstamp = ns_to_ktime(be64_to_cpu(*ns)); ++ shhwtstamps->hwtstamp = ns_to_ktime(*ns); + } + + if (priv->padding) + skb_pull(skb, priv->padding); + +- if (ndev->features & NETIF_F_RXCSUM) ++ if (dev->features & NETIF_F_RXCSUM) + gfar_rx_checksum(skb, fcb); + + /* Tell the skb what kind of packet this is */ +- skb->protocol = eth_type_trans(skb, ndev); ++ skb->protocol = eth_type_trans(skb, dev); + + /* There's need to check for NETIF_F_HW_VLAN_CTAG_RX here. + * Even if vlan rx accel is disabled, on some chips + * RXFCB_VLN is pseudo randomly set. + */ +- if (ndev->features & NETIF_F_HW_VLAN_CTAG_RX && ++ if (dev->features & NETIF_F_HW_VLAN_CTAG_RX && + be16_to_cpu(fcb->flags) & RXFCB_VLN) + __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), + be16_to_cpu(fcb->vlctl)); ++ ++ /* Send the packet up the stack */ ++ napi_gro_receive(napi, skb); ++ + } + + /* gfar_clean_rx_ring() -- Processes each frame in the rx ring +@@ -3082,89 +2892,91 @@ static void gfar_process_frame(struct net_device *ndev, struct sk_buff *skb) + */ + int gfar_clean_rx_ring(struct gfar_priv_rx_q *rx_queue, int rx_work_limit) + { +- struct net_device *ndev = rx_queue->ndev; +- struct gfar_private *priv = netdev_priv(ndev); +- struct rxbd8 *bdp; +- int i, howmany = 0; +- struct sk_buff *skb = rx_queue->skb; +- int cleaned_cnt = gfar_rxbd_unused(rx_queue); +- unsigned int total_bytes = 0, total_pkts = 0; ++ struct net_device *dev = rx_queue->dev; ++ struct rxbd8 *bdp, *base; ++ struct sk_buff *skb; ++ int pkt_len; ++ int amount_pull; ++ int howmany = 0; ++ struct gfar_private *priv = netdev_priv(dev); + + /* Get the first full descriptor */ +- i = rx_queue->next_to_clean; ++ bdp = rx_queue->cur_rx; ++ base = rx_queue->rx_bd_base; + +- while (rx_work_limit--) { +- u32 lstatus; ++ amount_pull = priv->uses_rxfcb ? GMAC_FCB_LEN : 0; + +- if (cleaned_cnt >= GFAR_RX_BUFF_ALLOC) { +- gfar_alloc_rx_buffs(rx_queue, cleaned_cnt); +- cleaned_cnt = 0; +- } +- +- bdp = &rx_queue->rx_bd_base[i]; +- lstatus = be32_to_cpu(bdp->lstatus); +- if (lstatus & BD_LFLAG(RXBD_EMPTY)) +- break; ++ while (!(be16_to_cpu(bdp->status) & RXBD_EMPTY) && rx_work_limit--) { ++ struct sk_buff *newskb; ++ dma_addr_t bufaddr; + +- /* order rx buffer descriptor reads */ + rmb(); + +- /* fetch next to clean buffer from the ring */ +- skb = gfar_get_next_rxbuff(rx_queue, lstatus, skb); +- if (unlikely(!skb)) +- break; +- +- cleaned_cnt++; +- howmany++; ++ /* Add another skb for the future */ ++ newskb = gfar_new_skb(dev, &bufaddr); + +- if (unlikely(++i == rx_queue->rx_ring_size)) +- i = 0; ++ skb = rx_queue->rx_skbuff[rx_queue->skb_currx]; + +- rx_queue->next_to_clean = i; +- +- /* fetch next buffer if not the last in frame */ +- if (!(lstatus & BD_LFLAG(RXBD_LAST))) +- continue; ++ dma_unmap_single(priv->dev, be32_to_cpu(bdp->bufPtr), ++ priv->rx_buffer_size, DMA_FROM_DEVICE); ++ ++ if (unlikely(!(be16_to_cpu(bdp->status) & RXBD_ERR) && ++ be16_to_cpu(bdp->length) > priv->rx_buffer_size)) ++ bdp->status = cpu_to_be16(RXBD_LARGE); ++ ++ /* We drop the frame if we failed to allocate a new buffer */ ++ if (unlikely(!newskb || ++ !(be16_to_cpu(bdp->status) & RXBD_LAST) || ++ be16_to_cpu(bdp->status) & RXBD_ERR)) { ++ count_errors(be16_to_cpu(bdp->status), dev); ++ ++ if (unlikely(!newskb)) { ++ newskb = skb; ++ bufaddr = be32_to_cpu(bdp->bufPtr); ++ } else if (skb) ++ dev_kfree_skb(skb); ++ } else { ++ /* Increment the number of packets */ ++ rx_queue->stats.rx_packets++; ++ howmany++; ++ ++ if (likely(skb)) { ++ pkt_len = be16_to_cpu(bdp->length) - ++ ETH_FCS_LEN; ++ /* Remove the FCS from the packet length */ ++ skb_put(skb, pkt_len); ++ rx_queue->stats.rx_bytes += pkt_len; ++ skb_record_rx_queue(skb, rx_queue->qindex); ++ gfar_process_frame(dev, skb, amount_pull, ++ &rx_queue->grp->napi_rx); + +- if (unlikely(lstatus & BD_LFLAG(RXBD_ERR))) { +- count_errors(lstatus, ndev); ++ } else { ++ netif_warn(priv, rx_err, dev, "Missing skb!\n"); ++ rx_queue->stats.rx_dropped++; ++ atomic64_inc(&priv->extra_stats.rx_skbmissing); ++ } + +- /* discard faulty buffer */ +- dev_kfree_skb(skb); +- skb = NULL; +- rx_queue->stats.rx_dropped++; +- continue; + } + +- /* Increment the number of packets */ +- total_pkts++; +- total_bytes += skb->len; ++ rx_queue->rx_skbuff[rx_queue->skb_currx] = newskb; + +- skb_record_rx_queue(skb, rx_queue->qindex); ++ /* Setup the new bdp */ ++ gfar_init_rxbdp(rx_queue, bdp, bufaddr); + +- gfar_process_frame(ndev, skb); ++ /* Update Last Free RxBD pointer for LFC */ ++ if (unlikely(rx_queue->rfbptr && priv->tx_actual_en)) ++ gfar_write(rx_queue->rfbptr, (u32)bdp); + +- /* Send the packet up the stack */ +- napi_gro_receive(&rx_queue->grp->napi_rx, skb); ++ /* Update to the next pointer */ ++ bdp = next_bd(bdp, base, rx_queue->rx_ring_size); + +- skb = NULL; ++ /* update to point at the next skb */ ++ rx_queue->skb_currx = (rx_queue->skb_currx + 1) & ++ RX_RING_MOD_MASK(rx_queue->rx_ring_size); + } + +- /* Store incomplete frames for completion */ +- rx_queue->skb = skb; +- +- rx_queue->stats.rx_packets += total_pkts; +- rx_queue->stats.rx_bytes += total_bytes; +- +- if (cleaned_cnt) +- gfar_alloc_rx_buffs(rx_queue, cleaned_cnt); +- +- /* Update Last Free RxBD pointer for LFC */ +- if (unlikely(priv->tx_actual_en)) { +- u32 bdp_dma = gfar_rxbd_dma_lastfree(rx_queue); +- +- gfar_write(rx_queue->rfbptr, bdp_dma); +- } ++ /* Update the current rxbd pointer to be the next one */ ++ rx_queue->cur_rx = bdp; + + return howmany; + } +@@ -3396,7 +3208,7 @@ static irqreturn_t gfar_interrupt(int irq, void *grp_id) + static void adjust_link(struct net_device *dev) + { + struct gfar_private *priv = netdev_priv(dev); +- struct phy_device *phydev = dev->phydev; ++ struct phy_device *phydev = priv->phydev; + + if (unlikely(phydev->link != priv->oldlink || + (phydev->link && (phydev->duplex != priv->oldduplex || +@@ -3599,19 +3411,30 @@ static irqreturn_t gfar_error(int irq, void *grp_id) + if (events & IEVENT_CRL) + dev->stats.tx_aborted_errors++; + if (events & IEVENT_XFUN) { ++ unsigned long flags; ++ + netif_dbg(priv, tx_err, dev, + "TX FIFO underrun, packet dropped\n"); + dev->stats.tx_dropped++; + atomic64_inc(&priv->extra_stats.tx_underrun); + +- schedule_work(&priv->reset_task); ++ local_irq_save(flags); ++ lock_tx_qs(priv); ++ ++ /* Reactivate the Tx Queues */ ++ gfar_write(®s->tstat, gfargrp->tstat); ++ ++ unlock_tx_qs(priv); ++ local_irq_restore(flags); + } + netif_dbg(priv, tx_err, dev, "Transmit Error\n"); + } + if (events & IEVENT_BSY) { +- dev->stats.rx_over_errors++; ++ dev->stats.rx_errors++; + atomic64_inc(&priv->extra_stats.rx_bsy); + ++ gfar_receive(irq, grp_id); ++ + netif_dbg(priv, rx_err, dev, "busy error (rstat: %x)\n", + gfar_read(®s->rstat)); + } +@@ -3637,8 +3460,7 @@ static irqreturn_t gfar_error(int irq, void *grp_id) + + static u32 gfar_get_flowctrl_cfg(struct gfar_private *priv) + { +- struct net_device *ndev = priv->ndev; +- struct phy_device *phydev = ndev->phydev; ++ struct phy_device *phydev = priv->phydev; + u32 val = 0; + + if (!phydev->duplex) +@@ -3678,10 +3500,10 @@ static u32 gfar_get_flowctrl_cfg(struct gfar_private *priv) + static noinline void gfar_update_link_state(struct gfar_private *priv) + { + struct gfar __iomem *regs = priv->gfargrp[0].regs; +- struct net_device *ndev = priv->ndev; +- struct phy_device *phydev = ndev->phydev; ++ struct phy_device *phydev = priv->phydev; + struct gfar_priv_rx_q *rx_queue = NULL; + int i; ++ struct rxbd8 *bdp; + + if (unlikely(test_bit(GFAR_RESETTING, &priv->state))) + return; +@@ -3738,11 +3560,15 @@ static noinline void gfar_update_link_state(struct gfar_private *priv) + /* Turn last free buffer recording on */ + if ((tempval1 & MACCFG1_TX_FLOW) && !tx_flow_oldval) { + for (i = 0; i < priv->num_rx_queues; i++) { +- u32 bdp_dma; +- + rx_queue = priv->rx_queue[i]; +- bdp_dma = gfar_rxbd_dma_lastfree(rx_queue); +- gfar_write(rx_queue->rfbptr, bdp_dma); ++ bdp = rx_queue->cur_rx; ++ /* skip to previous bd */ ++ bdp = skip_bd(bdp, rx_queue->rx_ring_size - 1, ++ rx_queue->rx_bd_base, ++ rx_queue->rx_ring_size); ++ ++ if (rx_queue->rfbptr) ++ gfar_write(rx_queue->rfbptr, (u32)bdp); + } + + priv->tx_actual_en = 1; +diff --git a/drivers/net/ethernet/freescale/gianfar.h b/drivers/net/ethernet/freescale/gianfar.h +index 6e8a9c8..daa1d37 100644 +--- a/drivers/net/ethernet/freescale/gianfar.h ++++ b/drivers/net/ethernet/freescale/gianfar.h +@@ -71,6 +71,11 @@ struct ethtool_rx_list { + /* Number of bytes to align the rx bufs to */ + #define RXBUF_ALIGNMENT 64 + ++/* The number of bytes which composes a unit for the purpose of ++ * allocating data buffers. ie-for any given MTU, the data buffer ++ * will be the next highest multiple of 512 bytes. */ ++#define INCREMENTAL_BUFFER_SIZE 512 ++ + #define PHY_INIT_TIMEOUT 100000 + + #define DRV_NAME "gfar-enet" +@@ -87,8 +92,6 @@ extern const char gfar_driver_version[]; + #define DEFAULT_TX_RING_SIZE 256 + #define DEFAULT_RX_RING_SIZE 256 + +-#define GFAR_RX_BUFF_ALLOC 16 +- + #define GFAR_RX_MAX_RING_SIZE 256 + #define GFAR_TX_MAX_RING_SIZE 256 + +@@ -100,15 +103,11 @@ extern const char gfar_driver_version[]; + #define DEFAULT_RX_LFC_THR 16 + #define DEFAULT_LFC_PTVVAL 4 + +-/* prevent fragmenation by HW in DSA environments */ +-#define GFAR_RXB_SIZE roundup(1536 + 8, 64) +-#define GFAR_SKBFRAG_SIZE (RXBUF_ALIGNMENT + GFAR_RXB_SIZE \ +- + SKB_DATA_ALIGN(sizeof(struct skb_shared_info))) +-#define GFAR_RXB_TRUESIZE 2048 +- ++#define DEFAULT_RX_BUFFER_SIZE 1536 + #define TX_RING_MOD_MASK(size) (size-1) + #define RX_RING_MOD_MASK(size) (size-1) +-#define GFAR_JUMBO_FRAME_SIZE 9600 ++#define JUMBO_BUFFER_SIZE 9728 ++#define JUMBO_FRAME_SIZE 9600 + + #define DEFAULT_FIFO_TX_THR 0x100 + #define DEFAULT_FIFO_TX_STARVE 0x40 +@@ -341,7 +340,6 @@ extern const char gfar_driver_version[]; + #define IEVENT_MAG 0x00000800 + #define IEVENT_GRSC 0x00000100 + #define IEVENT_RXF0 0x00000080 +-#define IEVENT_FGPI 0x00000010 + #define IEVENT_FIR 0x00000008 + #define IEVENT_FIQ 0x00000004 + #define IEVENT_DPE 0x00000002 +@@ -374,7 +372,6 @@ extern const char gfar_driver_version[]; + #define IMASK_MAG 0x00000800 + #define IMASK_GRSC 0x00000100 + #define IMASK_RXFEN0 0x00000080 +-#define IMASK_FGPI 0x00000010 + #define IMASK_FIR 0x00000008 + #define IMASK_FIQ 0x00000004 + #define IMASK_DPE 0x00000002 +@@ -543,9 +540,6 @@ extern const char gfar_driver_version[]; + + #define GFAR_INT_NAME_MAX (IFNAMSIZ + 6) /* '_g#_xx' */ + +-#define GFAR_WOL_MAGIC 0x00000001 +-#define GFAR_WOL_FILER_UCAST 0x00000002 +- + struct txbd8 + { + union { +@@ -646,7 +640,6 @@ struct rmon_mib + }; + + struct gfar_extra_stats { +- atomic64_t rx_alloc_err; + atomic64_t rx_large; + atomic64_t rx_short; + atomic64_t rx_nonoctet; +@@ -658,6 +651,7 @@ struct gfar_extra_stats { + atomic64_t eberr; + atomic64_t tx_babt; + atomic64_t tx_underrun; ++ atomic64_t rx_skbmissing; + atomic64_t tx_timeout; + }; + +@@ -923,8 +917,6 @@ struct gfar { + #define FSL_GIANFAR_DEV_HAS_BD_STASHING 0x00000200 + #define FSL_GIANFAR_DEV_HAS_BUF_STASHING 0x00000400 + #define FSL_GIANFAR_DEV_HAS_TIMER 0x00000800 +-#define FSL_GIANFAR_DEV_HAS_WAKE_ON_FILER 0x00001000 +-#define FSL_GIANFAR_DEV_HAS_RX_FILER 0x00002000 + + #if (MAXGROUPS == 2) + #define DEFAULT_MAPPING 0xAA +@@ -1020,42 +1012,34 @@ struct rx_q_stats { + unsigned long rx_dropped; + }; + +-struct gfar_rx_buff { +- dma_addr_t dma; +- struct page *page; +- unsigned int page_offset; +-}; +- + /** + * struct gfar_priv_rx_q - per rx queue structure +- * @rx_buff: Array of buffer info metadata structs ++ * @rx_skbuff: skb pointers ++ * @skb_currx: currently use skb pointer + * @rx_bd_base: First rx buffer descriptor +- * @next_to_use: index of the next buffer to be alloc'd +- * @next_to_clean: index of the next buffer to be cleaned ++ * @cur_rx: Next free rx ring entry + * @qindex: index of this queue +- * @ndev: back pointer to net_device ++ * @dev: back pointer to the dev structure + * @rx_ring_size: Rx ring size + * @rxcoalescing: enable/disable rx-coalescing + * @rxic: receive interrupt coalescing vlaue + */ + + struct gfar_priv_rx_q { +- struct gfar_rx_buff *rx_buff __aligned(SMP_CACHE_BYTES); ++ struct sk_buff **rx_skbuff __aligned(SMP_CACHE_BYTES); ++ dma_addr_t rx_bd_dma_base; + struct rxbd8 *rx_bd_base; +- struct net_device *ndev; +- struct device *dev; +- u16 rx_ring_size; +- u16 qindex; +- struct gfar_priv_grp *grp; +- u16 next_to_clean; +- u16 next_to_use; +- u16 next_to_alloc; +- struct sk_buff *skb; ++ struct rxbd8 *cur_rx; ++ struct net_device *dev; ++ struct gfar_priv_grp *grp; + struct rx_q_stats stats; +- u32 __iomem *rfbptr; ++ u16 skb_currx; ++ u16 qindex; ++ unsigned int rx_ring_size; ++ /* RX Coalescing values */ + unsigned char rxcoalescing; + unsigned long rxic; +- dma_addr_t rx_bd_dma_base; ++ u32 __iomem *rfbptr; + }; + + enum gfar_irqinfo_id { +@@ -1125,6 +1109,7 @@ struct gfar_private { + struct device *dev; + struct net_device *ndev; + enum gfar_errata errata; ++ unsigned int rx_buffer_size; + + u16 uses_rxfcb; + u16 padding; +@@ -1154,11 +1139,15 @@ struct gfar_private { + phy_interface_t interface; + struct device_node *phy_node; + struct device_node *tbi_node; ++ struct phy_device *phydev; + struct mii_bus *mii_bus; + int oldspeed; + int oldduplex; + int oldlink; + ++ /* Bitfield update lock */ ++ spinlock_t bflock; ++ + uint32_t msg_enable; + + struct work_struct reset_task; +@@ -1168,6 +1157,8 @@ struct gfar_private { + extended_hash:1, + bd_stash_en:1, + rx_filer_enable:1, ++ /* Wake-on-LAN enabled */ ++ wol_en:1, + /* Enable priorty based Tx scheduling in Hw */ + prio_sched_en:1, + /* Flow control flags */ +@@ -1196,10 +1187,6 @@ struct gfar_private { + u32 __iomem *hash_regs[16]; + int hash_width; + +- /* wake-on-lan settings */ +- u16 wol_opts; +- u16 wol_supported; +- + /*Filer table*/ + unsigned int ftp_rqfpr[MAX_FILER_IDX + 1]; + unsigned int ftp_rqfcr[MAX_FILER_IDX + 1]; +@@ -1308,28 +1295,6 @@ static inline void gfar_clear_txbd_status(struct txbd8 *bdp) + bdp->lstatus = cpu_to_be32(lstatus); + } + +-static inline int gfar_rxbd_unused(struct gfar_priv_rx_q *rxq) +-{ +- if (rxq->next_to_clean > rxq->next_to_use) +- return rxq->next_to_clean - rxq->next_to_use - 1; +- +- return rxq->rx_ring_size + rxq->next_to_clean - rxq->next_to_use - 1; +-} +- +-static inline u32 gfar_rxbd_dma_lastfree(struct gfar_priv_rx_q *rxq) +-{ +- struct rxbd8 *bdp; +- u32 bdp_dma; +- int i; +- +- i = rxq->next_to_use ? rxq->next_to_use - 1 : rxq->rx_ring_size - 1; +- bdp = &rxq->rx_bd_base[i]; +- bdp_dma = lower_32_bits(rxq->rx_bd_dma_base); +- bdp_dma += (uintptr_t)bdp - (uintptr_t)rxq->rx_bd_base; +- +- return bdp_dma; +-} +- + irqreturn_t gfar_receive(int irq, void *dev_id); + int startup_gfar(struct net_device *dev); + void stop_gfar(struct net_device *dev); +diff --git a/drivers/net/ethernet/freescale/gianfar_ethtool.c b/drivers/net/ethernet/freescale/gianfar_ethtool.c +index 56588f2..fda12fb 100644 +--- a/drivers/net/ethernet/freescale/gianfar_ethtool.c ++++ b/drivers/net/ethernet/freescale/gianfar_ethtool.c +@@ -61,8 +61,6 @@ static void gfar_gdrvinfo(struct net_device *dev, + struct ethtool_drvinfo *drvinfo); + + static const char stat_gstrings[][ETH_GSTRING_LEN] = { +- /* extra stats */ +- "rx-allocation-errors", + "rx-large-frame-errors", + "rx-short-frame-errors", + "rx-non-octet-errors", +@@ -74,8 +72,8 @@ static const char stat_gstrings[][ETH_GSTRING_LEN] = { + "ethernet-bus-error", + "tx-babbling-errors", + "tx-underrun-errors", ++ "rx-skb-missing-errors", + "tx-timeout-errors", +- /* rmon stats */ + "tx-rx-64-frames", + "tx-rx-65-127-frames", + "tx-rx-128-255-frames", +@@ -182,6 +180,42 @@ static void gfar_gdrvinfo(struct net_device *dev, + sizeof(drvinfo->version)); + strlcpy(drvinfo->fw_version, "N/A", sizeof(drvinfo->fw_version)); + strlcpy(drvinfo->bus_info, "N/A", sizeof(drvinfo->bus_info)); ++ drvinfo->regdump_len = 0; ++ drvinfo->eedump_len = 0; ++} ++ ++ ++static int gfar_ssettings(struct net_device *dev, struct ethtool_cmd *cmd) ++{ ++ struct gfar_private *priv = netdev_priv(dev); ++ struct phy_device *phydev = priv->phydev; ++ ++ if (NULL == phydev) ++ return -ENODEV; ++ ++ return phy_ethtool_sset(phydev, cmd); ++} ++ ++ ++/* Return the current settings in the ethtool_cmd structure */ ++static int gfar_gsettings(struct net_device *dev, struct ethtool_cmd *cmd) ++{ ++ struct gfar_private *priv = netdev_priv(dev); ++ struct phy_device *phydev = priv->phydev; ++ struct gfar_priv_rx_q *rx_queue = NULL; ++ struct gfar_priv_tx_q *tx_queue = NULL; ++ ++ if (NULL == phydev) ++ return -ENODEV; ++ tx_queue = priv->tx_queue[0]; ++ rx_queue = priv->rx_queue[0]; ++ ++ /* etsec-1.7 and older versions have only one txic ++ * and rxic regs although they support multiple queues */ ++ cmd->maxtxpkt = get_icft_value(tx_queue->txic); ++ cmd->maxrxpkt = get_icft_value(rx_queue->rxic); ++ ++ return phy_ethtool_gset(phydev, cmd); + } + + /* Return the length of the register structure */ +@@ -208,12 +242,10 @@ static void gfar_get_regs(struct net_device *dev, struct ethtool_regs *regs, + static unsigned int gfar_usecs2ticks(struct gfar_private *priv, + unsigned int usecs) + { +- struct net_device *ndev = priv->ndev; +- struct phy_device *phydev = ndev->phydev; + unsigned int count; + + /* The timer is different, depending on the interface speed */ +- switch (phydev->speed) { ++ switch (priv->phydev->speed) { + case SPEED_1000: + count = GFAR_GBIT_TIME; + break; +@@ -235,12 +267,10 @@ static unsigned int gfar_usecs2ticks(struct gfar_private *priv, + static unsigned int gfar_ticks2usecs(struct gfar_private *priv, + unsigned int ticks) + { +- struct net_device *ndev = priv->ndev; +- struct phy_device *phydev = ndev->phydev; + unsigned int count; + + /* The timer is different, depending on the interface speed */ +- switch (phydev->speed) { ++ switch (priv->phydev->speed) { + case SPEED_1000: + count = GFAR_GBIT_TIME; + break; +@@ -274,7 +304,7 @@ static int gfar_gcoalesce(struct net_device *dev, + if (!(priv->device_flags & FSL_GIANFAR_DEV_HAS_COALESCE)) + return -EOPNOTSUPP; + +- if (!dev->phydev) ++ if (NULL == priv->phydev) + return -ENODEV; + + rx_queue = priv->rx_queue[0]; +@@ -335,7 +365,7 @@ static int gfar_scoalesce(struct net_device *dev, + if (!(priv->device_flags & FSL_GIANFAR_DEV_HAS_COALESCE)) + return -EOPNOTSUPP; + +- if (!dev->phydev) ++ if (NULL == priv->phydev) + return -ENODEV; + + /* Check the bounds of the values */ +@@ -499,7 +529,7 @@ static int gfar_spauseparam(struct net_device *dev, + struct ethtool_pauseparam *epause) + { + struct gfar_private *priv = netdev_priv(dev); +- struct phy_device *phydev = dev->phydev; ++ struct phy_device *phydev = priv->phydev; + struct gfar __iomem *regs = priv->gfargrp[0].regs; + u32 oldadv, newadv; + +@@ -612,49 +642,31 @@ static void gfar_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) + { + struct gfar_private *priv = netdev_priv(dev); + +- wol->supported = 0; +- wol->wolopts = 0; +- +- if (priv->wol_supported & GFAR_WOL_MAGIC) +- wol->supported |= WAKE_MAGIC; +- +- if (priv->wol_supported & GFAR_WOL_FILER_UCAST) +- wol->supported |= WAKE_UCAST; +- +- if (priv->wol_opts & GFAR_WOL_MAGIC) +- wol->wolopts |= WAKE_MAGIC; +- +- if (priv->wol_opts & GFAR_WOL_FILER_UCAST) +- wol->wolopts |= WAKE_UCAST; ++ if (priv->device_flags & FSL_GIANFAR_DEV_HAS_MAGIC_PACKET) { ++ wol->supported = WAKE_MAGIC; ++ wol->wolopts = priv->wol_en ? WAKE_MAGIC : 0; ++ } else { ++ wol->supported = wol->wolopts = 0; ++ } + } + + static int gfar_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) + { + struct gfar_private *priv = netdev_priv(dev); +- u16 wol_opts = 0; +- int err; ++ unsigned long flags; + +- if (!priv->wol_supported && wol->wolopts) ++ if (!(priv->device_flags & FSL_GIANFAR_DEV_HAS_MAGIC_PACKET) && ++ wol->wolopts != 0) + return -EINVAL; + +- if (wol->wolopts & ~(WAKE_MAGIC | WAKE_UCAST)) ++ if (wol->wolopts & ~WAKE_MAGIC) + return -EINVAL; + +- if (wol->wolopts & WAKE_MAGIC) { +- wol_opts |= GFAR_WOL_MAGIC; +- } else { +- if (wol->wolopts & WAKE_UCAST) +- wol_opts |= GFAR_WOL_FILER_UCAST; +- } +- +- wol_opts &= priv->wol_supported; +- priv->wol_opts = 0; +- +- err = device_set_wakeup_enable(priv->dev, wol_opts); +- if (err) +- return err; ++ device_set_wakeup_enable(&dev->dev, wol->wolopts & WAKE_MAGIC); + +- priv->wol_opts = wol_opts; ++ spin_lock_irqsave(&priv->bflock, flags); ++ priv->wol_en = !!device_may_wakeup(&dev->dev); ++ spin_unlock_irqrestore(&priv->bflock, flags); + + return 0; + } +@@ -665,14 +677,14 @@ static void ethflow_to_filer_rules (struct gfar_private *priv, u64 ethflow) + u32 fcr = 0x0, fpr = FPR_FILER_MASK; + + if (ethflow & RXH_L2DA) { +- fcr = RQFCR_PID_DAH | RQFCR_CMP_NOMATCH | ++ fcr = RQFCR_PID_DAH |RQFCR_CMP_NOMATCH | + RQFCR_HASH | RQFCR_AND | RQFCR_HASHTBL_0; + priv->ftp_rqfpr[priv->cur_filer_idx] = fpr; + priv->ftp_rqfcr[priv->cur_filer_idx] = fcr; + gfar_write_filer(priv, priv->cur_filer_idx, fcr, fpr); + priv->cur_filer_idx = priv->cur_filer_idx - 1; + +- fcr = RQFCR_PID_DAL | RQFCR_CMP_NOMATCH | ++ fcr = RQFCR_PID_DAL | RQFCR_AND | RQFCR_CMP_NOMATCH | + RQFCR_HASH | RQFCR_AND | RQFCR_HASHTBL_0; + priv->ftp_rqfpr[priv->cur_filer_idx] = fpr; + priv->ftp_rqfcr[priv->cur_filer_idx] = fcr; +@@ -891,6 +903,27 @@ static int gfar_check_filer_hardware(struct gfar_private *priv) + return 0; + } + ++static int gfar_comp_asc(const void *a, const void *b) ++{ ++ return memcmp(a, b, 4); ++} ++ ++static int gfar_comp_desc(const void *a, const void *b) ++{ ++ return -memcmp(a, b, 4); ++} ++ ++static void gfar_swap(void *a, void *b, int size) ++{ ++ u32 *_a = a; ++ u32 *_b = b; ++ ++ swap(_a[0], _b[0]); ++ swap(_a[1], _b[1]); ++ swap(_a[2], _b[2]); ++ swap(_a[3], _b[3]); ++} ++ + /* Write a mask to filer cache */ + static void gfar_set_mask(u32 mask, struct filer_table *tab) + { +@@ -1240,6 +1273,310 @@ static int gfar_convert_to_filer(struct ethtool_rx_flow_spec *rule, + return 0; + } + ++/* Copy size filer entries */ ++static void gfar_copy_filer_entries(struct gfar_filer_entry dst[0], ++ struct gfar_filer_entry src[0], s32 size) ++{ ++ while (size > 0) { ++ size--; ++ dst[size].ctrl = src[size].ctrl; ++ dst[size].prop = src[size].prop; ++ } ++} ++ ++/* Delete the contents of the filer-table between start and end ++ * and collapse them ++ */ ++static int gfar_trim_filer_entries(u32 begin, u32 end, struct filer_table *tab) ++{ ++ int length; ++ ++ if (end > MAX_FILER_CACHE_IDX || end < begin) ++ return -EINVAL; ++ ++ end++; ++ length = end - begin; ++ ++ /* Copy */ ++ while (end < tab->index) { ++ tab->fe[begin].ctrl = tab->fe[end].ctrl; ++ tab->fe[begin++].prop = tab->fe[end++].prop; ++ ++ } ++ /* Fill up with don't cares */ ++ while (begin < tab->index) { ++ tab->fe[begin].ctrl = 0x60; ++ tab->fe[begin].prop = 0xFFFFFFFF; ++ begin++; ++ } ++ ++ tab->index -= length; ++ return 0; ++} ++ ++/* Make space on the wanted location */ ++static int gfar_expand_filer_entries(u32 begin, u32 length, ++ struct filer_table *tab) ++{ ++ if (length == 0 || length + tab->index > MAX_FILER_CACHE_IDX || ++ begin > MAX_FILER_CACHE_IDX) ++ return -EINVAL; ++ ++ gfar_copy_filer_entries(&(tab->fe[begin + length]), &(tab->fe[begin]), ++ tab->index - length + 1); ++ ++ tab->index += length; ++ return 0; ++} ++ ++static int gfar_get_next_cluster_start(int start, struct filer_table *tab) ++{ ++ for (; (start < tab->index) && (start < MAX_FILER_CACHE_IDX - 1); ++ start++) { ++ if ((tab->fe[start].ctrl & (RQFCR_AND | RQFCR_CLE)) == ++ (RQFCR_AND | RQFCR_CLE)) ++ return start; ++ } ++ return -1; ++} ++ ++static int gfar_get_next_cluster_end(int start, struct filer_table *tab) ++{ ++ for (; (start < tab->index) && (start < MAX_FILER_CACHE_IDX - 1); ++ start++) { ++ if ((tab->fe[start].ctrl & (RQFCR_AND | RQFCR_CLE)) == ++ (RQFCR_CLE)) ++ return start; ++ } ++ return -1; ++} ++ ++/* Uses hardwares clustering option to reduce ++ * the number of filer table entries ++ */ ++static void gfar_cluster_filer(struct filer_table *tab) ++{ ++ s32 i = -1, j, iend, jend; ++ ++ while ((i = gfar_get_next_cluster_start(++i, tab)) != -1) { ++ j = i; ++ while ((j = gfar_get_next_cluster_start(++j, tab)) != -1) { ++ /* The cluster entries self and the previous one ++ * (a mask) must be identical! ++ */ ++ if (tab->fe[i].ctrl != tab->fe[j].ctrl) ++ break; ++ if (tab->fe[i].prop != tab->fe[j].prop) ++ break; ++ if (tab->fe[i - 1].ctrl != tab->fe[j - 1].ctrl) ++ break; ++ if (tab->fe[i - 1].prop != tab->fe[j - 1].prop) ++ break; ++ iend = gfar_get_next_cluster_end(i, tab); ++ jend = gfar_get_next_cluster_end(j, tab); ++ if (jend == -1 || iend == -1) ++ break; ++ ++ /* First we make some free space, where our cluster ++ * element should be. Then we copy it there and finally ++ * delete in from its old location. ++ */ ++ if (gfar_expand_filer_entries(iend, (jend - j), tab) == ++ -EINVAL) ++ break; ++ ++ gfar_copy_filer_entries(&(tab->fe[iend + 1]), ++ &(tab->fe[jend + 1]), jend - j); ++ ++ if (gfar_trim_filer_entries(jend - 1, ++ jend + (jend - j), ++ tab) == -EINVAL) ++ return; ++ ++ /* Mask out cluster bit */ ++ tab->fe[iend].ctrl &= ~(RQFCR_CLE); ++ } ++ } ++} ++ ++/* Swaps the masked bits of a1<>a2 and b1<>b2 */ ++static void gfar_swap_bits(struct gfar_filer_entry *a1, ++ struct gfar_filer_entry *a2, ++ struct gfar_filer_entry *b1, ++ struct gfar_filer_entry *b2, u32 mask) ++{ ++ u32 temp[4]; ++ temp[0] = a1->ctrl & mask; ++ temp[1] = a2->ctrl & mask; ++ temp[2] = b1->ctrl & mask; ++ temp[3] = b2->ctrl & mask; ++ ++ a1->ctrl &= ~mask; ++ a2->ctrl &= ~mask; ++ b1->ctrl &= ~mask; ++ b2->ctrl &= ~mask; ++ ++ a1->ctrl |= temp[1]; ++ a2->ctrl |= temp[0]; ++ b1->ctrl |= temp[3]; ++ b2->ctrl |= temp[2]; ++} ++ ++/* Generate a list consisting of masks values with their start and ++ * end of validity and block as indicator for parts belonging ++ * together (glued by ANDs) in mask_table ++ */ ++static u32 gfar_generate_mask_table(struct gfar_mask_entry *mask_table, ++ struct filer_table *tab) ++{ ++ u32 i, and_index = 0, block_index = 1; ++ ++ for (i = 0; i < tab->index; i++) { ++ ++ /* LSByte of control = 0 sets a mask */ ++ if (!(tab->fe[i].ctrl & 0xF)) { ++ mask_table[and_index].mask = tab->fe[i].prop; ++ mask_table[and_index].start = i; ++ mask_table[and_index].block = block_index; ++ if (and_index >= 1) ++ mask_table[and_index - 1].end = i - 1; ++ and_index++; ++ } ++ /* cluster starts and ends will be separated because they should ++ * hold their position ++ */ ++ if (tab->fe[i].ctrl & RQFCR_CLE) ++ block_index++; ++ /* A not set AND indicates the end of a depended block */ ++ if (!(tab->fe[i].ctrl & RQFCR_AND)) ++ block_index++; ++ } ++ ++ mask_table[and_index - 1].end = i - 1; ++ ++ return and_index; ++} ++ ++/* Sorts the entries of mask_table by the values of the masks. ++ * Important: The 0xFF80 flags of the first and last entry of a ++ * block must hold their position (which queue, CLusterEnable, ReJEct, ++ * AND) ++ */ ++static void gfar_sort_mask_table(struct gfar_mask_entry *mask_table, ++ struct filer_table *temp_table, u32 and_index) ++{ ++ /* Pointer to compare function (_asc or _desc) */ ++ int (*gfar_comp)(const void *, const void *); ++ ++ u32 i, size = 0, start = 0, prev = 1; ++ u32 old_first, old_last, new_first, new_last; ++ ++ gfar_comp = &gfar_comp_desc; ++ ++ for (i = 0; i < and_index; i++) { ++ if (prev != mask_table[i].block) { ++ old_first = mask_table[start].start + 1; ++ old_last = mask_table[i - 1].end; ++ sort(mask_table + start, size, ++ sizeof(struct gfar_mask_entry), ++ gfar_comp, &gfar_swap); ++ ++ /* Toggle order for every block. This makes the ++ * thing more efficient! ++ */ ++ if (gfar_comp == gfar_comp_desc) ++ gfar_comp = &gfar_comp_asc; ++ else ++ gfar_comp = &gfar_comp_desc; ++ ++ new_first = mask_table[start].start + 1; ++ new_last = mask_table[i - 1].end; ++ ++ gfar_swap_bits(&temp_table->fe[new_first], ++ &temp_table->fe[old_first], ++ &temp_table->fe[new_last], ++ &temp_table->fe[old_last], ++ RQFCR_QUEUE | RQFCR_CLE | ++ RQFCR_RJE | RQFCR_AND); ++ ++ start = i; ++ size = 0; ++ } ++ size++; ++ prev = mask_table[i].block; ++ } ++} ++ ++/* Reduces the number of masks needed in the filer table to save entries ++ * This is done by sorting the masks of a depended block. A depended block is ++ * identified by gluing ANDs or CLE. The sorting order toggles after every ++ * block. Of course entries in scope of a mask must change their location with ++ * it. ++ */ ++static int gfar_optimize_filer_masks(struct filer_table *tab) ++{ ++ struct filer_table *temp_table; ++ struct gfar_mask_entry *mask_table; ++ ++ u32 and_index = 0, previous_mask = 0, i = 0, j = 0, size = 0; ++ s32 ret = 0; ++ ++ /* We need a copy of the filer table because ++ * we want to change its order ++ */ ++ temp_table = kmemdup(tab, sizeof(*temp_table), GFP_KERNEL); ++ if (temp_table == NULL) ++ return -ENOMEM; ++ ++ mask_table = kcalloc(MAX_FILER_CACHE_IDX / 2 + 1, ++ sizeof(struct gfar_mask_entry), GFP_KERNEL); ++ ++ if (mask_table == NULL) { ++ ret = -ENOMEM; ++ goto end; ++ } ++ ++ and_index = gfar_generate_mask_table(mask_table, tab); ++ ++ gfar_sort_mask_table(mask_table, temp_table, and_index); ++ ++ /* Now we can copy the data from our duplicated filer table to ++ * the real one in the order the mask table says ++ */ ++ for (i = 0; i < and_index; i++) { ++ size = mask_table[i].end - mask_table[i].start + 1; ++ gfar_copy_filer_entries(&(tab->fe[j]), ++ &(temp_table->fe[mask_table[i].start]), size); ++ j += size; ++ } ++ ++ /* And finally we just have to check for duplicated masks and drop the ++ * second ones ++ */ ++ for (i = 0; i < tab->index && i < MAX_FILER_CACHE_IDX; i++) { ++ if (tab->fe[i].ctrl == 0x80) { ++ previous_mask = i++; ++ break; ++ } ++ } ++ for (; i < tab->index && i < MAX_FILER_CACHE_IDX; i++) { ++ if (tab->fe[i].ctrl == 0x80) { ++ if (tab->fe[i].prop == tab->fe[previous_mask].prop) { ++ /* Two identical ones found! ++ * So drop the second one! ++ */ ++ gfar_trim_filer_entries(i, i, tab); ++ } else ++ /* Not identical! */ ++ previous_mask = i; ++ } ++ } ++ ++ kfree(mask_table); ++end: kfree(temp_table); ++ return ret; ++} ++ + /* Write the bit-pattern from software's buffer to hardware registers */ + static int gfar_write_filer_table(struct gfar_private *priv, + struct filer_table *tab) +@@ -1249,10 +1586,11 @@ static int gfar_write_filer_table(struct gfar_private *priv, + return -EBUSY; + + /* Fill regular entries */ +- for (; i < MAX_FILER_IDX && (tab->fe[i].ctrl | tab->fe[i].prop); i++) ++ for (; i < MAX_FILER_IDX - 1 && (tab->fe[i].ctrl | tab->fe[i].prop); ++ i++) + gfar_write_filer(priv, i, tab->fe[i].ctrl, tab->fe[i].prop); + /* Fill the rest with fall-troughs */ +- for (; i < MAX_FILER_IDX; i++) ++ for (; i < MAX_FILER_IDX - 1; i++) + gfar_write_filer(priv, i, 0x60, 0xFFFFFFFF); + /* Last entry must be default accept + * because that's what people expect +@@ -1286,6 +1624,7 @@ static int gfar_process_filer_changes(struct gfar_private *priv) + { + struct ethtool_flow_spec_container *j; + struct filer_table *tab; ++ s32 i = 0; + s32 ret = 0; + + /* So index is set to zero, too! */ +@@ -1310,6 +1649,17 @@ static int gfar_process_filer_changes(struct gfar_private *priv) + } + } + ++ i = tab->index; ++ ++ /* Optimizations to save entries */ ++ gfar_cluster_filer(tab); ++ gfar_optimize_filer_masks(tab); ++ ++ pr_debug("\tSummary:\n" ++ "\tData on hardware: %d\n" ++ "\tCompression rate: %d%%\n", ++ tab->index, 100 - (100 * tab->index) / i); ++ + /* Write everything to hardware */ + ret = gfar_write_filer_table(priv, tab); + if (ret == -EBUSY) { +@@ -1375,14 +1725,13 @@ static int gfar_add_cls(struct gfar_private *priv, + } + + process: +- priv->rx_list.count++; + ret = gfar_process_filer_changes(priv); + if (ret) + goto clean_list; ++ priv->rx_list.count++; + return ret; + + clean_list: +- priv->rx_list.count--; + list_del(&temp->list); + clean_mem: + kfree(temp); +@@ -1535,6 +1884,8 @@ static int gfar_get_ts_info(struct net_device *dev, + } + + const struct ethtool_ops gfar_ethtool_ops = { ++ .get_settings = gfar_gsettings, ++ .set_settings = gfar_ssettings, + .get_drvinfo = gfar_gdrvinfo, + .get_regs_len = gfar_reglen, + .get_regs = gfar_get_regs, +@@ -1557,6 +1908,4 @@ const struct ethtool_ops gfar_ethtool_ops = { + .set_rxnfc = gfar_set_nfc, + .get_rxnfc = gfar_get_nfc, + .get_ts_info = gfar_get_ts_info, +- .get_link_ksettings = phy_ethtool_get_link_ksettings, +- .set_link_ksettings = phy_ethtool_set_link_ksettings, + }; +diff --git a/drivers/net/ethernet/freescale/gianfar_ptp.c b/drivers/net/ethernet/freescale/gianfar_ptp.c +index 5779881..8e3cd77 100644 +--- a/drivers/net/ethernet/freescale/gianfar_ptp.c ++++ b/drivers/net/ethernet/freescale/gianfar_ptp.c +@@ -422,6 +422,19 @@ static struct ptp_clock_info ptp_gianfar_caps = { + .enable = ptp_gianfar_enable, + }; + ++/* OF device tree */ ++ ++static int get_of_u32(struct device_node *node, char *str, u32 *val) ++{ ++ int plen; ++ const u32 *prop = of_get_property(node, str, &plen); ++ ++ if (!prop || plen != sizeof(*prop)) ++ return -1; ++ *val = *prop; ++ return 0; ++} ++ + static int gianfar_ptp_probe(struct platform_device *dev) + { + struct device_node *node = dev->dev.of_node; +@@ -439,28 +452,22 @@ static int gianfar_ptp_probe(struct platform_device *dev) + + etsects->caps = ptp_gianfar_caps; + +- if (of_property_read_u32(node, "fsl,cksel", &etsects->cksel)) ++ if (get_of_u32(node, "fsl,cksel", &etsects->cksel)) + etsects->cksel = DEFAULT_CKSEL; + +- if (of_property_read_u32(node, +- "fsl,tclk-period", &etsects->tclk_period) || +- of_property_read_u32(node, +- "fsl,tmr-prsc", &etsects->tmr_prsc) || +- of_property_read_u32(node, +- "fsl,tmr-add", &etsects->tmr_add) || +- of_property_read_u32(node, +- "fsl,tmr-fiper1", &etsects->tmr_fiper1) || +- of_property_read_u32(node, +- "fsl,tmr-fiper2", &etsects->tmr_fiper2) || +- of_property_read_u32(node, +- "fsl,max-adj", &etsects->caps.max_adj)) { ++ if (get_of_u32(node, "fsl,tclk-period", &etsects->tclk_period) || ++ get_of_u32(node, "fsl,tmr-prsc", &etsects->tmr_prsc) || ++ get_of_u32(node, "fsl,tmr-add", &etsects->tmr_add) || ++ get_of_u32(node, "fsl,tmr-fiper1", &etsects->tmr_fiper1) || ++ get_of_u32(node, "fsl,tmr-fiper2", &etsects->tmr_fiper2) || ++ get_of_u32(node, "fsl,max-adj", &etsects->caps.max_adj)) { + pr_err("device tree node missing required elements\n"); + goto no_node; + } + + etsects->irq = platform_get_irq(dev, 0); + +- if (etsects->irq < 0) { ++ if (etsects->irq == NO_IRQ) { + pr_err("irq not in device tree\n"); + goto no_node; + } +@@ -550,7 +557,6 @@ static const struct of_device_id match_table[] = { + { .compatible = "fsl,etsec-ptp" }, + {}, + }; +-MODULE_DEVICE_TABLE(of, match_table); + + static struct platform_driver gianfar_ptp_driver = { + .driver = { +diff --git a/drivers/net/ethernet/freescale/ucc_geth.c b/drivers/net/ethernet/freescale/ucc_geth.c +index f76d332..4dd40e0 100644 +--- a/drivers/net/ethernet/freescale/ucc_geth.c ++++ b/drivers/net/ethernet/freescale/ucc_geth.c +@@ -40,10 +40,10 @@ + #include + #include + #include +-#include +-#include +-#include +-#include ++#include ++#include ++#include ++#include + #include + + #include "ucc_geth.h" +@@ -1384,8 +1384,6 @@ static int adjust_enet_interface(struct ucc_geth_private *ugeth) + value = phy_read(tbiphy, ENET_TBI_MII_CR); + value &= ~0x1000; /* Turn off autonegotiation */ + phy_write(tbiphy, ENET_TBI_MII_CR, value); +- +- put_device(&tbiphy->mdio.dev); + } + + init_check_frame_length_mode(ug_info->lengthCheckRx, &ug_regs->maccfg2); +@@ -1704,10 +1702,8 @@ static void uec_configure_serdes(struct net_device *dev) + * everything for us? Resetting it takes the link down and requires + * several seconds for it to come back. + */ +- if (phy_read(tbiphy, ENET_TBI_MII_SR) & TBISR_LSTATUS) { +- put_device(&tbiphy->mdio.dev); ++ if (phy_read(tbiphy, ENET_TBI_MII_SR) & TBISR_LSTATUS) + return; +- } + + /* Single clk mode, mii mode off(for serdes communication) */ + phy_write(tbiphy, ENET_TBI_MII_ANA, TBIANA_SETTINGS); +@@ -1715,8 +1711,6 @@ static void uec_configure_serdes(struct net_device *dev) + phy_write(tbiphy, ENET_TBI_MII_TBICON, TBICON_CLK_SELECT); + + phy_write(tbiphy, ENET_TBI_MII_CR, TBICR_SETTINGS); +- +- put_device(&tbiphy->mdio.dev); + } + + /* Configure the PHY for dev. +@@ -3756,7 +3750,7 @@ static int ucc_geth_probe(struct platform_device* ofdev) + return -EINVAL; + } + if ((*prop < QE_CLK_NONE) || (*prop > QE_CLK24)) { +- pr_err("invalid rx-clock property\n"); ++ pr_err("invalid rx-clock propperty\n"); + return -EINVAL; + } + ug_info->uf_info.rx_clock = *prop; +@@ -3868,8 +3862,9 @@ static int ucc_geth_probe(struct platform_device* ofdev) + dev = alloc_etherdev(sizeof(*ugeth)); + + if (dev == NULL) { +- err = -ENOMEM; +- goto err_deregister_fixed_link; ++ of_node_put(ug_info->tbi_node); ++ of_node_put(ug_info->phy_node); ++ return -ENOMEM; + } + + ugeth = netdev_priv(dev); +@@ -3906,7 +3901,10 @@ static int ucc_geth_probe(struct platform_device* ofdev) + if (netif_msg_probe(ugeth)) + pr_err("%s: Cannot register net device, aborting\n", + dev->name); +- goto err_free_netdev; ++ free_netdev(dev); ++ of_node_put(ug_info->tbi_node); ++ of_node_put(ug_info->phy_node); ++ return err; + } + + mac_addr = of_get_mac_address(np); +@@ -3919,29 +3917,16 @@ static int ucc_geth_probe(struct platform_device* ofdev) + ugeth->node = np; + + return 0; +- +-err_free_netdev: +- free_netdev(dev); +-err_deregister_fixed_link: +- if (of_phy_is_fixed_link(np)) +- of_phy_deregister_fixed_link(np); +- of_node_put(ug_info->tbi_node); +- of_node_put(ug_info->phy_node); +- +- return err; + } + + static int ucc_geth_remove(struct platform_device* ofdev) + { + struct net_device *dev = platform_get_drvdata(ofdev); + struct ucc_geth_private *ugeth = netdev_priv(dev); +- struct device_node *np = ofdev->dev.of_node; + + unregister_netdev(dev); + free_netdev(dev); + ucc_geth_memclean(ugeth); +- if (of_phy_is_fixed_link(np)) +- of_phy_deregister_fixed_link(np); + of_node_put(ugeth->ug_info->tbi_node); + of_node_put(ugeth->ug_info->phy_node); + +diff --git a/drivers/net/ethernet/freescale/ucc_geth.h b/drivers/net/ethernet/freescale/ucc_geth.h +index 5da19b4..75f3371 100644 +--- a/drivers/net/ethernet/freescale/ucc_geth.h ++++ b/drivers/net/ethernet/freescale/ucc_geth.h +@@ -22,11 +22,11 @@ + #include + #include + +-#include +-#include ++#include ++#include + +-#include +-#include ++#include ++#include + + #define DRV_DESC "QE UCC Gigabit Ethernet Controller" + #define DRV_NAME "ucc_geth" +diff --git a/drivers/net/ethernet/freescale/ucc_geth_ethtool.c b/drivers/net/ethernet/freescale/ucc_geth_ethtool.c +index 812a968..cc83350 100644 +--- a/drivers/net/ethernet/freescale/ucc_geth_ethtool.c ++++ b/drivers/net/ethernet/freescale/ucc_geth_ethtool.c +@@ -105,20 +105,23 @@ static const char rx_fw_stat_gstrings[][ETH_GSTRING_LEN] = { + #define UEC_RX_FW_STATS_LEN ARRAY_SIZE(rx_fw_stat_gstrings) + + static int +-uec_get_ksettings(struct net_device *netdev, struct ethtool_link_ksettings *cmd) ++uec_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) + { + struct ucc_geth_private *ugeth = netdev_priv(netdev); + struct phy_device *phydev = ugeth->phydev; ++ struct ucc_geth_info *ug_info = ugeth->ug_info; + + if (!phydev) + return -ENODEV; + +- return phy_ethtool_ksettings_get(phydev, cmd); ++ ecmd->maxtxpkt = 1; ++ ecmd->maxrxpkt = ug_info->interruptcoalescingmaxvalue[0]; ++ ++ return phy_ethtool_gset(phydev, ecmd); + } + + static int +-uec_set_ksettings(struct net_device *netdev, +- const struct ethtool_link_ksettings *cmd) ++uec_set_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) + { + struct ucc_geth_private *ugeth = netdev_priv(netdev); + struct phy_device *phydev = ugeth->phydev; +@@ -126,7 +129,7 @@ uec_set_ksettings(struct net_device *netdev, + if (!phydev) + return -ENODEV; + +- return phy_ethtool_ksettings_set(phydev, cmd); ++ return phy_ethtool_sset(phydev, ecmd); + } + + static void +@@ -348,6 +351,8 @@ uec_get_drvinfo(struct net_device *netdev, + strlcpy(drvinfo->version, DRV_VERSION, sizeof(drvinfo->version)); + strlcpy(drvinfo->fw_version, "N/A", sizeof(drvinfo->fw_version)); + strlcpy(drvinfo->bus_info, "QUICC ENGINE", sizeof(drvinfo->bus_info)); ++ drvinfo->eedump_len = 0; ++ drvinfo->regdump_len = uec_get_regs_len(netdev); + } + + #ifdef CONFIG_PM +@@ -389,6 +394,8 @@ static int uec_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) + #endif /* CONFIG_PM */ + + static const struct ethtool_ops uec_ethtool_ops = { ++ .get_settings = uec_get_settings, ++ .set_settings = uec_set_settings, + .get_drvinfo = uec_get_drvinfo, + .get_regs_len = uec_get_regs_len, + .get_regs = uec_get_regs, +@@ -406,8 +413,6 @@ static const struct ethtool_ops uec_ethtool_ops = { + .get_wol = uec_get_wol, + .set_wol = uec_set_wol, + .get_ts_info = ethtool_op_get_ts_info, +- .get_link_ksettings = uec_get_ksettings, +- .set_link_ksettings = uec_set_ksettings, + }; + + void uec_set_ethtool_ops(struct net_device *netdev) +diff --git a/drivers/net/ethernet/freescale/xgmac_mdio.c b/drivers/net/ethernet/freescale/xgmac_mdio.c +index e03b30c..7b8fe86 100644 +--- a/drivers/net/ethernet/freescale/xgmac_mdio.c ++++ b/drivers/net/ethernet/freescale/xgmac_mdio.c +@@ -271,8 +271,11 @@ static int xgmac_mdio_probe(struct platform_device *pdev) + goto err_ioremap; + } + +- priv->is_little_endian = of_property_read_bool(pdev->dev.of_node, +- "little-endian"); ++ if (of_get_property(pdev->dev.of_node, ++ "little-endian", NULL)) ++ priv->is_little_endian = true; ++ else ++ priv->is_little_endian = false; + + ret = of_mdiobus_register(bus, np); + if (ret) { diff --git a/recipes-kernel/linux/linux-karo-4.9.11/gpu-viv_gcc6_indent_warning_error_fix.patch b/recipes-kernel/linux/linux-karo-4.9.11/gpu-viv_gcc6_indent_warning_error_fix.patch new file mode 100755 index 0000000..b48606c --- /dev/null +++ b/recipes-kernel/linux/linux-karo-4.9.11/gpu-viv_gcc6_indent_warning_error_fix.patch @@ -0,0 +1,30 @@ +From 8d0142efbfcfe4e3998f748496ceba62890c47f0 Mon Sep 17 00:00:00 2001 +From: Lauren Post +Date: Wed, 13 Jul 2016 03:07:23 -0500 +Subject: [PATCH] gpu-viv: Fix gcc 6.0 indent warning error in gc_hal_kernel_platform_imx6ql4.c + +Upstream-Status: Pending + +Signed-off-by: Lauren Post +--- + .../linux/kernel/platform/freescale/gc_hal_kernel_platform_imx6q14.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/mxc/gpu-viv/hal/os/linux/kernel/platform/freescale/gc_hal_kernel_platform_imx6q14.c b/drivers/mxc/gpu-viv/hal/os/linux/kernel/platform/freescale/gc_hal_kernel_platform_imx6q14.c +index e436ada..d98c2f8 100644 +--- a/drivers/mxc/gpu-viv/hal/os/linux/kernel/platform/freescale/gc_hal_kernel_platform_imx6q14.c ++++ b/drivers/mxc/gpu-viv/hal/os/linux/kernel/platform/freescale/gc_hal_kernel_platform_imx6q14.c +@@ -475,8 +475,8 @@ gckPLATFORM_AdjustParam( + + Args->gpu3DMinClock = initgpu3DMinClock; + +- if(Args->physSize == 0) +- Args->physSize = 0x80000000; ++ if(Args->physSize == 0) ++ Args->physSize = 0x80000000; + + return gcvSTATUS_OK; + } +-- +1.9.1 + diff --git a/recipes-kernel/linux/linux-karo-4.9.11/reset-phy-minimal.patch b/recipes-kernel/linux/linux-karo-4.9.11/reset-phy-minimal.patch new file mode 100644 index 0000000..8a35d74 --- /dev/null +++ b/recipes-kernel/linux/linux-karo-4.9.11/reset-phy-minimal.patch @@ -0,0 +1,30 @@ +diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c +index 41a31f2..c062438 100644 +--- a/drivers/net/ethernet/freescale/fec_main.c ++++ b/drivers/net/ethernet/freescale/fec_main.c +@@ -1875,6 +1875,8 @@ static int fec_enet_mdio_write(struct mii_bus *bus, int mii_id, int regnum, + return ret; + } + ++static int fec_reset_phy(struct platform_device *pdev); ++ + static int fec_enet_clk_enable(struct net_device *ndev, bool enable) + { + struct fec_enet_private *fep = netdev_priv(ndev); +@@ -1885,6 +1887,7 @@ static int fec_enet_clk_enable(struct net_device *ndev, bool enable) + ret = clk_prepare_enable(fep->clk_enet_out); + if (ret) + return ret; ++ fec_reset_phy(fep->pdev); + } + if (fep->clk_ptp) { + mutex_lock(&fep->ptp_clk_mutex); +@@ -3367,6 +3370,8 @@ static int fec_reset_phy(struct platform_device *pdev) + + gpio_set_value_cansleep(phy_reset, !active_high); + ++ devm_gpio_free(&pdev->dev, phy_reset); ++ + return 0; + } + #else /* CONFIG_OF */ diff --git a/recipes-kernel/linux/linux-karo-4.9.11/reset_ethernet_phy_whenever_the_enet_out_clock_is_being_enabled.patch b/recipes-kernel/linux/linux-karo-4.9.11/reset_ethernet_phy_whenever_the_enet_out_clock_is_being_enabled.patch new file mode 100644 index 0000000..d0233dd --- /dev/null +++ b/recipes-kernel/linux/linux-karo-4.9.11/reset_ethernet_phy_whenever_the_enet_out_clock_is_being_enabled.patch @@ -0,0 +1,203 @@ +From fac8dc6a300ced21494cba76af18cb4197c699c6 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Lothar=20Wa=C3=9Fmann?= +Date: Tue, 10 Oct 2017 14:05:36 +0200 +Subject: [PATCH] net: fec: reset PHY whenever enet out clock has been + re-enabled + +--- + drivers/net/ethernet/freescale/fec.h | 5 ++ + drivers/net/ethernet/freescale/fec_main.c | 124 +++++++++++++++++++----------- + 2 files changed, 82 insertions(+), 47 deletions(-) + +diff --git a/drivers/net/ethernet/freescale/fec.h b/drivers/net/ethernet/freescale/fec.h +index 38c7b21e5d63..4c2de04fe0aa 100644 +--- a/drivers/net/ethernet/freescale/fec.h ++++ b/drivers/net/ethernet/freescale/fec.h +@@ -523,6 +523,11 @@ struct fec_enet_private { + + int dev_id; + ++ int reset_gpio; ++ int phy_reset_duration; ++ int phy_post_delay; ++ int reset_active_high; ++ + /* Phylib and MDIO interface */ + struct mii_bus *mii_bus; + int mii_timeout; +diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c +index c1160ae22f94..3c2cff867704 100644 +--- a/drivers/net/ethernet/freescale/fec_main.c ++++ b/drivers/net/ethernet/freescale/fec_main.c +@@ -1836,6 +1836,8 @@ static int fec_enet_mdio_write(struct mii_bus *bus, int mii_id, int regnum, + return ret; + } + ++static void fec_reset_phy(struct fec_enet_private *fep); ++ + static int fec_enet_clk_enable(struct net_device *ndev, bool enable) + { + struct fec_enet_private *fep = netdev_priv(ndev); +@@ -1846,9 +1848,13 @@ static int fec_enet_clk_enable(struct net_device *ndev, bool enable) + if (ret) + return ret; + +- ret = clk_prepare_enable(fep->clk_enet_out); +- if (ret) +- goto failed_clk_enet_out; ++ if (fep->clk_enet_out) { ++ ret = clk_prepare_enable(fep->clk_enet_out); ++ if (ret) ++ goto failed_clk_enet_out; ++ ++ fec_reset_phy(fep); ++ } + + if (fep->clk_ptp) { + mutex_lock(&fep->ptp_clk_mutex); +@@ -3213,67 +3219,90 @@ static int fec_enet_init(struct net_device *ndev) + } + + #ifdef CONFIG_OF +-static int fec_reset_phy(struct platform_device *pdev) ++static void fec_reset_phy(struct fec_enet_private *fep) + { +- int err, phy_reset; +- bool active_high = false; +- int msec = 1, phy_post_delay = 0; +- struct device_node *np = pdev->dev.of_node; ++ if (!gpio_is_valid(fep->reset_gpio)) ++ return; + +- if (!np) +- return 0; ++ gpio_set_value_cansleep(fep->reset_gpio, fep->reset_active_high); + +- err = of_property_read_u32(np, "phy-reset-duration", &msec); +- /* A sane reset duration should not be longer than 1s */ +- if (!err && msec > 1000) +- msec = 1; ++ if (fep->phy_reset_duration > 20) ++ msleep(fep->phy_reset_duration); ++ else ++ usleep_range(fep->phy_reset_duration * 1000, ++ fep->phy_reset_duration * 1000 + 1000); + +- phy_reset = of_get_named_gpio(np, "phy-reset-gpios", 0); +- if (phy_reset == -EPROBE_DEFER) +- return phy_reset; +- else if (!gpio_is_valid(phy_reset)) +- return 0; ++ gpio_set_value_cansleep(fep->reset_gpio, !fep->reset_active_high); + +- err = of_property_read_u32(np, "phy-reset-post-delay", &phy_post_delay); +- /* valid reset duration should be less than 1s */ +- if (!err && phy_post_delay > 1000) +- return -EINVAL; ++ if (!fep->phy_post_delay) ++ return; ++ if (fep->phy_post_delay > 20) ++ msleep(fep->phy_post_delay); ++ else ++ usleep_range(fep->phy_post_delay * 1000, ++ fep->phy_post_delay * 1000 + 1000); ++} ++ ++static int fec_get_reset_gpio(struct platform_device *pdev) ++{ ++ int err; ++ struct device_node *np = pdev->dev.of_node; ++ struct net_device *ndev = platform_get_drvdata(pdev); ++ struct fec_enet_private *fep = netdev_priv(ndev); + +- active_high = of_property_read_bool(np, "phy-reset-active-high"); ++ /* Most DT files do not specify the correct polarity ++ * of the phy-reset GPIO. ++ * So use this special property to signal the actual ++ * signal polarity. ++ */ ++ fep->reset_gpio = of_get_named_gpio(np, "phy-reset-gpios", 0); ++ if (fep->reset_gpio == -EPROBE_DEFER) ++ return -EPROBE_DEFER; ++ if (!gpio_is_valid(fep->reset_gpio)) ++ return 0; ++ ++ fep->reset_active_high = of_property_read_bool(np, ++ "phy-reset-active-high"); + +- err = devm_gpio_request_one(&pdev->dev, phy_reset, +- active_high ? GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW, +- "phy-reset"); ++ err = devm_gpio_request_one(&pdev->dev, fep->reset_gpio, ++ fep->reset_active_high ? ++ GPIOF_OUT_INIT_LOW : GPIOF_OUT_INIT_HIGH, ++ "phy-reset"); + if (err) { + dev_err(&pdev->dev, "failed to get phy-reset-gpios: %d\n", err); + return err; + } + +- if (msec > 20) +- msleep(msec); +- else +- usleep_range(msec * 1000, msec * 1000 + 1000); +- +- gpio_set_value_cansleep(phy_reset, !active_high); +- +- if (!phy_post_delay) +- return 0; ++ err = of_property_read_u32(np, "phy-reset-duration", ++ &fep->phy_reset_duration); ++ /* A sane reset duration should not be longer than 1s */ ++ if (err || fep->phy_reset_duration > 1000) ++ fep->phy_reset_duration = 1; + +- if (phy_post_delay > 20) +- msleep(phy_post_delay); +- else +- usleep_range(phy_post_delay * 1000, +- phy_post_delay * 1000 + 1000); ++ err = of_property_read_u32(np, "phy-reset-post-delay", ++ &fep->phy_post_delay); ++ /* valid post reset delay should be less than 1s */ ++ if (err) ++ fep->phy_post_delay = 0; ++ else if (fep->phy_post_delay > 1000) ++ return -EINVAL; + + return 0; + } + #else /* CONFIG_OF */ +-static int fec_reset_phy(struct platform_device *pdev) ++/* In case of platform probe, the reset has been done ++ * by machine code. ++ */ ++static inline void fec_reset_phy(struct fec_enet_private *fep) + { +- /* +- * In case of platform probe, the reset has been done +- * by machine code. +- */ ++} ++ ++static int fec_get_reset_gpio(struct platform_device *pdev) ++{ ++ struct net_device *ndev = platform_get_drvdata(pdev); ++ struct fec_enet_private *fep = netdev_priv(ndev); ++ ++ fep->reset_gpio = -EINVAL; + return 0; + } + #endif /* CONFIG_OF */ +@@ -3455,9 +3484,10 @@ fec_probe(struct platform_device *pdev) + pm_runtime_set_active(&pdev->dev); + pm_runtime_enable(&pdev->dev); + +- ret = fec_reset_phy(pdev); ++ ret = fec_get_reset_gpio(pdev); + if (ret) + goto failed_reset; ++ fec_reset_phy(fep); + + if (fep->bufdesc_ex) + fec_ptp_init(pdev); diff --git a/recipes-kernel/linux/linux-karo-4.9.11/set-enet_ref_clk-to-50-mhz.patch b/recipes-kernel/linux/linux-karo-4.9.11/set-enet_ref_clk-to-50-mhz.patch new file mode 100755 index 0000000..088e9bb --- /dev/null +++ b/recipes-kernel/linux/linux-karo-4.9.11/set-enet_ref_clk-to-50-mhz.patch @@ -0,0 +1,25 @@ +diff --git a/arch/arm/mach-imx/clk-imx6q.c b/arch/arm/mach-imx/clk-imx6q.c +index f45de65..3845ab3 100644 +--- a/drivers/clk/imx/clk-imx6q.c ++++ b/drivers/clk/imx/clk-imx6q.c +@@ -882,6 +882,20 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node) + /*Set enet_ref clock to 125M to supply for RGMII tx_clk */ + clk_set_rate(clk[IMX6QDL_CLK_ENET_REF], 125000000); + ++ np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-fec"); ++ if (np) { ++ u32 clock_frequency; ++ int ret; ++ ++ ret = of_property_read_u32(np, "ref-clock", &clock_frequency); ++ if (ret == 0) { ++ printk("fec ref-clock: %d\n", clock_frequency); ++ imx_clk_set_rate(clk[IMX6QDL_CLK_ENET_REF], clock_frequency); ++ } ++ } ++ // This clock may be needed very early on ++ imx_clk_prepare_enable(clk[IMX6QDL_CLK_ENET_REF]); ++ + #ifdef CONFIG_MX6_VPU_352M + /* + * If VPU 352M is enabled, then PLL2_PDF2 need to be diff --git a/recipes-kernel/linux/linux-karo-4.9.11/tx6/defconfig b/recipes-kernel/linux/linux-karo-4.9.11/tx6/defconfig new file mode 100644 index 0000000..68aeadb --- /dev/null +++ b/recipes-kernel/linux/linux-karo-4.9.11/tx6/defconfig @@ -0,0 +1,461 @@ +CONFIG_LOCALVERSION="-1.0.0" +CONFIG_KERNEL_LZO=y +CONFIG_SYSVIPC=y +CONFIG_POSIX_MQUEUE=y +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_LOG_BUF_SHIFT=18 +CONFIG_CGROUPS=y +CONFIG_MEMCG=y +CONFIG_MEMCG_SWAP=y +CONFIG_BLK_CGROUP=y +CONFIG_CGROUP_SCHED=y +CONFIG_CFS_BANDWIDTH=y +CONFIG_RT_GROUP_SCHED=y +CONFIG_CGROUP_PIDS=y +CONFIG_CGROUP_FREEZER=y +CONFIG_CPUSETS=y +CONFIG_CGROUP_DEVICE=y +CONFIG_CGROUP_CPUACCT=y +CONFIG_CGROUP_PERF=y +CONFIG_NAMESPACES=y +CONFIG_RELAY=y +CONFIG_BLK_DEV_INITRD=y +CONFIG_EXPERT=y +CONFIG_KALLSYMS_ALL=y +CONFIG_PERF_EVENTS=y +# CONFIG_SLUB_DEBUG is not set +# CONFIG_COMPAT_BRK is not set +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +CONFIG_MODVERSIONS=y +CONFIG_MODULE_SRCVERSION_ALL=y +CONFIG_BLK_DEV_BSGLIB=y +CONFIG_BLK_DEV_INTEGRITY=y +CONFIG_BLK_DEV_THROTTLING=y +CONFIG_CFQ_GROUP_IOSCHED=y +CONFIG_ARCH_MXC=y +CONFIG_SOC_IMX50=y +CONFIG_SOC_IMX53=y +CONFIG_SOC_IMX6Q=y +CONFIG_SOC_IMX6SL=y +CONFIG_SOC_IMX6SX=y +CONFIG_SOC_IMX6ULL=y +CONFIG_SOC_IMX7D=y +CONFIG_SOC_IMX6SLL=y +CONFIG_SOC_VF610=y +CONFIG_ARM_THUMBEE=y +CONFIG_SMP=y +CONFIG_VMSPLIT_2G=y +CONFIG_PREEMPT=y +CONFIG_AEABI=y +CONFIG_HIGHMEM=y +CONFIG_CMA=y +CONFIG_ZBOOT_ROM_TEXT=0x0 +CONFIG_ZBOOT_ROM_BSS=0x0 +CONFIG_CMDLINE="noinitrd console=ttymxc0,115200" +CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y +CONFIG_CPU_FREQ_GOV_POWERSAVE=y +CONFIG_CPU_FREQ_GOV_USERSPACE=y +CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y +CONFIG_ARM_IMX6Q_CPUFREQ=y +CONFIG_CPU_IDLE=y +CONFIG_VFP=y +CONFIG_NEON=y +CONFIG_BINFMT_MISC=m +CONFIG_PM_DEBUG=y +CONFIG_PM_TEST_SUSPEND=y +CONFIG_NET=y +CONFIG_PACKET=y +CONFIG_PACKET_DIAG=m +CONFIG_UNIX=y +CONFIG_UNIX_DIAG=m +CONFIG_XFRM_USER=y +CONFIG_XFRM_SUB_POLICY=y +CONFIG_XFRM_MIGRATE=y +CONFIG_XFRM_STATISTICS=y +CONFIG_INET=y +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_INET_AH=m +CONFIG_INET_ESP=m +CONFIG_INET_XFRM_MODE_TRANSPORT=m +CONFIG_INET_XFRM_MODE_TUNNEL=m +CONFIG_INET_XFRM_MODE_BEET=m +CONFIG_NETFILTER=y +CONFIG_BRIDGE_NETFILTER=y +CONFIG_NF_CONNTRACK=y +CONFIG_NF_CONNTRACK_FTP=m +CONFIG_NF_CONNTRACK_IRC=m +CONFIG_NF_CONNTRACK_SIP=m +CONFIG_NF_CT_NETLINK=m +CONFIG_NETFILTER_XT_MARK=m +CONFIG_NETFILTER_XT_TARGET_LOG=m +CONFIG_NETFILTER_XT_TARGET_NFLOG=m +CONFIG_NETFILTER_XT_TARGET_TCPMSS=m +CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m +CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m +CONFIG_NETFILTER_XT_MATCH_IPVS=m +CONFIG_NETFILTER_XT_MATCH_POLICY=m +CONFIG_NETFILTER_XT_MATCH_STATE=m +CONFIG_IP_VS=m +CONFIG_NF_CONNTRACK_IPV4=y +CONFIG_NF_LOG_ARP=m +CONFIG_NF_NAT_IPV4=y +CONFIG_IP_NF_IPTABLES=m +CONFIG_IP_NF_MATCH_AH=m +CONFIG_IP_NF_MATCH_ECN=m +CONFIG_IP_NF_MATCH_RPFILTER=m +CONFIG_IP_NF_MATCH_TTL=m +CONFIG_IP_NF_FILTER=m +CONFIG_IP_NF_TARGET_REJECT=m +CONFIG_IP_NF_NAT=m +CONFIG_IP_NF_TARGET_MASQUERADE=m +CONFIG_IP_NF_MANGLE=m +CONFIG_NF_CONNTRACK_IPV6=m +CONFIG_IP6_NF_IPTABLES=m +CONFIG_IP6_NF_MATCH_AH=m +CONFIG_IP6_NF_MATCH_EUI64=m +CONFIG_IP6_NF_MATCH_FRAG=m +CONFIG_IP6_NF_MATCH_OPTS=m +CONFIG_IP6_NF_MATCH_HL=m +CONFIG_IP6_NF_MATCH_IPV6HEADER=m +CONFIG_IP6_NF_MATCH_RPFILTER=m +CONFIG_IP6_NF_MATCH_RT=m +CONFIG_IP6_NF_TARGET_HL=m +CONFIG_IP6_NF_FILTER=m +CONFIG_IP6_NF_TARGET_REJECT=m +CONFIG_IP6_NF_MANGLE=m +CONFIG_BRIDGE_NF_EBTABLES=m +CONFIG_BRIDGE_EBT_BROUTE=m +CONFIG_BRIDGE_EBT_T_FILTER=m +CONFIG_BRIDGE_EBT_T_NAT=m +CONFIG_BRIDGE_EBT_802_3=m +CONFIG_BRIDGE_EBT_AMONG=m +CONFIG_BRIDGE_EBT_ARP=m +CONFIG_BRIDGE_EBT_IP=m +CONFIG_BRIDGE_EBT_IP6=m +CONFIG_BRIDGE_EBT_LIMIT=m +CONFIG_BRIDGE_EBT_MARK=m +CONFIG_BRIDGE_EBT_PKTTYPE=m +CONFIG_BRIDGE_EBT_STP=m +CONFIG_BRIDGE_EBT_VLAN=m +CONFIG_BRIDGE_EBT_ARPREPLY=m +CONFIG_BRIDGE_EBT_DNAT=m +CONFIG_BRIDGE_EBT_MARK_T=m +CONFIG_BRIDGE_EBT_REDIRECT=m +CONFIG_BRIDGE_EBT_SNAT=m +CONFIG_BRIDGE_EBT_LOG=m +CONFIG_BRIDGE_EBT_NFLOG=m +CONFIG_BRIDGE=y +CONFIG_VLAN_8021Q=y +CONFIG_LLC2=y +CONFIG_NETLINK_DIAG=y +CONFIG_CGROUP_NET_PRIO=y +CONFIG_CGROUP_NET_CLASSID=y +CONFIG_CAN=y +CONFIG_CAN_FLEXCAN=y +CONFIG_CAN_M_CAN=y +CONFIG_BT=y +CONFIG_BT_RFCOMM=y +CONFIG_BT_RFCOMM_TTY=y +CONFIG_BT_BNEP=y +CONFIG_BT_BNEP_MC_FILTER=y +CONFIG_BT_BNEP_PROTO_FILTER=y +CONFIG_BT_HIDP=y +CONFIG_BT_HCIBTUSB=y +CONFIG_BT_HCIUART=y +CONFIG_BT_HCIUART_BCSP=y +CONFIG_BT_HCIUART_ATH3K=y +CONFIG_BT_HCIBCM203X=y +CONFIG_BT_ATH3K=y +CONFIG_CFG80211=y +CONFIG_MAC80211=y +CONFIG_DEVTMPFS=y +CONFIG_DEVTMPFS_MOUNT=y +# CONFIG_STANDALONE is not set +CONFIG_DMA_CMA=y +CONFIG_CMA_SIZE_MBYTES=0 +CONFIG_IMX_WEIM=y +CONFIG_CONNECTOR=y +CONFIG_MTD=y +CONFIG_MTD_TESTS=m +CONFIG_MTD_CMDLINE_PARTS=y +CONFIG_MTD_BLOCK=y +CONFIG_NFTL=y +CONFIG_NFTL_RW=y +CONFIG_MTD_NAND=y +CONFIG_MTD_NAND_GPMI_NAND=y +CONFIG_MTD_NAND_MXC=y +CONFIG_MTD_UBI=y +CONFIG_MTD_UBI_FASTMAP=y +CONFIG_MTD_UBI_GLUEBI=y +CONFIG_MTD_UBI_BLOCK=y +CONFIG_BLK_DEV_LOOP=y +CONFIG_VIRTIO_BLK=y +CONFIG_EEPROM_AT24=y +CONFIG_EEPROM_AT25=y +# CONFIG_SCSI_PROC_FS is not set +CONFIG_BLK_DEV_SD=y +CONFIG_SCSI_CONSTANTS=y +CONFIG_SCSI_LOGGING=y +CONFIG_SCSI_SCAN_ASYNC=y +# CONFIG_SCSI_LOWLEVEL is not set +CONFIG_ATA=y +CONFIG_SATA_AHCI_PLATFORM=y +CONFIG_AHCI_IMX=y +CONFIG_PATA_IMX=y +CONFIG_NETDEVICES=y +CONFIG_VXLAN=y +CONFIG_TUN=m +CONFIG_VETH=m +CONFIG_VIRTIO_NET=m +CONFIG_NLMON=m +# CONFIG_NET_VENDOR_BROADCOM is not set +CONFIG_CS89x0=y +CONFIG_CS89x0_PLATFORM=y +# CONFIG_NET_VENDOR_FARADAY is not set +# CONFIG_NET_VENDOR_INTEL is not set +# CONFIG_NET_VENDOR_MARVELL is not set +# CONFIG_NET_VENDOR_MICREL is not set +# CONFIG_NET_VENDOR_MICROCHIP is not set +# CONFIG_NET_VENDOR_NATSEMI is not set +# CONFIG_NET_VENDOR_SEEQ is not set +CONFIG_SMC91X=y +CONFIG_SMC911X=y +CONFIG_SMSC911X=y +# CONFIG_NET_VENDOR_STMICRO is not set +CONFIG_SMSC_PHY=y +CONFIG_USB_PEGASUS=m +CONFIG_USB_RTL8150=m +CONFIG_USB_RTL8152=m +CONFIG_USB_USBNET=m +CONFIG_USB_NET_CDC_EEM=m +# CONFIG_RTL_CARDS is not set +CONFIG_INPUT_EVDEV=y +CONFIG_INPUT_EVBUG=m +CONFIG_KEYBOARD_GPIO=y +CONFIG_KEYBOARD_IMX=y +CONFIG_MOUSE_PS2=m +CONFIG_MOUSE_PS2_ELANTECH=y +CONFIG_INPUT_TOUCHSCREEN=y +CONFIG_TOUCHSCREEN_EGALAX=y +CONFIG_TOUCHSCREEN_IMX6UL_TSC=y +CONFIG_TOUCHSCREEN_EDT_FT5X06=y +CONFIG_TOUCHSCREEN_USB_COMPOSITE=y +CONFIG_TOUCHSCREEN_TSC2007=y +CONFIG_TOUCHSCREEN_STMPE=y +CONFIG_INPUT_MISC=y +CONFIG_INPUT_MMA8450=y +CONFIG_SERIO_SERPORT=m +# CONFIG_LEGACY_PTYS is not set +CONFIG_SERIAL_IMX=y +CONFIG_SERIAL_IMX_CONSOLE=y +CONFIG_SERIAL_FSL_LPUART=y +CONFIG_SERIAL_FSL_LPUART_CONSOLE=y +# CONFIG_I2C_COMPAT is not set +CONFIG_I2C_CHARDEV=y +# CONFIG_I2C_HELPER_AUTO is not set +CONFIG_I2C_ALGOPCF=m +CONFIG_I2C_ALGOPCA=m +CONFIG_I2C_IMX=y +CONFIG_SPI=y +CONFIG_SPI_GPIO=y +CONFIG_SPI_IMX=y +CONFIG_GPIO_SYSFS=y +CONFIG_GPIO_MAX732X=y +CONFIG_GPIO_PCA953X=y +CONFIG_GPIO_74X164=y +CONFIG_POWER_RESET=y +CONFIG_POWER_RESET_SYSCON_POWEROFF=y +CONFIG_POWER_SUPPLY=y +CONFIG_THERMAL=y +CONFIG_CPU_THERMAL=y +CONFIG_IMX_THERMAL=y +CONFIG_WATCHDOG=y +CONFIG_IMX2_WDT=y +CONFIG_MFD_DA9052_I2C=y +CONFIG_MFD_MC13XXX_SPI=y +CONFIG_MFD_MC13XXX_I2C=y +CONFIG_MFD_SI476X_CORE=y +CONFIG_MFD_STMPE=y +CONFIG_REGULATOR=y +CONFIG_REGULATOR_FIXED_VOLTAGE=y +CONFIG_REGULATOR_ANATOP=y +CONFIG_REGULATOR_DA9052=y +CONFIG_REGULATOR_GPIO=y +CONFIG_REGULATOR_MC13783=y +CONFIG_REGULATOR_MC13892=y +CONFIG_REGULATOR_PFUZE100=y +CONFIG_MEDIA_SUPPORT=y +CONFIG_MEDIA_CAMERA_SUPPORT=y +CONFIG_MEDIA_RADIO_SUPPORT=y +CONFIG_MEDIA_USB_SUPPORT=y +CONFIG_USB_VIDEO_CLASS=m +CONFIG_V4L_PLATFORM_DRIVERS=y +CONFIG_SOC_CAMERA=y +CONFIG_V4L_MEM2MEM_DRIVERS=y +CONFIG_VIDEO_CODA=y +CONFIG_RADIO_SI476X=y +CONFIG_DRM=y +CONFIG_DRM_VIVANTE=y +CONFIG_DRM_PANEL_SIMPLE=y +CONFIG_DRM_IMX=y +CONFIG_DRM_IMX_PARALLEL_DISPLAY=y +CONFIG_DRM_IMX_LDB=y +CONFIG_FB_MXS=y +CONFIG_FB_MXC_SYNC_PANEL=y +CONFIG_FB_MXC_OVERLAY=y +CONFIG_FB_MXC_LDB=y +CONFIG_LCD_CLASS_DEVICE=y +CONFIG_LCD_L4F00242T03=y +CONFIG_LCD_PLATFORM=y +CONFIG_BACKLIGHT_PWM=y +CONFIG_FRAMEBUFFER_CONSOLE=y +CONFIG_LOGO=y +CONFIG_SOUND=y +CONFIG_SND=y +CONFIG_SND_USB_AUDIO=m +CONFIG_SND_SOC=y +CONFIG_SND_IMX_SOC=y +CONFIG_SND_SOC_EUKREA_TLV320=y +CONFIG_SND_SOC_IMX_WM8962=y +CONFIG_SND_SOC_IMX_SGTL5000=y +CONFIG_SND_SOC_IMX_SPDIF=y +CONFIG_SND_SOC_IMX_MC13783=y +CONFIG_HID_MULTITOUCH=y +CONFIG_USB_OTG_WHITELIST=y +CONFIG_USB_EHCI_HCD=y +CONFIG_USB_EHCI_MXC=y +CONFIG_USB_HCD_TEST_MODE=y +CONFIG_USB_ACM=m +CONFIG_USB_STORAGE=y +CONFIG_USB_CHIPIDEA=y +CONFIG_USB_CHIPIDEA_UDC=y +CONFIG_USB_CHIPIDEA_HOST=y +CONFIG_USB_SERIAL=m +CONFIG_USB_SERIAL_GENERIC=y +CONFIG_USB_SERIAL_FTDI_SIO=m +CONFIG_USB_SERIAL_OPTION=m +CONFIG_USB_EHSET_TEST_FIXTURE=y +CONFIG_NOP_USB_XCEIV=y +CONFIG_USB_MXS_PHY=y +CONFIG_USB_GADGET=y +CONFIG_USB_CONFIGFS=m +CONFIG_USB_CONFIGFS_SERIAL=y +CONFIG_USB_CONFIGFS_ACM=y +CONFIG_USB_CONFIGFS_OBEX=y +CONFIG_USB_CONFIGFS_NCM=y +CONFIG_USB_CONFIGFS_ECM=y +CONFIG_USB_CONFIGFS_ECM_SUBSET=y +CONFIG_USB_CONFIGFS_RNDIS=y +CONFIG_USB_CONFIGFS_EEM=y +CONFIG_USB_CONFIGFS_MASS_STORAGE=y +CONFIG_USB_CONFIGFS_F_LB_SS=y +CONFIG_USB_CONFIGFS_F_FS=y +CONFIG_USB_ZERO=m +CONFIG_USB_ETH=m +CONFIG_USB_G_NCM=m +CONFIG_USB_GADGETFS=m +CONFIG_USB_MASS_STORAGE=m +CONFIG_USB_G_SERIAL=m +CONFIG_MMC=y +CONFIG_MMC_SDHCI=y +CONFIG_MMC_SDHCI_PLTFM=y +CONFIG_MMC_SDHCI_ESDHC_IMX=y +CONFIG_MXC_IPU=y +CONFIG_MXC_IPU_V3_PRE=y +CONFIG_MXC_GPU_VIV=y +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y +CONFIG_LEDS_GPIO=y +CONFIG_LEDS_TRIGGERS=y +CONFIG_LEDS_TRIGGER_TIMER=y +CONFIG_LEDS_TRIGGER_ONESHOT=y +CONFIG_LEDS_TRIGGER_HEARTBEAT=y +CONFIG_LEDS_TRIGGER_BACKLIGHT=y +CONFIG_LEDS_TRIGGER_GPIO=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_INTF_DEV_UIE_EMUL=y +CONFIG_RTC_DRV_DS1307=y +CONFIG_DMADEVICES=y +CONFIG_IMX_SDMA=y +CONFIG_MXS_DMA=y +CONFIG_DMATEST=m +CONFIG_STAGING=y +CONFIG_STAGING_MEDIA=y +# CONFIG_IOMMU_SUPPORT is not set +CONFIG_IIO=y +CONFIG_IMX7D_ADC=y +CONFIG_VF610_ADC=y +CONFIG_PWM=y +CONFIG_PWM_IMX=y +CONFIG_EXT4_FS=y +CONFIG_EXT4_FS_POSIX_ACL=y +CONFIG_EXT4_FS_SECURITY=y +CONFIG_BTRFS_FS=m +CONFIG_BTRFS_FS_POSIX_ACL=y +CONFIG_QUOTA=y +CONFIG_QUOTA_NETLINK_INTERFACE=y +# CONFIG_PRINT_QUOTA_WARNING is not set +CONFIG_AUTOFS4_FS=y +CONFIG_FUSE_FS=y +CONFIG_OVERLAY_FS=y +CONFIG_ISO9660_FS=m +CONFIG_JOLIET=y +CONFIG_ZISOFS=y +CONFIG_UDF_FS=m +CONFIG_MSDOS_FS=m +CONFIG_VFAT_FS=y +CONFIG_TMPFS=y +CONFIG_UBIFS_FS=y +CONFIG_UBIFS_FS_ADVANCED_COMPR=y +CONFIG_CRAMFS=y +CONFIG_NFS_FS=y +CONFIG_NFS_V3_ACL=y +CONFIG_NFS_V4=y +CONFIG_ROOT_NFS=y +CONFIG_NLS_DEFAULT="cp437" +CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_ASCII=y +CONFIG_NLS_ISO8859_1=y +CONFIG_NLS_ISO8859_15=m +CONFIG_NLS_UTF8=y +CONFIG_DEBUG_FS=y +CONFIG_MAGIC_SYSRQ=y +# CONFIG_SCHED_DEBUG is not set +# CONFIG_DEBUG_BUGVERBOSE is not set +# CONFIG_FTRACE is not set +CONFIG_SECURITYFS=y +CONFIG_CRYPTO_USER=y +CONFIG_CRYPTO_TEST=m +CONFIG_CRYPTO_CBC=y +CONFIG_CRYPTO_CTS=y +CONFIG_CRYPTO_LRW=y +CONFIG_CRYPTO_XTS=y +CONFIG_CRYPTO_MD4=y +CONFIG_CRYPTO_MD5=y +CONFIG_CRYPTO_MICHAEL_MIC=y +CONFIG_CRYPTO_RMD128=y +CONFIG_CRYPTO_RMD160=y +CONFIG_CRYPTO_RMD256=y +CONFIG_CRYPTO_RMD320=y +CONFIG_CRYPTO_SHA1=y +CONFIG_CRYPTO_SHA512=y +CONFIG_CRYPTO_TGR192=y +CONFIG_CRYPTO_WP512=y +CONFIG_CRYPTO_BLOWFISH=y +CONFIG_CRYPTO_CAMELLIA=y +CONFIG_CRYPTO_TWOFISH=y +CONFIG_CRYPTO_DEV_FSL_CAAM=y +CONFIG_CRC_CCITT=m +CONFIG_CRC_T10DIF=y +CONFIG_CRC7=m +CONFIG_LIBCRC32C=m +CONFIG_FONTS=y +CONFIG_FONT_8x8=y +CONFIG_FONT_8x16=y diff --git a/recipes-kernel/linux/linux-karo-4.9.11/tx6/imx6qdl-tx6-gpio.h b/recipes-kernel/linux/linux-karo-4.9.11/tx6/imx6qdl-tx6-gpio.h new file mode 100755 index 0000000..2ee5c86 --- /dev/null +++ b/recipes-kernel/linux/linux-karo-4.9.11/tx6/imx6qdl-tx6-gpio.h @@ -0,0 +1,338 @@ +/* + * Copyright 2016 Lothar Waßmann + * Copyright 2016 Michael Vyskocil + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file 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 file 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. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef __DTS_TX6QDL_GPIO_H +#define __DTS_TX6QDL_GPIO_H + +#define TX_GPIO_PIN15 &gpio7 12 +#define TX_GPIO_PIN27 &gpio3 31 +#define TX_GPIO_PIN28 &gpio3 30 +#define TX_GPIO_PIN33 &gpio3 23 +#define TX_GPIO_PIN34 &gpio1 7 +#define TX_GPIO_PIN36 &gpio1 8 +#define TX_GPIO_PIN40 &gpio1 6 +#define TX_GPIO_PIN41 &gpio1 3 +#define TX_GPIO_PIN42 &gpio1 1 +#define TX_GPIO_PIN43 &gpio7 13 +#define TX_GPIO_PIN44 &gpio2 30 +#define TX_GPIO_PIN45 &gpio3 19 +#define TX_GPIO_PIN46 &gpio3 18 +#define TX_GPIO_PIN47 &gpio3 17 +#define TX_GPIO_PIN48 &gpio3 16 +#define TX_GPIO_PIN49 &gpio4 5 +#define TX_GPIO_PIN51 &gpio7 2 +#define TX_GPIO_PIN52 &gpio1 16 +#define TX_GPIO_PIN53 &gpio1 17 +#define TX_GPIO_PIN54 &gpio1 19 +#define TX_GPIO_PIN55 &gpio1 21 +#define TX_GPIO_PIN56 &gpio1 18 +#define TX_GPIO_PIN57 &gpio1 20 +#define TX_GPIO_PIN59 &gpio6 17 +#define TX_GPIO_PIN60 &gpio6 18 +#define TX_GPIO_PIN61 &gpio7 5 +#define TX_GPIO_PIN62 &gpio7 4 +#define TX_GPIO_PIN63 &gpio2 15 +#define TX_GPIO_PIN64 &gpio2 12 +#define TX_GPIO_PIN65 &gpio2 13 +#define TX_GPIO_PIN66 &gpio2 14 +#define TX_GPIO_PIN67 &gpio3 24 +#define TX_GPIO_PIN68 &gpio3 25 +#define TX_GPIO_PIN69 &gpio7 8 +#define TX_GPIO_PIN70 &gpio7 7 +#define TX_GPIO_PIN72 &gpio1 9 +#define TX_GPIO_PIN73 &gpio1 4 +#define TX_GPIO_PIN74 &gpio4 10 +#define TX_GPIO_PIN75 &gpio4 12 +#define TX_GPIO_PIN76 &gpio4 14 +#define TX_GPIO_PIN77 &gpio1 2 +#define TX_GPIO_PIN78 &gpio1 5 +#define TX_GPIO_PIN79 &gpio4 11 +#define TX_GPIO_PIN80 &gpio4 13 +#define TX_GPIO_PIN81 &gpio4 15 +#define TX_GPIO_PIN83 &gpio3 26 +#define TX_GPIO_PIN84 &gpio4 9 +#define TX_GPIO_PIN85 &gpio4 7 +#define TX_GPIO_PIN86 &gpio4 6 +#define TX_GPIO_PIN87 &gpio4 8 +#define TX_GPIO_PIN89 &gpio3 27 +#define TX_GPIO_PIN90 &gpio5 25 +#define TX_GPIO_PIN91 &gpio5 23 +#define TX_GPIO_PIN92 &gpio5 22 +#define TX_GPIO_PIN93 &gpio5 24 +#define TX_GPIO_PIN95 &gpio7 3 +#define TX_GPIO_PIN96 &gpio1 15 +#define TX_GPIO_PIN97 &gpio1 14 +#define TX_GPIO_PIN98 &gpio1 13 +#define TX_GPIO_PIN99 &gpio1 12 +#define TX_GPIO_PIN100 &gpio1 11 +#define TX_GPIO_PIN101 &gpio1 10 +#define TX_GPIO_PIN103 &gpio5 30 +#define TX_GPIO_PIN104 &gpio5 31 +#define TX_GPIO_PIN105 &gpio6 0 +#define TX_GPIO_PIN106 &gpio6 1 +#define TX_GPIO_PIN107 &gpio6 2 +#define TX_GPIO_PIN108 &gpio6 3 +#define TX_GPIO_PIN109 &gpio6 4 +#define TX_GPIO_PIN110 &gpio6 5 +#define TX_GPIO_PIN112 &gpio5 19 +#define TX_GPIO_PIN113 &gpio5 21 +#define TX_GPIO_PIN114 &gpio5 18 +#define TX_GPIO_PIN115 &gpio1 0 +#define TX_GPIO_PIN117 &gpio4 21 +#define TX_GPIO_PIN118 &gpio4 22 +#define TX_GPIO_PIN119 &gpio4 23 +#define TX_GPIO_PIN120 &gpio4 24 +#define TX_GPIO_PIN121 &gpio4 25 +#define TX_GPIO_PIN122 &gpio4 26 +#define TX_GPIO_PIN123 &gpio4 27 +#define TX_GPIO_PIN124 &gpio4 28 +#define TX_GPIO_PIN125 &gpio4 29 +#define TX_GPIO_PIN126 &gpio4 30 +#define TX_GPIO_PIN127 &gpio4 31 +#define TX_GPIO_PIN128 &gpio5 5 +#define TX_GPIO_PIN130 &gpio5 6 +#define TX_GPIO_PIN131 &gpio5 7 +#define TX_GPIO_PIN132 &gpio5 8 +#define TX_GPIO_PIN133 &gpio5 9 +#define TX_GPIO_PIN134 &gpio5 10 +#define TX_GPIO_PIN135 &gpio5 11 +#define TX_GPIO_PIN136 &gpio5 12 +#define TX_GPIO_PIN137 &gpio5 13 +#define TX_GPIO_PIN138 &gpio5 14 +#define TX_GPIO_PIN139 &gpio5 15 +#define TX_GPIO_PIN140 &gpio5 16 +#define TX_GPIO_PIN141 &gpio5 17 +#define TX_GPIO_PIN143 &gpio4 18 +#define TX_GPIO_PIN144 &gpio4 19 +#define TX_GPIO_PIN145 &gpio4 17 +#define TX_GPIO_PIN146 &gpio4 16 +#define TX_GPIO_PIN148 &gpio6 15 +#define TX_GPIO_PIN149 &gpio2 22 +#define TX_GPIO_PIN150 &gpio3 29 +#define TX_GPIO_PIN151 &gpio2 31 +#define TX_GPIO_PIN152 &gpio2 21 +#define TX_GPIO_PIN153 &gpio2 20 +#define TX_GPIO_PIN154 &gpio2 19 +#define TX_GPIO_PIN155 &gpio2 18 +#define TX_GPIO_PIN156 &gpio2 17 +#define TX_GPIO_PIN157 &gpio2 16 +#define TX_GPIO_PIN158 &gpio6 6 +#define TX_GPIO_PIN159 &gpio5 4 +#define TX_GPIO_PIN161 &gpio5 26 +#define TX_GPIO_PIN162 &gpio5 27 +#define TX_GPIO_PIN163 &gpio5 28 +#define TX_GPIO_PIN164 &gpio5 29 +#define TX_GPIO_PIN165 &gpio3 22 +#define TX_GPIO_PIN173 &gpio2 23 +#define TX_GPIO_PIN174 &gpio2 24 +#define TX_GPIO_PIN175 &gpio5 20 +#define TX_GPIO_PIN176 &gpio5 0 +#define TX_GPIO_PIN177 &gpio2 28 +#define TX_GPIO_PIN178 &gpio2 29 +#define TX_GPIO_PIN179 &gpio2 25 +#define TX_GPIO_PIN180 &gpio2 27 +#define TX_GPIO_PIN181 &gpio2 26 +#define TX_GPIO_PIN182 &gpio6 31 +#define TX_GPIO_PIN184 &gpio3 0 +#define TX_GPIO_PIN185 &gpio3 1 +#define TX_GPIO_PIN186 &gpio3 2 +#define TX_GPIO_PIN187 &gpio3 3 +#define TX_GPIO_PIN188 &gpio3 4 +#define TX_GPIO_PIN189 &gpio3 5 +#define TX_GPIO_PIN190 &gpio3 6 +#define TX_GPIO_PIN191 &gpio3 7 +#define TX_GPIO_PIN192 &gpio3 8 +#define TX_GPIO_PIN193 &gpio3 9 +#define TX_GPIO_PIN194 &gpio3 10 +#define TX_GPIO_PIN195 &gpio3 11 +#define TX_GPIO_PIN196 &gpio3 12 +#define TX_GPIO_PIN197 &gpio3 13 +#define TX_GPIO_PIN198 &gpio3 14 +#define TX_GPIO_PIN199 &gpio3 15 + +#define TX_GPIO_PAD15 MX6QDL_PAD_GPIO_17__GPIO7_IO12 0x1b0b0 +#define TX_GPIO_PAD27 MX6QDL_PAD_EIM_D31__GPIO3_IO31 0x1b0b0 +#define TX_GPIO_PAD28 MX6QDL_PAD_EIM_D30__GPIO3_IO30 0x1b0b0 +#define TX_GPIO_PAD33 MX6QDL_PAD_EIM_D23__GPIO3_IO23 0x1b0b0 +#define TX_GPIO_PAD34 MX6QDL_PAD_GPIO_7__GPIO1_IO07 0x1b0b0 +#define TX_GPIO_PAD36 MX6QDL_PAD_GPIO_8__GPIO1_IO08 0x1b0b0 +#define TX_GPIO_PAD40 MX6QDL_PAD_GPIO_6__GPIO1_IO06 0x1b0b0 +#define TX_GPIO_PAD41 MX6QDL_PAD_GPIO_3__GPIO1_IO03 0x1b0b0 +#define TX_GPIO_PAD42 MX6QDL_PAD_GPIO_1__GPIO1_IO01 0x1b0b0 +#define TX_GPIO_PAD43 MX6QDL_PAD_GPIO_18__GPIO7_IO13 0x1b0b0 +#define TX_GPIO_PAD44 MX6QDL_PAD_EIM_EB2__GPIO2_IO30 0x1b0b0 +#define TX_GPIO_PAD45 MX6QDL_PAD_EIM_D19__GPIO3_IO19 0x1b0b0 +#define TX_GPIO_PAD46 MX6QDL_PAD_EIM_D18__GPIO3_IO18 0x1b0b0 +#define TX_GPIO_PAD47 MX6QDL_PAD_EIM_D17__GPIO3_IO17 0x1b0b0 +#define TX_GPIO_PAD48 MX6QDL_PAD_EIM_D16__GPIO3_IO16 0x1b0b0 +#define TX_GPIO_PAD49 MX6QDL_PAD_GPIO_19__GPIO4_IO05 0x1b0b0 +#define TX_GPIO_PAD51 MX6QDL_PAD_SD3_CMD__GPIO7_IO02 0x1b0b0 +#define TX_GPIO_PAD52 MX6QDL_PAD_SD1_DAT0__GPIO1_IO16 0x1b0b0 +#define TX_GPIO_PAD53 MX6QDL_PAD_SD1_DAT1__GPIO1_IO17 0x1b0b0 +#define TX_GPIO_PAD54 MX6QDL_PAD_SD1_DAT2__GPIO1_IO19 0x1b0b0 +#define TX_GPIO_PAD55 MX6QDL_PAD_SD1_DAT3__GPIO1_IO21 0x1b0b0 +#define TX_GPIO_PAD56 MX6QDL_PAD_SD1_CMD__GPIO1_IO18 0x1b0b0 +#define TX_GPIO_PAD57 MX6QDL_PAD_SD1_CLK__GPIO1_IO20 0x1b0b0 +#define TX_GPIO_PAD59 MX6QDL_PAD_SD3_DAT7__GPIO6_IO17 0x1b0b0 +#define TX_GPIO_PAD60 MX6QDL_PAD_SD3_DAT6__GPIO6_IO18 0x1b0b0 +#define TX_GPIO_PAD61 MX6QDL_PAD_SD3_DAT1__GPIO7_IO05 0x1b0b0 +#define TX_GPIO_PAD62 MX6QDL_PAD_SD3_DAT0__GPIO7_IO04 0x1b0b0 +#define TX_GPIO_PAD63 MX6QDL_PAD_SD4_DAT7__GPIO2_IO15 0x1b0b0 +#define TX_GPIO_PAD64 MX6QDL_PAD_SD4_DAT4__GPIO2_IO12 0x1b0b0 +#define TX_GPIO_PAD65 MX6QDL_PAD_SD4_DAT5__GPIO2_IO13 0x1b0b0 +#define TX_GPIO_PAD66 MX6QDL_PAD_SD4_DAT6__GPIO2_IO14 0x1b0b0 +#define TX_GPIO_PAD67 MX6QDL_PAD_EIM_D24__GPIO3_IO24 0x1b0b0 +#define TX_GPIO_PAD68 MX6QDL_PAD_EIM_D25__GPIO3_IO25 0x1b0b0 +#define TX_GPIO_PAD69 MX6QDL_PAD_SD3_RST__GPIO7_IO08 0x1b0b0 +#define TX_GPIO_PAD70 MX6QDL_PAD_SD3_DAT3__GPIO7_IO07 0x1b0b0 +#define TX_GPIO_PAD72 MX6QDL_PAD_GPIO_9__GPIO1_IO09 0x1b0b0 +#define TX_GPIO_PAD73 MX6QDL_PAD_GPIO_4__GPIO1_IO04 0x1b0b0 +#define TX_GPIO_PAD74 MX6QDL_PAD_KEY_COL2__GPIO4_IO10 0x1b0b0 +#define TX_GPIO_PAD75 MX6QDL_PAD_KEY_COL3__GPIO4_IO12 0x1b0b0 +#define TX_GPIO_PAD76 MX6QDL_PAD_KEY_COL4__GPIO4_IO14 0x1b0b0 +#define TX_GPIO_PAD77 MX6QDL_PAD_GPIO_2__GPIO1_IO02 0x1b0b0 +#define TX_GPIO_PAD78 MX6QDL_PAD_GPIO_5__GPIO1_IO05 0x1b0b0 +#define TX_GPIO_PAD79 MX6QDL_PAD_KEY_ROW2__GPIO4_IO11 0x1b0b0 +#define TX_GPIO_PAD80 MX6QDL_PAD_KEY_ROW3__GPIO4_IO13 0x1b0b0 +#define TX_GPIO_PAD81 MX6QDL_PAD_KEY_ROW4__GPIO4_IO15 0x1b0b0 +#define TX_GPIO_PAD83 MX6QDL_PAD_EIM_D26__GPIO3_IO26 0x1b0b0 +#define TX_GPIO_PAD84 MX6QDL_PAD_KEY_ROW1 __GPIO4_IO09 0x1b0b0 +#define TX_GPIO_PAD85 MX6QDL_PAD_KEY_ROW0__GPIO4_IO07 0x1b0b0 +#define TX_GPIO_PAD86 MX6QDL_PAD_KEY_COL0__GPIO4_IO06 0x1b0b0 +#define TX_GPIO_PAD87 MX6QDL_PAD_KEY_COL1__GPIO4_IO08 0x1b0b0 +#define TX_GPIO_PAD89 MX6QDL_PAD_EIM_D27__GPIO3_IO27 0x1b0b0 +#define TX_GPIO_PAD90 MX6QDL_PAD_CSI0_DAT7__GPIO5_IO25 0x1b0b0 +#define TX_GPIO_PAD91 MX6QDL_PAD_CSI0_DAT5 __GPIO5_IO23 0x1b0b0 +#define TX_GPIO_PAD92 MX6QDL_PAD_CSI0_DAT4__GPIO5_IO22 0x1b0b0 +#define TX_GPIO_PAD93 MX6QDL_PAD_CSI0_DAT6 __GPIO5_IO24 0x1b0b0 +#define TX_GPIO_PAD95 MX6QDL_PAD_SD3_CLK__GPIO7_IO03 0x1b0b0 +#define TX_GPIO_PAD96 MX6QDL_PAD_SD2_DAT0__GPIO1_IO15 0x1b0b0 +#define TX_GPIO_PAD97 MX6QDL_PAD_SD2_DAT1__GPIO1_IO14 0x1b0b0 +#define TX_GPIO_PAD98 MX6QDL_PAD_SD2_DAT2__GPIO1_IO13 0x1b0b0 +#define TX_GPIO_PAD99 MX6QDL_PAD_SD2_DAT3__GPIO1_IO12 0x1b0b0 +#define TX_GPIO_PAD100 MX6QDL_PAD_SD2_CMD__GPIO1_IO11 0x1b0b0 +#define TX_GPIO_PAD101 MX6QDL_PAD_SD2_CLK__GPIO1_IO10 0x1b0b0 +#define TX_GPIO_PAD103 MX6QDL_PAD_CSI0_DAT12__GPIO5_IO30 0x1b0b0 +#define TX_GPIO_PAD104 MX6QDL_PAD_CSI0_DAT13__GPIO5_IO31 0x1b0b0 +#define TX_GPIO_PAD105 MX6QDL_PAD_CSI0_DAT14__GPIO6_IO00 0x1b0b0 +#define TX_GPIO_PAD106 MX6QDL_PAD_CSI0_DAT15__GPIO6_IO01 0x1b0b0 +#define TX_GPIO_PAD107 MX6QDL_PAD_CSI0_DAT16__GPIO6_IO02 0x1b0b0 +#define TX_GPIO_PAD108 MX6QDL_PAD_CSI0_DAT17__GPIO6_IO03 0x1b0b0 +#define TX_GPIO_PAD109 MX6QDL_PAD_CSI0_DAT18__GPIO6_IO04 0x1b0b0 +#define TX_GPIO_PAD110 MX6QDL_PAD_CSI0_DAT19__GPIO6_IO05 0x1b0b0 +#define TX_GPIO_PAD112 MX6QDL_PAD_CSI0_MCLK__GPIO5_IO19 0x1b0b0 +#define TX_GPIO_PAD113 MX6QDL_PAD_CSI0_VSYNC__GPIO5_IO21 0x1b0b0 +#define TX_GPIO_PAD114 MX6QDL_PAD_CSI0_PIXCLK__GPIO5_IO18 0x1b0b0 +#define TX_GPIO_PAD115 MX6QDL_PAD_GPIO_0__GPIO1_IO00 0x1b0b0 +#define TX_GPIO_PAD117 MX6QDL_PAD_DISP0_DAT0__GPIO4_IO21 0x1b0b0 +#define TX_GPIO_PAD118 MX6QDL_PAD_DISP0_DAT1__GPIO4_IO22 0x1b0b0 +#define TX_GPIO_PAD119 MX6QDL_PAD_DISP0_DAT2__GPIO4_IO23 0x1b0b0 +#define TX_GPIO_PAD120 MX6QDL_PAD_DISP0_DAT3__GPIO4_IO24 0x1b0b0 +#define TX_GPIO_PAD121 MX6QDL_PAD_DISP0_DAT4__GPIO4_IO25 0x1b0b0 +#define TX_GPIO_PAD122 MX6QDL_PAD_DISP0_DAT5__GPIO4_IO26 0x1b0b0 +#define TX_GPIO_PAD123 MX6QDL_PAD_DISP0_DAT6__GPIO4_IO27 0x1b0b0 +#define TX_GPIO_PAD124 MX6QDL_PAD_DISP0_DAT7__GPIO4_IO28 0x1b0b0 +#define TX_GPIO_PAD125 MX6QDL_PAD_DISP0_DAT8__GPIO4_IO29 0x1b0b0 +#define TX_GPIO_PAD126 MX6QDL_PAD_DISP0_DAT9__GPIO4_IO30 0x1b0b0 +#define TX_GPIO_PAD127 MX6QDL_PAD_DISP0_DAT10__GPIO4_IO31 0x1b0b0 +#define TX_GPIO_PAD128 MX6QDL_PAD_DISP0_DAT11__GPIO5_IO05 0x1b0b0 +#define TX_GPIO_PAD130 MX6QDL_PAD_DISP0_DAT12__GPIO5_IO06 0x1b0b0 +#define TX_GPIO_PAD131 MX6QDL_PAD_DISP0_DAT13__GPIO5_IO07 0x1b0b0 +#define TX_GPIO_PAD132 MX6QDL_PAD_DISP0_DAT14__GPIO5_IO08 0x1b0b0 +#define TX_GPIO_PAD133 MX6QDL_PAD_DISP0_DAT15__GPIO5_IO09 0x1b0b0 +#define TX_GPIO_PAD134 MX6QDL_PAD_DISP0_DAT16__GPIO5_IO10 0x1b0b0 +#define TX_GPIO_PAD135 MX6QDL_PAD_DISP0_DAT17__GPIO5_IO11 0x1b0b0 +#define TX_GPIO_PAD136 MX6QDL_PAD_DISP0_DAT18__GPIO5_IO12 0x1b0b0 +#define TX_GPIO_PAD137 MX6QDL_PAD_DISP0_DAT19__GPIO5_IO13 0x1b0b0 +#define TX_GPIO_PAD138 MX6QDL_PAD_DISP0_DAT20__GPIO5_IO14 0x1b0b0 +#define TX_GPIO_PAD139 MX6QDL_PAD_DISP0_DAT21__GPIO5_IO15 0x1b0b0 +#define TX_GPIO_PAD140 MX6QDL_PAD_DISP0_DAT22__GPIO5_IO16 0x1b0b0 +#define TX_GPIO_PAD141 MX6QDL_PAD_DISP0_DAT23__GPIO5_IO17 0x1b0b0 +#define TX_GPIO_PAD143 MX6QDL_PAD_DI0_PIN2__GPIO4_IO18 0x1b0b0 +#define TX_GPIO_PAD144 MX6QDL_PAD_DI0_PIN3__GPIO4_IO19 0x1b0b0 +#define TX_GPIO_PAD145 MX6QDL_PAD_DI0_PIN15__GPIO4_IO17 0x1b0b0 +#define TX_GPIO_PAD146 MX6QDL_PAD_DI0_DISP_CLK__GPIO4_IO16 0x1b0b0 +#define TX_GPIO_PAD148 MX6QDL_PAD_NANDF_CS2__GPIO6_IO15 0x1b0b0 +#define TX_GPIO_PAD149 MX6QDL_PAD_EIM_A16__GPIO2_IO22 0x1b0b0 +#define TX_GPIO_PAD150 MX6QDL_PAD_EIM_D29__GPIO3_IO29 0x1b0b0 +#define TX_GPIO_PAD151 MX6QDL_PAD_EIM_EB3__GPIO2_IO31 0x1b0b0 +#define TX_GPIO_PAD152 MX6QDL_PAD_EIM_A17__GPIO2_IO21 0x1b0b0 +#define TX_GPIO_PAD153 MX6QDL_PAD_EIM_A18__GPIO2_IO20 0x1b0b0 +#define TX_GPIO_PAD154 MX6QDL_PAD_EIM_A19__GPIO2_IO19 0x1b0b0 +#define TX_GPIO_PAD155 MX6QDL_PAD_EIM_A20__GPIO2_IO18 0x1b0b0 +#define TX_GPIO_PAD156 MX6QDL_PAD_EIM_A21__GPIO2_IO17 0x1b0b0 +#define TX_GPIO_PAD157 MX6QDL_PAD_EIM_A22__GPIO2_IO16 0x1b0b0 +#define TX_GPIO_PAD158 MX6QDL_PAD_EIM_A23__GPIO6_IO06 0x1b0b0 +#define TX_GPIO_PAD159 MX6QDL_PAD_EIM_A24__GPIO5_IO04 0x1b0b0 +#define TX_GPIO_PAD161 MX6QDL_PAD_CSI0_DAT8__GPIO5_IO26 0x1b0b0 +#define TX_GPIO_PAD162 MX6QDL_PAD_CSI0_DAT9 __GPIO5_IO27 0x1b0b0 +#define TX_GPIO_PAD163 MX6QDL_PAD_CSI0_DAT10__GPIO5_IO28 0x1b0b0 +#define TX_GPIO_PAD164 MX6QDL_PAD_CSI0_DAT11__GPIO5_IO29 0x1b0b0 +#define TX_GPIO_PAD165 MX6QDL_PAD_EIM_D22__GPIO3_IO22 0x1b0b0 +#define TX_GPIO_PAD173 MX6QDL_PAD_EIM_CS0__GPIO2_IO23 0x1b0b0 +#define TX_GPIO_PAD174 MX6QDL_PAD_EIM_CS1__GPIO2_IO24 0x1b0b0 +#define TX_GPIO_PAD175 MX6QDL_PAD_CSI0_DATA_EN__GPIO5_IO20 0x1b0b0 +#define TX_GPIO_PAD176 MX6QDL_PAD_EIM_WAIT__GPIO5_IO00 0x1b0b0 +#define TX_GPIO_PAD177 MX6QDL_PAD_EIM_EB0__GPIO2_IO28 0x1b0b0 +#define TX_GPIO_PAD178 MX6QDL_PAD_EIM_EB1__GPIO2_IO29 0x1b0b0 +#define TX_GPIO_PAD179 MX6QDL_PAD_EIM_OE__GPIO2_IO25 0x1b0b0 +#define TX_GPIO_PAD180 MX6QDL_PAD_EIM_LBA__GPIO2_IO27 0x1b0b0 +#define TX_GPIO_PAD181 MX6QDL_PAD_EIM_RW__GPIO2_IO26 0x1b0b0 +#define TX_GPIO_PAD182 MX6QDL_PAD_EIM_BCLK__GPIO6_IO31 0x1b0b0 +#define TX_GPIO_PAD184 MX6QDL_PAD_EIM_DA0__GPIO3_IO00 0x1b0b0 +#define TX_GPIO_PAD185 MX6QDL_PAD_EIM_DA1__GPIO3_IO01 0x1b0b0 +#define TX_GPIO_PAD186 MX6QDL_PAD_EIM_DA2__GPIO3_IO02 0x1b0b0 +#define TX_GPIO_PAD187 MX6QDL_PAD_EIM_DA3__GPIO3_IO03 0x1b0b0 +#define TX_GPIO_PAD188 MX6QDL_PAD_EIM_DA4__GPIO3_IO04 0x1b0b0 +#define TX_GPIO_PAD189 MX6QDL_PAD_EIM_DA5__GPIO3_IO05 0x1b0b0 +#define TX_GPIO_PAD190 MX6QDL_PAD_EIM_DA6__GPIO3_IO06 0x1b0b0 +#define TX_GPIO_PAD191 MX6QDL_PAD_EIM_DA7__GPIO3_IO07 0x1b0b0 +#define TX_GPIO_PAD192 MX6QDL_PAD_EIM_DA8__GPIO3_IO08 0x1b0b0 +#define TX_GPIO_PAD193 MX6QDL_PAD_EIM_DA9__GPIO3_IO09 0x1b0b0 +#define TX_GPIO_PAD194 MX6QDL_PAD_EIM_DA10__GPIO3_IO10 0x1b0b0 +#define TX_GPIO_PAD195 MX6QDL_PAD_EIM_DA11__GPIO3_IO11 0x1b0b0 +#define TX_GPIO_PAD196 MX6QDL_PAD_EIM_DA12__GPIO3_IO12 0x1b0b0 +#define TX_GPIO_PAD197 MX6QDL_PAD_EIM_DA13__GPIO3_IO13 0x1b0b0 +#define TX_GPIO_PAD198 MX6QDL_PAD_EIM_DA14__GPIO3_IO14 0x1b0b0 +#define TX_GPIO_PAD199 MX6QDL_PAD_EIM_DA15__GPIO3_IO15 0x1b0b0 + +#endif /* __DTS_TX6QDL_GPIO_H */ diff --git a/recipes-kernel/linux/linux-karo-4.9.11/tx6/imx6qdl-tx6.dtsi b/recipes-kernel/linux/linux-karo-4.9.11/tx6/imx6qdl-tx6.dtsi new file mode 100755 index 0000000..6f61150 --- /dev/null +++ b/recipes-kernel/linux/linux-karo-4.9.11/tx6/imx6qdl-tx6.dtsi @@ -0,0 +1,647 @@ +/* + * Copyright 2016 Lothar Waßmann + * Copyright 2016-2017 Oliver Wendt + * Copyright 2016 Michael Vyskocil + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file 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 file 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. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/* + * Please be reminded that in general DTSI file(s) are include files that are + * for more than one purpose (usually bound to a SoC) and as such shouldn't be + * edited. For end-user products it should be the DTS file(s) that choose which + * devices and pins are active and setup. + * + * The setup of DT files for Ka-Ro TX COM Modules under Yocto follow a + * different, non-standard, implementation, which can make it necessary. + */ + +#include +#include +#include +#include + +/* + * Definitions for simpler referencing of TX's standard nodes + */ + +/* On-board NVMe */ +#define TX_EMMC &usdhc4 +#define TX_NAND &gpmi +/* bus connectors */ +#define TX_I2C &i2c3 +#define TX_CAN1 &can2 +#define TX_CAN2 &can1 +/* video & display */ +#define TX_LCD &lcd +#define TX_LCD_FB &mxcfb0 +#define TX_LDB &ldb +#define TX_LDB_FB1 &mxcfb1 +#define TX_LDB_FB2 &mxcfb2 +#define TX_PWM &pwm2 +#define TX_PWM1 &pwm2 /* First (1st) PWM used (TX's default) */ +#define TX_PWM2 &pwm1 /* Second (2nd) PWM used */ +/* NVM */ +#define TX_SD1 &usdhc1 +#define TX_SD2 &usdhc2 +#define TX_SPI &ecspi1 +#define TX_SSI1 &audmux +#define TX_SSI_PIN &pinctrl_ssi1 +/* UART */ +#define TX_UART1 &uart1 +#define TX_UART2 &uart2 +#define TX_UART3 &uart3 +/* USB */ +#define TX_USBH &usbh1 +#define TX_USBOTG &usbotg + +/ { + aliases { + can0 = &can2; + can1 = &can1; + emmc = &usdhc4; + ethernet0 = &fec; + sdhc0 = &usdhc1; + sdhc1 = &usdhc2; + usbh = &usbh1; + usbotg = &usbotg; + }; + + memory { + reg = <0 0>; /* will be filled by U-Boot */ + }; + + /* override imx6dl.dtsi gpu clock definition bug */ + + clocks { + #address-cells = <1>; + #size-cells = <0>; + + mclk: clock { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <26000000>; + }; + }; + + chosen { + stdout-path = TX_UART1; + }; + + regulators { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <0>; + + reg_3v3_etn: regulator-3v3etn { + compatible = "regulator-fixed"; + regulator-name = "3V3_ETN"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_etnphy_power>; + gpio = <&gpio3 20 GPIO_ACTIVE_HIGH>; + enable-active-high; + }; + + reg_usbh1_vbus: regulator-usbh1vbus { + compatible = "regulator-fixed"; + regulator-name = "usbh1_vbus"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usbh1_vbus>; + gpio = ; + enable-active-high; + }; + + reg_usbotg_vbus: regulator-usbotgvbus { + compatible = "regulator-fixed"; + regulator-name = "usbotg_vbus"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usbotg_vbus>; + gpio = ; + enable-active-high; + }; + }; + + lcd: lcd@0 { + status = "disabled"; + }; + + mxcfb0: fb@0 { + compatible = "fsl,mxc_sdc_fb"; + disp_dev = "lcd"; + interface_pix_fmt = "RGB24"; + default_bpp = <16>; + int_clk = <0>; + late_init = <0>; + status = "disabled"; + }; + + mxcfb1: fb@1 { + compatible = "fsl,mxc_sdc_fb"; + disp_dev = "ldb"; + interface_pix_fmt = "RGB666"; + default_bpp = <16>; + int_clk = <0>; + late_init = <0>; + status = "disabled"; + }; + + mxcfb2: fb@2 { + compatible = "fsl,mxc_sdc_fb"; + disp_dev = "ldb"; + interface_pix_fmt = "RGB666"; + default_bpp = <16>; + int_clk = <0>; + late_init = <0>; + status = "disabled"; + }; + + v4l2_cap_0 { + compatible = "fsl,imx6q-v4l2-capture"; + ipu_id = <0>; + csi_id = <0>; + mclk_source = <0>; + status = "disabled"; + }; + + v4l2_cap_1 { + compatible = "fsl,imx6q-v4l2-capture"; + ipu_id = <0>; + csi_id = <1>; + mclk_source = <0>; + status = "disabled"; + }; + + v4l2_out { + compatible = "fsl,mxc_v4l2_output"; + status = "disabled"; + }; +}; + +&can1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_flexcan1>; + status = "disabled"; +}; + +&can2 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_flexcan2>; + status = "disabled"; +}; + +&clks { + fsl,ldb-di0-parent = <&clks IMX6QDL_CLK_PLL2_PFD0_352M>; + fsl,ldb-di1-parent = <&clks IMX6QDL_CLK_PLL2_PFD0_352M>; +}; + +&dcic2 { + dcic_id = <1>; + dcic_mux = "dcic-lvds1"; + status = "okay"; +}; + +&ecspi1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_ecspi1>; + fsl,spi-num-chipselects = <2>; + cs-gpios = < + TX_GPIO_PIN44 GPIO_ACTIVE_HIGH + TX_GPIO_PIN45 GPIO_ACTIVE_HIGH + >; + status = "disabled"; + + spidev0: spi@0 { + compatible = "spidev"; + reg = <0>; + spi-max-frequency = <54000000>; + }; + + spidev1: spi@1 { + compatible = "spidev"; + reg = <1>; + spi-max-frequency = <54000000>; + }; +}; + +&fec { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_enet>; + clocks = <&clks IMX6QDL_CLK_ENET>, + <&clks IMX6QDL_CLK_ENET>, + <&clks IMX6QDL_CLK_ENET_REF>, + <&clks IMX6QDL_CLK_ENET_REF>; + clock-names = "ipg", "ahb", "ptp", "enet_out"; + ref-clock = <50000000>; + phy-mode = "rmii"; + phy-reset-gpios = <&gpio7 6 GPIO_ACTIVE_HIGH>; + phy-handle = <&etnphy>; + phy-supply = <®_3v3_etn>; + fsl,magic-packet; + fsl,err006687-workaround-present; + status = "okay"; + + mdio { + #address-cells = <1>; + #size-cells = <0>; + + etnphy: ethernet-phy@0 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <0>; + interrupts-extended = <&gpio7 1 IRQ_TYPE_EDGE_FALLING>; + status = "okay"; + }; + }; +}; + +&gpmi { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_gpmi_nand>; + nand-on-flash-bbt; + fsl,no-blockmark-swap; + status = "disabled"; +}; + +&i2c3 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_i2c3>; + clock-frequency = <400000>; + status = "disabled"; +}; + +&pwm1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_pwm1>; + status = "disabled"; +}; + +&pwm2 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_pwm2>; + status = "disabled"; +}; + +®_arm { + /delete-property/ regulator-allow-bypass; +}; + +®_pu { + /delete-property/ regulator-allow-bypass; +}; + +®_soc { + /delete-property/ regulator-allow-bypass; +}; + +&snvs_poweroff { + status = "okay"; +}; + +&ssi1 { + status = "okay"; +}; + +&ssi2 { + status = "okay"; +}; + +&uart1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart1 &pinctrl_uart1_rtscts>; + status = "disabled"; +}; + +&uart2 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart2 &pinctrl_uart2_rtscts>; + status = "disabled"; +}; + +&uart3 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart3 &pinctrl_uart3_rtscts>; + status = "disabled"; +}; + +&usbotg { + vbus-supply = <®_usbotg_vbus>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usbotg>; + dr_mode = "peripheral"; + disable-over-current; + status = "disabled"; +}; + +&usbh1 { + vbus-supply = <®_usbh1_vbus>; + dr_mode = "host"; + disable-over-current; + status = "disabled"; +}; + +&usdhc1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usdhc1>; + bus-width = <4>; + no-1-8-v; + cd-gpios = <&gpio7 2 GPIO_ACTIVE_LOW>; + fsl,wp-controller; + status = "disabled"; +}; + +&usdhc2 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usdhc2>; + bus-width = <4>; + no-1-8-v; + cd-gpios = <&gpio7 3 GPIO_ACTIVE_LOW>; + fsl,wp-controller; + status = "disabled"; +}; + +&usdhc4 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usdhc4>; + bus-width = <4>; + non-removable; + no-1-8-v; + fsl,wp-controller; + status = "disabled"; +}; + +&iomuxc { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_hog>; + + tx6 { + pinctrl_hog: hoggrp { + fsl,pins = < + MX6QDL_PAD_SD3_DAT2__GPIO7_IO06 0x1b0b1 /* ETN PHY RESET */ + MX6QDL_PAD_SD3_DAT4__GPIO7_IO01 0x1b0b1 /* ETN PHY INT */ + >; + }; + + pinctrl_ssi1: audmuxgrp { + fsl,pins = < + MX6QDL_PAD_KEY_ROW1__AUD5_RXD 0x130b0 /* SSI1_RXD */ + MX6QDL_PAD_KEY_ROW0__AUD5_TXD 0x110b0 /* SSI1_TXD */ + MX6QDL_PAD_KEY_COL0__AUD5_TXC 0x130b0 /* SSI1_CLK */ + MX6QDL_PAD_KEY_COL1__AUD5_TXFS 0x130b0 /* SSI1_FS */ + >; + }; + + pinctrl_ecspi1: ecspi1grp { + fsl,pins = < + MX6QDL_PAD_EIM_D18__ECSPI1_MOSI 0x0b0b0 + MX6QDL_PAD_EIM_D17__ECSPI1_MISO 0x0b0b0 + MX6QDL_PAD_EIM_D16__ECSPI1_SCLK 0x0b0b0 + MX6QDL_PAD_GPIO_19__ECSPI1_RDY 0x0b0b0 + MX6QDL_PAD_EIM_EB2__GPIO2_IO30 0x0b0b0 /* SPI CS0 */ + MX6QDL_PAD_EIM_D19__GPIO3_IO19 0x0b0b0 /* SPI CS1 */ + >; + }; + + pinctrl_enet: enetgrp { + fsl,pins = < + MX6QDL_PAD_ENET_MDC__ENET_MDC 0x1b0b0 + MX6QDL_PAD_ENET_MDIO__ENET_MDIO 0x1b0b0 + MX6QDL_PAD_ENET_RXD0__ENET_RX_DATA0 0x1b0b0 + MX6QDL_PAD_ENET_RXD1__ENET_RX_DATA1 0x1b0b0 + MX6QDL_PAD_ENET_RX_ER__ENET_RX_ER 0x1b0b0 + MX6QDL_PAD_ENET_TX_EN__ENET_TX_EN 0x1b0b0 + MX6QDL_PAD_ENET_TXD0__ENET_TX_DATA0 0x1b0b0 + MX6QDL_PAD_ENET_TXD1__ENET_TX_DATA1 0x1b0b0 + MX6QDL_PAD_ENET_CRS_DV__ENET_RX_EN 0x1b0b0 + >; + }; + + pinctrl_etnphy_power: etnphy-pwrgrp { + fsl,pins = < + MX6QDL_PAD_EIM_D20__GPIO3_IO20 0x1b0b1 /* ETN PHY POWER */ + >; + }; + + pinctrl_flexcan1: flexcan1grp { + fsl,pins = < + MX6QDL_PAD_GPIO_7__FLEXCAN1_TX 0x1b0b0 + MX6QDL_PAD_GPIO_8__FLEXCAN1_RX 0x1b0b0 + >; + }; + + pinctrl_flexcan2: flexcan2grp { + fsl,pins = < + MX6QDL_PAD_KEY_COL4__FLEXCAN2_TX 0x1b0b0 + MX6QDL_PAD_KEY_ROW4__FLEXCAN2_RX 0x1b0b0 + >; + }; + + pinctrl_gpmi_nand: gpminandgrp { + fsl,pins = < + MX6QDL_PAD_NANDF_CLE__NAND_CLE 0x0b0b1 + MX6QDL_PAD_NANDF_ALE__NAND_ALE 0x0b0b1 + MX6QDL_PAD_NANDF_WP_B__NAND_WP_B 0x0b0b1 + MX6QDL_PAD_NANDF_RB0__NAND_READY_B 0x0b000 + MX6QDL_PAD_NANDF_CS0__NAND_CE0_B 0x0b0b1 + MX6QDL_PAD_SD4_CMD__NAND_RE_B 0x0b0b1 + MX6QDL_PAD_SD4_CLK__NAND_WE_B 0x0b0b1 + MX6QDL_PAD_NANDF_D0__NAND_DATA00 0x0b0b1 + MX6QDL_PAD_NANDF_D1__NAND_DATA01 0x0b0b1 + MX6QDL_PAD_NANDF_D2__NAND_DATA02 0x0b0b1 + MX6QDL_PAD_NANDF_D3__NAND_DATA03 0x0b0b1 + MX6QDL_PAD_NANDF_D4__NAND_DATA04 0x0b0b1 + MX6QDL_PAD_NANDF_D5__NAND_DATA05 0x0b0b1 + MX6QDL_PAD_NANDF_D6__NAND_DATA06 0x0b0b1 + MX6QDL_PAD_NANDF_D7__NAND_DATA07 0x0b0b1 + >; + }; + + pinctrl_i2c3: i2c3grp { + fsl,pins = < + MX6QDL_PAD_GPIO_3__I2C3_SCL 0x4001b8b1 + MX6QDL_PAD_GPIO_6__I2C3_SDA 0x4001b8b1 + >; + }; + + pinctrl_ipu1: ipu1grp { + fsl,pins = < + MX6QDL_PAD_DI0_DISP_CLK__IPU1_DI0_DISP_CLK 0x10 + MX6QDL_PAD_DI0_PIN15__IPU1_DI0_PIN15 0x10 + MX6QDL_PAD_DI0_PIN2__IPU1_DI0_PIN02 0x10 + MX6QDL_PAD_DI0_PIN3__IPU1_DI0_PIN03 0x10 + MX6QDL_PAD_DI0_PIN4__IPU1_DI0_PIN04 0x80000000 + MX6QDL_PAD_DISP0_DAT0__IPU1_DISP0_DATA00 0x10 + MX6QDL_PAD_DISP0_DAT1__IPU1_DISP0_DATA01 0x10 + MX6QDL_PAD_DISP0_DAT2__IPU1_DISP0_DATA02 0x10 + MX6QDL_PAD_DISP0_DAT3__IPU1_DISP0_DATA03 0x10 + MX6QDL_PAD_DISP0_DAT4__IPU1_DISP0_DATA04 0x10 + MX6QDL_PAD_DISP0_DAT5__IPU1_DISP0_DATA05 0x10 + MX6QDL_PAD_DISP0_DAT6__IPU1_DISP0_DATA06 0x10 + MX6QDL_PAD_DISP0_DAT7__IPU1_DISP0_DATA07 0x10 + MX6QDL_PAD_DISP0_DAT8__IPU1_DISP0_DATA08 0x10 + MX6QDL_PAD_DISP0_DAT9__IPU1_DISP0_DATA09 0x10 + MX6QDL_PAD_DISP0_DAT10__IPU1_DISP0_DATA10 0x10 + MX6QDL_PAD_DISP0_DAT11__IPU1_DISP0_DATA11 0x10 + MX6QDL_PAD_DISP0_DAT12__IPU1_DISP0_DATA12 0x10 + MX6QDL_PAD_DISP0_DAT13__IPU1_DISP0_DATA13 0x10 + MX6QDL_PAD_DISP0_DAT14__IPU1_DISP0_DATA14 0x10 + MX6QDL_PAD_DISP0_DAT15__IPU1_DISP0_DATA15 0x10 + MX6QDL_PAD_DISP0_DAT16__IPU1_DISP0_DATA16 0x10 + MX6QDL_PAD_DISP0_DAT17__IPU1_DISP0_DATA17 0x10 + MX6QDL_PAD_DISP0_DAT18__IPU1_DISP0_DATA18 0x10 + MX6QDL_PAD_DISP0_DAT19__IPU1_DISP0_DATA19 0x10 + MX6QDL_PAD_DISP0_DAT20__IPU1_DISP0_DATA20 0x10 + MX6QDL_PAD_DISP0_DAT21__IPU1_DISP0_DATA21 0x10 + MX6QDL_PAD_DISP0_DAT22__IPU1_DISP0_DATA22 0x10 + MX6QDL_PAD_DISP0_DAT23__IPU1_DISP0_DATA23 0x10 + >; + }; + + pinctrl_pwm1: pwm1grp { + fsl,pins = < + MX6QDL_PAD_GPIO_9__PWM1_OUT 0x1b0b1 + >; + }; + + pinctrl_pwm2: pwm2grp { + fsl,pins = < + MX6QDL_PAD_GPIO_1__PWM2_OUT 0x1b0b1 + >; + }; + + pinctrl_uart1: uart1grp { + fsl,pins = < + MX6QDL_PAD_SD3_DAT7__UART1_TX_DATA 0x1b0b1 + MX6QDL_PAD_SD3_DAT6__UART1_RX_DATA 0x1b0b1 + >; + }; + + pinctrl_uart1_rtscts: uart1_rtsctsgrp { + fsl,pins = < + MX6QDL_PAD_SD3_DAT1__UART1_RTS_B 0x1b0b1 + MX6QDL_PAD_SD3_DAT0__UART1_CTS_B 0x1b0b1 + >; + }; + + pinctrl_uart2: uart2grp { + fsl,pins = < + MX6QDL_PAD_SD4_DAT7__UART2_TX_DATA 0x1b0b1 + MX6QDL_PAD_SD4_DAT4__UART2_RX_DATA 0x1b0b1 + >; + }; + + pinctrl_uart2_rtscts: uart2_rtsctsgrp { + fsl,pins = < + MX6QDL_PAD_SD4_DAT5__UART2_RTS_B 0x1b0b1 + MX6QDL_PAD_SD4_DAT6__UART2_CTS_B 0x1b0b1 + >; + }; + + pinctrl_uart3: uart3grp { + fsl,pins = < + MX6QDL_PAD_EIM_D24__UART3_TX_DATA 0x1b0b1 + MX6QDL_PAD_EIM_D25__UART3_RX_DATA 0x1b0b1 + >; + }; + + pinctrl_uart3_rtscts: uart3_rtsctsgrp { + fsl,pins = < + MX6QDL_PAD_SD3_DAT3__UART3_CTS_B 0x1b0b1 + MX6QDL_PAD_SD3_RST__UART3_RTS_B 0x1b0b1 + >; + }; + + pinctrl_usbh1_vbus: usbh1-vbusgrp { + fsl,pins = < + MX6QDL_PAD_EIM_D31__GPIO3_IO31 0x1b0b0 /* USBH1_VBUSEN */ + >; + }; + + pinctrl_usbotg: usbotggrp { + fsl,pins = < + MX6QDL_PAD_EIM_D23__GPIO3_IO23 0x17059 + >; + }; + + pinctrl_usbotg_vbus: usbotg-vbusgrp { + fsl,pins = < + MX6QDL_PAD_GPIO_7__GPIO1_IO07 0x1b0b0 /* USBOTG_VBUSEN */ + >; + }; + + pinctrl_usdhc1: usdhc1grp { + fsl,pins = < + MX6QDL_PAD_SD1_CMD__SD1_CMD 0x070b1 + MX6QDL_PAD_SD1_CLK__SD1_CLK 0x070b1 + MX6QDL_PAD_SD1_DAT0__SD1_DATA0 0x070b1 + MX6QDL_PAD_SD1_DAT1__SD1_DATA1 0x070b1 + MX6QDL_PAD_SD1_DAT2__SD1_DATA2 0x070b1 + MX6QDL_PAD_SD1_DAT3__SD1_DATA3 0x070b1 + MX6QDL_PAD_SD3_CMD__GPIO7_IO02 0x170b0 /* SD1 CD */ + >; + }; + + pinctrl_usdhc2: usdhc2grp { + fsl,pins = < + MX6QDL_PAD_SD2_CMD__SD2_CMD 0x070b1 + MX6QDL_PAD_SD2_CLK__SD2_CLK 0x070b1 + MX6QDL_PAD_SD2_DAT0__SD2_DATA0 0x070b1 + MX6QDL_PAD_SD2_DAT1__SD2_DATA1 0x070b1 + MX6QDL_PAD_SD2_DAT2__SD2_DATA2 0x070b1 + MX6QDL_PAD_SD2_DAT3__SD2_DATA3 0x070b1 + MX6QDL_PAD_SD3_CLK__GPIO7_IO03 0x170b0 /* SD2 CD */ + >; + }; + + pinctrl_usdhc4: usdhc4grp { + fsl,pins = < + MX6QDL_PAD_SD4_CMD__SD4_CMD 0x070b1 + MX6QDL_PAD_SD4_CLK__SD4_CLK 0x070b1 + MX6QDL_PAD_SD4_DAT0__SD4_DATA0 0x070b1 + MX6QDL_PAD_SD4_DAT1__SD4_DATA1 0x070b1 + MX6QDL_PAD_SD4_DAT2__SD4_DATA2 0x070b1 + MX6QDL_PAD_SD4_DAT3__SD4_DATA3 0x070b1 + MX6QDL_PAD_NANDF_ALE__SD4_RESET 0x0b0b1 + >; + }; + }; +}; diff --git a/recipes-kernel/linux/linux-karo-4.9.11/txbase/aclavis-lvds/imx6dl-tx6-emmc-aclavis-lvds.dts b/recipes-kernel/linux/linux-karo-4.9.11/txbase/aclavis-lvds/imx6dl-tx6-emmc-aclavis-lvds.dts new file mode 100755 index 0000000..23e60e9 --- /dev/null +++ b/recipes-kernel/linux/linux-karo-4.9.11/txbase/aclavis-lvds/imx6dl-tx6-emmc-aclavis-lvds.dts @@ -0,0 +1,128 @@ +/* + * Copyright 2016 Lothar Waßmann + * Copyright 2016-2017 Oliver Wendt + * Copyright 2016 Michael Vyskocil + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file 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 file 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. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/* + * Please be reminded that - in general - DTSI file(s) are include files that + * are for more than one purpose (usually bound to a SoC) and as such shouldn't + * be edited. For end-user products it should be the DTS file(s) that choose + * which devices and pins are active and setup. + * + * The setup of DT files for Ka-Ro TX COM Modules under Yocto follow a + * different, non-standard, implementation to the mainline Linux kernel. + */ + +/* + * Please see the imx6*-tx6-gpio.h && imx6*-tx6.dtsi in "linux-karo-x.y.ab/tx6" + * for the definitions like TX_NAND or TX_EMMC, etc. + */ + +/dts-v1/; + +#include "imx6dl.dtsi" +#include "imx6qdl-tx6.dtsi" +#include "txbase-aclavis-lvds.dtsi" + +/ { + model = "Ka-Ro electronics TX6U Module"; + compatible = "karo,imx6dl-tx6dl", "fsl,imx6dl"; +}; + +/* + * Every VOU is multi parted: backlight, device, framebuffer, pwm + * Thus all parts have to be enabled before a display can be used on the + * specific port. + */ + +&backlight0 { + status = "okay"; +}; + +/* + * NVM setup + */ + +TX_EMMC { + status = "okay"; +}; + +/* + * Remaining device references in alphabetical order + */ + +TX_LDB { + status = "okay"; + + lvds0: lvds-channel@0 { + status = "okay"; + /* + * Users should add their custom timing here, therewith + * overwriting the default/pre-defined timings. For more see: + * + * txbase/{BASEBOARD}-{DISPLAY-IF}/txbase-{BASEBOARD}-{DISPLAY-IF}.dtsi + * + * e.g.: + * txbase/mb7-lvds/txbase-aclavis.dtsi + */ + }; + + lvds1: lvds-channel@1 { + status = "disabled"; + /* + * Users should add their custom timing here, therewith + * overwriting the default/pre-defined timings. For more see: + * + * txbase/{BASEBOARD}-{DISPLAY-IF}/txbase-{BASEBOARD}-{DISPLAY-IF}.dtsi + * + * e.g.: + * txbase/mb7-lvds/txbase-aclavis.dtsi + */ + }; +}; + +TX_LDB_FB1 { + status = "okay"; +}; + +TX_LDB_FB2 { + status = "disabled"; +}; diff --git a/recipes-kernel/linux/linux-karo-4.9.11/txbase/aclavis-lvds/imx6dl-tx6-nand-aclavis-lvds.dts b/recipes-kernel/linux/linux-karo-4.9.11/txbase/aclavis-lvds/imx6dl-tx6-nand-aclavis-lvds.dts new file mode 100755 index 0000000..da02e27 --- /dev/null +++ b/recipes-kernel/linux/linux-karo-4.9.11/txbase/aclavis-lvds/imx6dl-tx6-nand-aclavis-lvds.dts @@ -0,0 +1,128 @@ +/* + * Copyright 2016 Lothar Waßmann + * Copyright 2016-2017 Oliver Wendt + * Copyright 2016 Michael Vyskocil + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file 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 file 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. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/* + * Please be reminded that - in general - DTSI file(s) are include files that + * are for more than one purpose (usually bound to a SoC) and as such shouldn't + * be edited. For end-user products it should be the DTS file(s) that choose + * which devices and pins are active and setup. + * + * The setup of DT files for Ka-Ro TX COM Modules under Yocto follow a + * different, non-standard, implementation to the mainline Linux kernel. + */ + +/* + * Please see the imx6*-tx6-gpio.h && imx6*-tx6.dtsi in "linux-karo-x.y.ab/tx6" + * for the definitions like TX_NAND or TX_EMMC, etc. + */ + +/dts-v1/; + +#include "imx6dl.dtsi" +#include "imx6qdl-tx6.dtsi" +#include "txbase-aclavis-lvds.dtsi" + +/ { + model = "Ka-Ro electronics TX6U Module"; + compatible = "karo,imx6dl-tx6dl", "fsl,imx6dl"; +}; + +/* + * Every VOU is multi parted: backlight, device, framebuffer, pwm + * Thus all parts have to be enabled before a display can be used on the + * specific port. + */ + +&backlight0 { + status = "okay"; +}; + +/* + * NVM setup + */ + +TX_NAND { + status = "okay"; +}; + +/* + * Remaining device references in alphabetical order + */ + +TX_LDB { + status = "okay"; + + lvds0: lvds-channel@0 { + status = "okay"; + /* + * Users should add their custom (U-Boot) timing here, + * overwriting the default/pre-defined timings. For more see: + * + * txbase/{BASEBOARD}-{DISPLAY-IF}/txbase-{BASEBOARD}-{DISPLAY-IF}.dtsi + * + * e.g.: + * txbase/mb7-lvds/txbase-aclavis.dtsi + */ + }; + + lvds1: lvds-channel@1 { + status = "disabled"; + /* + * Users should add their custom (U-Boot) timing here, + * overwriting the default/pre-defined timings. For more see: + * + * txbase/{BASEBOARD}-{DISPLAY-IF}/txbase-{BASEBOARD}-{DISPLAY-IF}.dtsi + * + * e.g.: + * txbase/mb7-lvds/txbase-aclavis.dtsi + */ + }; +}; + +TX_LDB_FB1 { + status = "okay"; +}; + +TX_LDB_FB2 { + status = "disabled"; +}; diff --git a/recipes-kernel/linux/linux-karo-4.9.11/txbase/aclavis-lvds/imx6q-tx6-emmc-aclavis-lvds.dts b/recipes-kernel/linux/linux-karo-4.9.11/txbase/aclavis-lvds/imx6q-tx6-emmc-aclavis-lvds.dts new file mode 100755 index 0000000..19332de --- /dev/null +++ b/recipes-kernel/linux/linux-karo-4.9.11/txbase/aclavis-lvds/imx6q-tx6-emmc-aclavis-lvds.dts @@ -0,0 +1,128 @@ +/* + * Copyright 2016 Lothar Waßmann + * Copyright 2016-2017 Oliver Wendt + * Copyright 2016 Michael Vyskocil + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file 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 file 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. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/* + * Please be reminded that - in general - DTSI file(s) are include files that + * are for more than one purpose (usually bound to a SoC) and as such shouldn't + * be edited. For end-user products it should be the DTS file(s) that choose + * which devices and pins are active and setup. + * + * The setup of DT files for Ka-Ro TX COM Modules under Yocto follow a + * different, non-standard, implementation to the mainline Linux kernel. + */ + +/* + * Please see the imx6*-tx6-gpio.h && imx6*-tx6.dtsi in "linux-karo-x.y.ab/tx6" + * for the definitions like TX_NAND or TX_EMMC, etc. + */ + +/dts-v1/; + +#include "imx6q.dtsi" +#include "imx6qdl-tx6.dtsi" +#include "txbase-aclavis-lvds.dtsi" + +/ { + model = "Ka-Ro electronics TX6Q Module (eMMC & LVDS)"; + compatible = "karo,imx6q-tx6q", "fsl,imx6q"; +}; + +/* + * Every VOU is multi parted: backlight, device, framebuffer, pwm + * Thus all parts have to be enabled before a display can be used on the + * specific port. + */ + +&backlight0 { + status = "okay"; +}; + +/* + * NVM setup + */ + +TX_EMMC { + status = "okay"; +}; + +/* + * Remaining device references in alphabetical order + */ + +TX_LDB { + status = "okay"; + + lvds0: lvds-channel@0 { + status = "okay"; + /* + * Users should add their custom timing here, therewith + * overwriting the default/pre-defined timings. For more see: + * + * txbase/{BASEBOARD}-{DISPLAY-IF}/txbase-{BASEBOARD}-{DISPLAY-IF}.dtsi + * + * e.g.: + * txbase/mb7-lvds/txbase-aclavis.dtsi + */ + }; + + lvds1: lvds-channel@1 { + status = "disabled"; + /* + * Users should add their custom timing here, therewith + * overwriting the default/pre-defined timings. For more see: + * + * txbase/{BASEBOARD}-{DISPLAY-IF}/txbase-{BASEBOARD}-{DISPLAY-IF}.dtsi + * + * e.g.: + * txbase/mb7-lvds/txbase-aclavis.dtsi + */ + }; +}; + +TX_LDB_FB1 { + status = "okay"; +}; + +TX_LDB_FB2 { + status = "disabled"; +}; diff --git a/recipes-kernel/linux/linux-karo-4.9.11/txbase/aclavis-lvds/imx6q-tx6-nand-aclavis-lvds.dts b/recipes-kernel/linux/linux-karo-4.9.11/txbase/aclavis-lvds/imx6q-tx6-nand-aclavis-lvds.dts new file mode 100755 index 0000000..34858ae --- /dev/null +++ b/recipes-kernel/linux/linux-karo-4.9.11/txbase/aclavis-lvds/imx6q-tx6-nand-aclavis-lvds.dts @@ -0,0 +1,128 @@ +/* + * Copyright 2016 Lothar Waßmann + * Copyright 2016-2017 Oliver Wendt + * Copyright 2016 Michael Vyskocil + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file 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 file 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. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/* + * Please be reminded that in general DTSI file(s) are include files that are + * for more than one purpose (usually bound to a SoC) and as such shouldn't be + * edited. For end-user products it should be the DTS file(s) that choose which + * devices and pins are active and setup. + * + * The setup of DT files for Ka-Ro TX COM Modules under Yocto follow a + * different, non-standard, implementation to the mainline Linux kernel. + */ + +/* + * Please see the imx6*-tx6-gpio.h && imx6*-tx6.dtsi in "linux-karo-x.y.ab/tx6" + * for the definitions like TX_NAND or TX_EMMC, etc. + */ + +/dts-v1/; + +#include "imx6q.dtsi" +#include "imx6qdl-tx6.dtsi" +#include "txbase-aclavis-lvds.dtsi" + +/ { + model = "Ka-Ro electronics TX6Q Module (NAND & LVDS)"; + compatible = "karo,imx6q-tx6q", "fsl,imx6q"; +}; + +/* + * Every VOU is multi parted: backlight, device, framebuffer, pwm + * Thus all parts have to be enabled before a display can be used on the + * specific port. + */ + +&backlight0 { + status = "okay"; +}; + +/* + * NVM setup + */ + +TX_NAND { + status = "okay"; +}; + +/* + * Remaining device references in alphabetical order + */ + +TX_LDB { + status = "okay"; + + lvds0: lvds-channel@0 { + status = "okay"; + /* + * Users should add their custom (U-Boot) timing here, + * overwriting the default/pre-defined timings. For more see: + * + * txbase/{BASEBOARD}-{DISPLAY-IF}/txbase-{BASEBOARD}-{DISPLAY-IF}.dtsi + * + * e.g.: + * txbase/mb7-lvds/txbase-aclavis.dtsi + */ + }; + + lvds1: lvds-channel@1 { + status = "disabled"; + /* + * Users should add their custom (U-Boot) timing here, + * overwriting the default/pre-defined timings. For more see: + * + * txbase/{BASEBOARD}-{DISPLAY-IF}/txbase-{BASEBOARD}-{DISPLAY-IF}.dtsi + * + * e.g.: + * txbase/mb7-lvds/txbase-aclavis.dtsi + */ + }; +}; + +TX_LDB_FB1 { + status = "okay"; +}; + +TX_LDB_FB2 { + status = "disabled"; +}; diff --git a/recipes-kernel/linux/linux-karo-4.9.11/txbase/aclavis-lvds/imx6qp-tx6-emmc-aclavis-lvds.dts b/recipes-kernel/linux/linux-karo-4.9.11/txbase/aclavis-lvds/imx6qp-tx6-emmc-aclavis-lvds.dts new file mode 100755 index 0000000..1f02434 --- /dev/null +++ b/recipes-kernel/linux/linux-karo-4.9.11/txbase/aclavis-lvds/imx6qp-tx6-emmc-aclavis-lvds.dts @@ -0,0 +1,129 @@ +/* + * Copyright 2016 Lothar Waßmann + * Copyright 2016-2017 Oliver Wendt + * Copyright 2016 Michael Vyskocil + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file 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 file 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. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/* + * Please be reminded that - in general - DTSI file(s) are include files that + * are for more than one purpose (usually bound to a SoC) and as such shouldn't + * be edited. For end-user products it should be the DTS file(s) that choose + * which devices and pins are active and setup. + * + * The setup of DT files for Ka-Ro TX COM Modules under Yocto follow a + * different, non-standard, implementation to the mainline Linux kernel. + */ + +/* + * Please see the imx6*-tx6-gpio.h && imx6*-tx6.dtsi in "linux-karo-x.y.ab/tx6" + * for the definitions like TX_NAND or TX_EMMC, etc. + */ + +/dts-v1/; + +#include "imx6q.dtsi" +#include "imx6qp.dtsi" +#include "imx6qdl-tx6.dtsi" +#include "txbase-aclavis-lvds.dtsi" + +/ { + model = "Ka-Ro electronics TX6Q Module (eMMC & LVDS)"; + compatible = "karo,imx6q-tx6q", "fsl,imx6q"; +}; + +/* + * Every VOU is multi parted: backlight, device, framebuffer, pwm + * Thus all parts have to be enabled before a display can be used on the + * specific port. + */ + +&backlight0 { + status = "okay"; +}; + +/* + * NVM setup + */ + +TX_EMMC { + status = "okay"; +}; + +/* + * Remaining device references in alphabetical order + */ + +TX_LDB { + status = "okay"; + + lvds0: lvds-channel@0 { + status = "okay"; + /* + * Users should add their custom timing here, therewith + * overwriting the default/pre-defined timings. For more see: + * + * txbase/{BASEBOARD}-{DISPLAY-IF}/txbase-{BASEBOARD}-{DISPLAY-IF}.dtsi + * + * e.g.: + * txbase/mb7-lvds/txbase-aclavis.dtsi + */ + }; + + lvds1: lvds-channel@1 { + status = "disabled"; + /* + * Users should add their custom timing here, therewith + * overwriting the default/pre-defined timings. For more see: + * + * txbase/{BASEBOARD}-{DISPLAY-IF}/txbase-{BASEBOARD}-{DISPLAY-IF}.dtsi + * + * e.g.: + * txbase/mb7-lvds/txbase-aclavis.dtsi + */ + }; +}; + +TX_LDB_FB1 { + status = "okay"; +}; + +TX_LDB_FB2 { + status = "disabled"; +}; diff --git a/recipes-kernel/linux/linux-karo-4.9.11/txbase/aclavis-lvds/imx6s-tx6-emmc-aclavis-lvds.dts b/recipes-kernel/linux/linux-karo-4.9.11/txbase/aclavis-lvds/imx6s-tx6-emmc-aclavis-lvds.dts new file mode 100755 index 0000000..e6e3436 --- /dev/null +++ b/recipes-kernel/linux/linux-karo-4.9.11/txbase/aclavis-lvds/imx6s-tx6-emmc-aclavis-lvds.dts @@ -0,0 +1,132 @@ +/* + * Copyright 2016 Lothar Waßmann + * Copyright 2016 Oliver Wendt + * Copyright 2016 Michael Vyskocil + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file 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 file 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. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/* + * Please be reminded that - in general - DTSI file(s) are include files that + * are for more than one purpose (usually bound to a SoC) and as such shouldn't + * be edited. For end-user products it should be the DTS file(s) that choose + * which devices and pins are active and setup. + * + * The setup of DT files for Ka-Ro TX COM Modules under Yocto follow a + * different, non-standard, implementation to the mainline Linux kernel. + */ + +/* + * Please see the imx6*-tx6-gpio.h && imx6*-tx6.dtsi in "linux-karo-x.y.ab/tx6" + * for the definitions like TX_NAND or TX_EMMC, etc. + */ + +/dts-v1/; + +#include "imx6dl.dtsi" +#include "imx6qdl-tx6.dtsi" +#include "txbase-aclavis-lvds.dtsi" + +/ { + model = "Ka-Ro electronics TX6S Module (eMMC & LVDS)"; + compatible = "karo,imx6dl-tx6dl", "fsl,imx6dl"; + + cpus { + /delete-node/ cpu@1; + }; +}; + +/* + * Every VOU is multi parted: backlight, device, framebuffer, pwm + * Thus all parts have to be enabled before a display can be used on the + * specific port. + */ + +&backlight0 { + status = "okay"; +}; + +/* + * NVM setup + */ + +TX_EMMC { + status = "okay"; +}; + +/* + * Remaining device references in alphabetical order + */ + +TX_LDB { + status = "okay"; + + lvds0: lvds-channel@0 { + status = "okay"; + /* + * Users should add their custom timing here, therewith + * overwriting the default/pre-defined timings. For more see: + * + * txbase/{BASEBOARD}-{DISPLAY-IF}/txbase-{BASEBOARD}-{DISPLAY-IF}.dtsi + * + * e.g.: + * txbase/mb7-lvds/txbase-aclavis.dtsi + */ + }; + + lvds1: lvds-channel@1 { + status = "disabled"; + /* + * Users should add their custom (U-Boot) timing here, + * overwriting the default/pre-defined timings. For more see: + * + * txbase/{BASEBOARD}-{DISPLAY-IF}/txbase-{BASEBOARD}-{DISPLAY-IF}.dtsi + * + * e.g.: + * txbase/mb7-lvds/txbase-aclavis.dtsi + */ + }; +}; + +TX_LDB_FB1 { + status = "okay"; +}; + +TX_LDB_FB2 { + status = "disabled"; +}; diff --git a/recipes-kernel/linux/linux-karo-4.9.11/txbase/aclavis-lvds/imx6s-tx6-nand-aclavis-lvds.dts b/recipes-kernel/linux/linux-karo-4.9.11/txbase/aclavis-lvds/imx6s-tx6-nand-aclavis-lvds.dts new file mode 100755 index 0000000..a5f890b --- /dev/null +++ b/recipes-kernel/linux/linux-karo-4.9.11/txbase/aclavis-lvds/imx6s-tx6-nand-aclavis-lvds.dts @@ -0,0 +1,132 @@ +/* + * Copyright 2016 Lothar Waßmann + * Copyright 2016 Oliver Wendt + * Copyright 2016 Michael Vyskocil + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file 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 file 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. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/* + * Please be reminded that in general DTSI file(s) are include files that are + * for more than one purpose (usually bound to a SoC) and as such shouldn't be + * edited. For end-user products it should be the DTS file(s) that choose which + * devices and pins are active and setup. + * + * The setup of DT files for Ka-Ro TX COM Modules under Yocto follow a + * different, non-standard, implementation to the mainline Linux kernel. + */ + +/* + * Please see the imx6*-tx6-gpio.h && imx6*-tx6.dtsi in "linux-karo-x.y.ab/tx6" + * for the definitions like TX_NAND or TX_EMMC, etc. + */ + +/dts-v1/; + +#include "imx6dl.dtsi" +#include "imx6qdl-tx6.dtsi" +#include "txbase-aclavis-lvds.dtsi" + +/ { + model = "Ka-Ro electronics TX6S Module (NAND & LVDS)"; + compatible = "karo,imx6dl-tx6dl", "fsl,imx6dl"; + + cpus { + /delete-node/ cpu@1; + }; +}; + +/* + * Every VOU is multi parted: backlight, device, framebuffer, pwm + * Thus all parts have to be enabled before a display can be used on the + * specific port. + */ + +&backlight0 { + status = "okay"; +}; + +/* + * NVM setup + */ + +TX_NAND { + status = "okay"; +}; + +/* + * Remaining device references in alphabetical order + */ + +TX_LDB { + status = "okay"; + + lvds0: lvds-channel@0 { + status = "okay"; + /* + * Users should add their custom (U-Boot) timing here, + * overwriting the default/pre-defined timings. For more see: + * + * txbase/{BASEBOARD}-{DISPLAY-IF}/txbase-{BASEBOARD}-{DISPLAY-IF}.dtsi + * + * e.g.: + * txbase/mb7-lvds/txbase-aclavis.dtsi + */ + }; + + lvds1: lvds-channel@1 { + status = "disabled"; + /* + * Users should add their custom (U-Boot) timing here, + * overwriting the default/pre-defined timings. For more see: + * + * txbase/{BASEBOARD}-{DISPLAY-IF}/txbase-{BASEBOARD}-{DISPLAY-IF}.dtsi + * + * e.g.: + * txbase/mb7-lvds/txbase-aclavis.dtsi + */ + }; +}; + +TX_LDB_FB1 { + status = "okay"; +}; + +TX_LDB_FB2 { + status = "disabled"; +}; diff --git a/recipes-kernel/linux/linux-karo-4.9.11/txbase/aclavis-lvds/txbase-aclavis-lvds.dtsi b/recipes-kernel/linux/linux-karo-4.9.11/txbase/aclavis-lvds/txbase-aclavis-lvds.dtsi new file mode 100755 index 0000000..52abdcd --- /dev/null +++ b/recipes-kernel/linux/linux-karo-4.9.11/txbase/aclavis-lvds/txbase-aclavis-lvds.dtsi @@ -0,0 +1,247 @@ +/* + * Copyright 2016 Lothar Waßmann + * Copyright 2016-2017 Oliver Wendt + * Copyright 2016 Michael Vyskocil + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file 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 file 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. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/ { + aliases { + backlight = &backlight0; + backlight0 = &backlight0; + /* + * The node/alias 'display' is needed for U-Boot to be able to + * show a logo/splash image at boot time. It needs to include + * 'display-timings' as direct sub-node. + */ + display = &lvds0; + lvds0 = &lvds0; + lvds1 = &lvds1; + mxcfb0 = TX_LDB_FB1; + mxcfb1 = TX_LDB_FB2; + }; + + backlight0: backlight0 { + compatible = "pwm-backlight"; + pwms = ; + power-supply = <®_lcd0_pwr>; + enable-gpios = ; + /* + * a poor man's way to create a 1:1 relationship between + * the PWM value and the actual duty cycle + */ + brightness-levels = < 0 1 2 3 4 5 6 7 8 9 + 10 11 12 13 14 15 16 17 18 19 + 20 21 22 23 24 25 26 27 28 29 + 30 31 32 33 34 35 36 37 38 39 + 40 41 42 43 44 45 46 47 48 49 + 50 51 52 53 54 55 56 57 58 59 + 60 61 62 63 64 65 66 67 68 69 + 70 71 72 73 74 75 76 77 78 79 + 80 81 82 83 84 85 86 87 88 89 + 90 91 92 93 94 95 96 97 98 99 + 100>; + default-brightness-level = <50>; + status = "disabled"; + }; + + leds { + compatible = "gpio-leds"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_gpio_leds>; + + user_led: user { + label = "Heartbeat"; + gpios = ; + linux,default-trigger = "heartbeat"; + }; + }; + + regulators { + reg_lcd0_pwr: regulator-lcd0-power { + compatible = "regulator-fixed"; + regulator-name = "LCD0 RESET"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_lcd0_pwr>; + gpio = ; + enable-active-high; + regulator-boot-on; + regulator-always-on; + }; + }; +}; + +TX_CAN1 { + status = "okay"; +}; + +TX_I2C { + status = "okay"; + + ds1339: rtc@68 { + compatible = "dallas,ds1339"; + reg = <0x68>; + }; +}; + +TX_LDB { +/* + * The node/alias 'display' is needed for U-Boot to be able to show a + * logo/splash image at boot time. It needs to include 'display-timings' + * as direct sub-node. + * + * Other naming is only needed for the NXP/Freescale non-mainline + * compliant/proprietary display driver in their Yocto 4.1 Kernel + * implementation. + */ + lvds0: lvds-channel@0 { + crtc = "ipu1-di0"; + fsl,data-mapping = "spwg"; + fsl,data-width = <24>; + primary; + status = "disabled"; + + display-timings { + /* + * The naitive mode has to be named seperately between + * lvds0 & lvds1, otherwise it will be overwritten. + */ + native-mode = <&timing0>; + timing0: ETML101001DKA { + clock-frequency = <0x043b5fc0>; + hactive = <0x00000500>; + vactive = <0x00000320>; + hback-porch = <0x00000032>; + hsync-len = <0x0000003c>; + hfront-porch = <0x00000032>; + vback-porch = <0x00000005>; + vsync-len = <0x0000000d>; + vfront-porch = <0x00000005>; + }; + }; + }; + + lvds1: lvds-channel@1 { + crtc = "ipu1-di1"; + fsl,data-mapping = "spwg"; + fsl,data-width = <18>; + status = "disabled"; + + display-timings { + /* + * The naitive mode has to be named seperately between + * lvds0 & lvds1, otherwise it will be overwritten. + */ + native-mode = <&timing1>; + timing1: ETML101001DKA { + clock-frequency = <0x043b5fc0>; + hactive = <0x00000500>; + vactive = <0x00000320>; + hback-porch = <0x00000032>; + hsync-len = <0x0000003c>; + hfront-porch = <0x00000032>; + vback-porch = <0x00000005>; + vsync-len = <0x0000000d>; + vfront-porch = <0x00000005>; + }; + }; + }; +}; + +TX_LDB_FB1 { + status = "okay"; +}; + +TX_LDB_FB2 { + status = "okay"; +}; + +TX_PWM { + status = "okay"; +}; + +TX_SD1 { + status = "okay"; +}; + +TX_UART1 { + status = "okay"; +}; + +TX_UART2 { + status = "okay"; + fsl,uart-has-rtscts; + uart-has-rtscts; +}; + +TX_USBH { + status = "okay"; +}; + +TX_USBOTG { + status = "okay"; +}; + +&iomuxc { + tx6 { + pinctrl_hog: hoggrp { + fsl,pins = < + TX_GPIO_PAD148 /* OPTO IN */ + TX_GPIO_PAD149 /* OPTO IN */ + TX_GPIO_PAD151 /* OPTO OUT */ + TX_GPIO_PAD152 /* OPTO OUT */ + TX_GPIO_PAD154 /* Backlight enable */ + >; + }; + + pinctrl_gpio_leds: gpioledsgrp { + fsl,pins = < + TX_GPIO_PAD153 /* LED Heartbeat */ + >; + }; + + pinctrl_lcd0_pwr: lcd0-pwrgrp { + fsl,pins = < + TX_GPIO_PAD150 /* LCD Reset */ + >; + }; + }; +}; diff --git a/recipes-kernel/linux/linux-karo-4.9.11/txbase/aclavis/imx6dl-tx6-emmc-aclavis.dts b/recipes-kernel/linux/linux-karo-4.9.11/txbase/aclavis/imx6dl-tx6-emmc-aclavis.dts new file mode 100755 index 0000000..d26a69a --- /dev/null +++ b/recipes-kernel/linux/linux-karo-4.9.11/txbase/aclavis/imx6dl-tx6-emmc-aclavis.dts @@ -0,0 +1,107 @@ +/* + * Copyright 2016 Lothar Waßmann + * Copyright 2016 Oliver Wendt + * Copyright 2016 Michael Vyskocil + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file 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 file 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. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/* + * Please be reminded that - in general - DTSI file(s) are include files that + * are for more than one purpose (usually bound to a SoC) and as such shouldn't + * be edited. For end-user products it should be the DTS file(s) that choose + * which devices and pins are active and setup. + * + * The setup of DT files for Ka-Ro TX COM Modules under Yocto follow a + * different, non-standard, implementation to the mainline Linux kernel. + */ + +/* + * Please see the imx6*-tx6-gpio.h && imx6*-tx6.dtsi in "linux-karo-x.y.ab/tx6" + * for the definitions like TX_NAND or TX_EMMC, etc. + */ + +/dts-v1/; + +#include "imx6dl.dtsi" +#include "imx6qdl-tx6.dtsi" +#include "txbase-aclavis.dtsi" + +/ { + model = "Ka-Ro electronics TX6U Module (eMMC & RGB)"; + compatible = "karo,imx6dl-tx6dl", "fsl,imx6dl"; +}; + +/* + * Every VOU is multi parted: backlight, device, framebuffer, pwm + * Thus all parts have to be enabled before a display can be used on the + * specific port. + */ + +&backlight0 { + status = "okay"; +}; + +/* + * NVM setup + */ + +TX_EMMC { + status = "okay"; +}; + +/* + * Remaining device references in alphabetical order + */ + +TX_LCD { + status = "okay"; + /* + * Users should add their custom timing here, therewith + * overwriting the default/pre-defined timings. For more see: + * + * txbase/{BASEBOARD}-{DISPLAY-IF}/txbase-{BASEBOARD}-{DISPLAY-IF}.dtsi + * + * e.g.: + * txbase/mb7-lvds/txbase-aclavis.dtsi + */ +}; + +TX_LCD_FB { + status = "okay"; +}; diff --git a/recipes-kernel/linux/linux-karo-4.9.11/txbase/aclavis/imx6dl-tx6-nand-aclavis.dts b/recipes-kernel/linux/linux-karo-4.9.11/txbase/aclavis/imx6dl-tx6-nand-aclavis.dts new file mode 100755 index 0000000..14cab69 --- /dev/null +++ b/recipes-kernel/linux/linux-karo-4.9.11/txbase/aclavis/imx6dl-tx6-nand-aclavis.dts @@ -0,0 +1,107 @@ +/* + * Copyright 2016 Lothar Waßmann + * Copyright 2016 Oliver Wendt + * Copyright 2016 Michael Vyskocil + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file 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 file 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. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/* + * Please be reminded that - in general - DTSI file(s) are include files that + * are for more than one purpose (usually bound to a SoC) and as such shouldn't + * be edited. For end-user products it should be the DTS file(s) that choose + * which devices and pins are active and setup. + * + * The setup of DT files for Ka-Ro TX COM Modules under Yocto follow a + * different, non-standard, implementation to the mainline Linux kernel. + */ + +/* + * Please see the imx6*-tx6-gpio.h && imx6*-tx6.dtsi in "linux-karo-x.y.ab/tx6" + * for the definitions like TX_NAND or TX_EMMC, etc. + */ + +/dts-v1/; + +#include "imx6dl.dtsi" +#include "imx6qdl-tx6.dtsi" +#include "txbase-aclavis.dtsi" + +/ { + model = "Ka-Ro electronics TX6U Module (NAND & RGB)"; + compatible = "karo,imx6dl-tx6dl", "fsl,imx6dl"; +}; + +/* + * Every VOU is multi parted: backlight, device, framebuffer, pwm + * Thus all parts have to be enabled before a display can be used on the + * specific port. + */ + +&backlight0 { + status = "okay"; +}; + +/* + * NVM setup + */ + +TX_NAND { + status = "okay"; +}; + +/* + * Remaining device references in alphabetical order + */ + +TX_LCD { + status = "okay"; + /* + * Users should add their custom timing here, therewith + * overwriting the default/pre-defined timings. For more see: + * + * txbase/{BASEBOARD}-{DISPLAY-IF}/txbase-{BASEBOARD}-{DISPLAY-IF}.dtsi + * + * e.g.: + * txbase/mb7-lvds/txbase-aclavis.dtsi + */ +}; + +TX_LCD_FB { + status = "okay"; +}; diff --git a/recipes-kernel/linux/linux-karo-4.9.11/txbase/aclavis/imx6q-tx6-emmc-aclavis.dts b/recipes-kernel/linux/linux-karo-4.9.11/txbase/aclavis/imx6q-tx6-emmc-aclavis.dts new file mode 100755 index 0000000..f17cf72 --- /dev/null +++ b/recipes-kernel/linux/linux-karo-4.9.11/txbase/aclavis/imx6q-tx6-emmc-aclavis.dts @@ -0,0 +1,107 @@ +/* + * Copyright 2016 Lothar Waßmann + * Copyright 2016-2017 Oliver Wendt + * Copyright 2016 Michael Vyskocil + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file 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 file 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. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/* + * Please be reminded that - in general - DTSI file(s) are include files that + * are for more than one purpose (usually bound to a SoC) and as such shouldn't + * be edited. For end-user products it should be the DTS file(s) that choose + * which devices and pins are active and setup. + * + * The setup of DT files for Ka-Ro TX COM Modules under Yocto follow a + * different, non-standard, implementation to the mainline Linux kernel. + */ + +/* + * Please see the imx6*-tx6-gpio.h && imx6*-tx6.dtsi in "linux-karo-x.y.ab/tx6" + * for the definitions like TX_NAND or TX_EMMC, etc. + */ + +/dts-v1/; + +#include "imx6q.dtsi" +#include "imx6qdl-tx6.dtsi" +#include "txbase-aclavis.dtsi" + +/ { + model = "Ka-Ro electronics TX6Q Module (eMMC & RGB)"; + compatible = "karo,imx6q-tx6q", "fsl,imx6q"; +}; + +/* + * Every VOU is multi parted: backlight, device, framebuffer, pwm + * Thus all parts have to be enabled before a display can be used on the + * specific port. + */ + +&backlight0 { + status = "okay"; +}; + +/* + * NVM setup + */ + +TX_EMMC { + status = "okay"; +}; + +/* + * Remaining device references in alphabetical order + */ + +TX_LCD { + status = "okay"; + /* + * Users should add their custom timing here, therewith + * overwriting the default/pre-defined timings. For more see: + * + * txbase/{BASEBOARD}-{DISPLAY-IF}/txbase-{BASEBOARD}-{DISPLAY-IF}.dtsi + * + * e.g.: + * txbase/mb7-lvds/txbase-aclavis.dtsi + */ +}; + +TX_LCD_FB { + status = "okay"; +}; diff --git a/recipes-kernel/linux/linux-karo-4.9.11/txbase/aclavis/imx6q-tx6-nand-aclavis.dts b/recipes-kernel/linux/linux-karo-4.9.11/txbase/aclavis/imx6q-tx6-nand-aclavis.dts new file mode 100755 index 0000000..dff34a1 --- /dev/null +++ b/recipes-kernel/linux/linux-karo-4.9.11/txbase/aclavis/imx6q-tx6-nand-aclavis.dts @@ -0,0 +1,107 @@ +/* + * Copyright 2016 Lothar Waßmann + * Copyright 2016-2017 Oliver Wendt + * Copyright 2016 Michael Vyskocil + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file 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 file 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. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/* + * Please be reminded that - in general - DTSI file(s) are include files that + * are for more than one purpose (usually bound to a SoC) and as such shouldn't + * be edited. For end-user products it should be the DTS file(s) that choose + * which devices and pins are active and setup. + * + * The setup of DT files for Ka-Ro TX COM Modules under Yocto follow a + * different, non-standard, implementation to the mainline Linux kernel. + */ + +/* + * Please see the imx6*-tx6-gpio.h && imx6*-tx6.dtsi in "linux-karo-x.y.ab/tx6" + * for the definitions like TX_NAND or TX_EMMC, etc. + */ + +/dts-v1/; + +#include "imx6q.dtsi" +#include "imx6qdl-tx6.dtsi" +#include "txbase-aclavis.dtsi" + +/ { + model = "Ka-Ro electronics TX6Q Module (NAND & RGB)"; + compatible = "karo,imx6q-tx6q", "fsl,imx6q"; +}; + +/* + * Every VOU is multi parted: backlight, device, framebuffer, pwm + * Thus all parts have to be enabled before a display can be used on the + * specific port. + */ + +&backlight0 { + status = "okay"; +}; + +/* + * NVM setup + */ + +TX_NAND { + status = "okay"; +}; + +/* + * Remaining device references in alphabetical order + */ + +TX_LCD { + status = "okay"; + /* + * Users should add their custom timing here, therewith + * overwriting the default/pre-defined timings. For more see: + * + * txbase/{BASEBOARD}-{DISPLAY-IF}/txbase-{BASEBOARD}-{DISPLAY-IF}.dtsi + * + * e.g.: + * txbase/mb7-lvds/txbase-aclavis.dtsi + */ +}; + +TX_LCD_FB { + status = "okay"; +}; diff --git a/recipes-kernel/linux/linux-karo-4.9.11/txbase/aclavis/imx6qp-tx6-emmc-aclavis.dts b/recipes-kernel/linux/linux-karo-4.9.11/txbase/aclavis/imx6qp-tx6-emmc-aclavis.dts new file mode 100755 index 0000000..7ede121 --- /dev/null +++ b/recipes-kernel/linux/linux-karo-4.9.11/txbase/aclavis/imx6qp-tx6-emmc-aclavis.dts @@ -0,0 +1,108 @@ +/* + * Copyright 2016 Lothar Waßmann + * Copyright 2016-2017 Oliver Wendt + * Copyright 2016 Michael Vyskocil + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file 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 file 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. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/* + * Please be reminded that - in general - DTSI file(s) are include files that + * are for more than one purpose (usually bound to a SoC) and as such shouldn't + * be edited. For end-user products it should be the DTS file(s) that choose + * which devices and pins are active and setup. + * + * The setup of DT files for Ka-Ro TX COM Modules under Yocto follow a + * different, non-standard, implementation to the mainline Linux kernel. + */ + +/* + * Please see the imx6*-tx6-gpio.h && imx6*-tx6.dtsi in "linux-karo-x.y.ab/tx6" + * for the definitions like TX_NAND or TX_EMMC, etc. + */ + +/dts-v1/; + +#include "imx6q.dtsi" +#include "imx6qp.dtsi" +#include "imx6qdl-tx6.dtsi" +#include "txbase-aclavis.dtsi" + +/ { + model = "Ka-Ro electronics TX6Q Module (eMMC & RGB)"; + compatible = "karo,imx6q-tx6q", "fsl,imx6q"; +}; + +/* + * Every VOU is multi parted: backlight, device, framebuffer, pwm + * Thus all parts have to be enabled before a display can be used on the + * specific port. + */ + +&backlight0 { + status = "okay"; +}; + +/* + * NVM setup + */ + +TX_EMMC { + status = "okay"; +}; + +/* + * Remaining device references in alphabetical order + */ + +TX_LCD { + status = "okay"; + /* + * Users should add their custom timing here, therewith + * overwriting the default/pre-defined timings. For more see: + * + * txbase/{BASEBOARD}-{DISPLAY-IF}/txbase-{BASEBOARD}-{DISPLAY-IF}.dtsi + * + * e.g.: + * txbase/mb7-lvds/txbase-aclavis.dtsi + */ +}; + +TX_LCD_FB { + status = "okay"; +}; diff --git a/recipes-kernel/linux/linux-karo-4.9.11/txbase/aclavis/imx6s-tx6-emmc-aclavis.dts b/recipes-kernel/linux/linux-karo-4.9.11/txbase/aclavis/imx6s-tx6-emmc-aclavis.dts new file mode 100755 index 0000000..d80dbdc --- /dev/null +++ b/recipes-kernel/linux/linux-karo-4.9.11/txbase/aclavis/imx6s-tx6-emmc-aclavis.dts @@ -0,0 +1,111 @@ +/* + * Copyright 2016 Lothar Waßmann + * Copyright 2016 Oliver Wendt + * Copyright 2016 Michael Vyskocil + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file 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 file 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. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/* + * Please be reminded that - in general - DTSI file(s) are include files that + * are for more than one purpose (usually bound to a SoC) and as such shouldn't + * be edited. For end-user products it should be the DTS file(s) that choose + * which devices and pins are active and setup. + * + * The setup of DT files for Ka-Ro TX COM Modules under Yocto follow a + * different, non-standard, implementation to the mainline Linux kernel. + */ + +/* + * Please see the imx6*-tx6-gpio.h && imx6*-tx6.dtsi in "linux-karo-x.y.ab/tx6" + * for the definitions like TX_NAND or TX_EMMC, etc. + */ + +/dts-v1/; + +#include "imx6dl.dtsi" +#include "imx6qdl-tx6.dtsi" +#include "txbase-aclavis.dtsi" + +/ { + model = "Ka-Ro electronics TX6S Module (eMMC & RGB)"; + compatible = "karo,imx6dl-tx6dl", "fsl,imx6dl"; + + cpus { + /delete-node/ cpu@1; + }; +}; + +/* + * Every VOU is multi parted: backlight, device, framebuffer, pwm + * Thus all parts have to be enabled before a display can be used on the + * specific port. + */ + +&backlight0 { + status = "okay"; +}; + +/* + * NVM setup + */ + +TX_EMMC { + status = "okay"; +}; + +/* + * Remaining device references in alphabetical order + */ + +TX_LCD { + status = "okay"; + /* + * Users should add their custom timing here, therewith + * overwriting the default/pre-defined timings. For more see: + * + * txbase/{BASEBOARD}-{DISPLAY-IF}/txbase-{BASEBOARD}-{DISPLAY-IF}.dtsi + * + * e.g.: + * txbase/mb7-lvds/txbase-aclavis.dtsi + */ +}; + +TX_LCD_FB { + status = "okay"; +}; diff --git a/recipes-kernel/linux/linux-karo-4.9.11/txbase/aclavis/imx6s-tx6-nand-aclavis.dts b/recipes-kernel/linux/linux-karo-4.9.11/txbase/aclavis/imx6s-tx6-nand-aclavis.dts new file mode 100755 index 0000000..4d1dbb9 --- /dev/null +++ b/recipes-kernel/linux/linux-karo-4.9.11/txbase/aclavis/imx6s-tx6-nand-aclavis.dts @@ -0,0 +1,111 @@ +/* + * Copyright 2016 Lothar Waßmann + * Copyright 2016 Oliver Wendt + * Copyright 2016 Michael Vyskocil + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file 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 file 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. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/* + * Please be reminded that - in general - DTSI file(s) are include files that + * are for more than one purpose (usually bound to a SoC) and as such shouldn't + * be edited. For end-user products it should be the DTS file(s) that choose + * which devices and pins are active and setup. + * + * The setup of DT files for Ka-Ro TX COM Modules under Yocto follow a + * different, non-standard, implementation to the mainline Linux kernel. + */ + +/* + * Please see the imx6*-tx6-gpio.h && imx6*-tx6.dtsi in "linux-karo-x.y.ab/tx6" + * for the definitions like TX_NAND or TX_EMMC, etc. + */ + +/dts-v1/; + +#include "imx6dl.dtsi" +#include "imx6qdl-tx6.dtsi" +#include "txbase-aclavis.dtsi" + +/ { + model = "Ka-Ro electronics TX6S Module (NAND & RGB)"; + compatible = "karo,imx6dl-tx6dl", "fsl,imx6dl"; + + cpus { + /delete-node/ cpu@1; + }; +}; + +/* + * Every VOU is multi parted: backlight, device, framebuffer, pwm + * Thus all parts have to be enabled before a display can be used on the + * specific port. + */ + +&backlight0 { + status = "okay"; +}; + +/* + * NVM setup + */ + +TX_NAND { + status = "okay"; +}; + +/* + * Remaining device references in alphabetical order + */ + +TX_LCD { + status = "okay"; + /* + * Users should add their custom timing here, therewith + * overwriting the default/pre-defined timings. For more see: + * + * txbase/{BASEBOARD}-{DISPLAY-IF}/txbase-{BASEBOARD}-{DISPLAY-IF}.dtsi + * + * e.g.: + * txbase/mb7-lvds/txbase-aclavis.dtsi + */ +}; + +TX_LCD_FB { + status = "okay"; +}; diff --git a/recipes-kernel/linux/linux-karo-4.9.11/txbase/aclavis/txbase-aclavis.dtsi b/recipes-kernel/linux/linux-karo-4.9.11/txbase/aclavis/txbase-aclavis.dtsi new file mode 100755 index 0000000..d3fa888 --- /dev/null +++ b/recipes-kernel/linux/linux-karo-4.9.11/txbase/aclavis/txbase-aclavis.dtsi @@ -0,0 +1,332 @@ +/* + * Copyright 2016 Lothar Waßmann + * Copyright 2017 Oliver Wendt + * Copyright 2017 Michael Vyskocil + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file 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 file 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. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/* + * Please be reminded that in general DTSI file(s) are include files that are + * for more than one purpose (usually bound to a SoC) and as such shouldn't be + * edited. For end-user products it should be the DTS file(s) that choose which + * devices and pins are active and setup. + * + * The setup of DT files for Ka-Ro TX COM Modules under Yocto follow a + * different, non-standard, implementation, which can make it necessary. + */ + +/* + * Please see the imx6*-tx6-gpio.h && imx6*-tx6.dtsi in "linux-karo-x.y.ab/tx6" + * for the definitions like TX_NAND or TX_EMMC, etc. + */ + +/ { + aliases { + backlight = &backlight0; + backlight0 = &backlight0; + /* + * The node/alias 'display' is needed for U-Boot to be able to + * show a logo/splash image at boot time. It needs to include + * 'display-timings' as direct sub-node. + */ + display = TX_LCD; + mxcfb0 = TX_LCD_FB; + }; + + backlight0: backlight0 { + compatible = "pwm-backlight"; + pwms = ; + power-supply = <®_lcd0_pwr>; + /* + * a poor man's way to create a 1:1 relationship between + * the PWM value and the actual duty cycle + */ + brightness-levels = < 0 1 2 3 4 5 6 7 8 9 + 10 11 12 13 14 15 16 17 18 19 + 20 21 22 23 24 25 26 27 28 29 + 30 31 32 33 34 35 36 37 38 39 + 40 41 42 43 44 45 46 47 48 49 + 50 51 52 53 54 55 56 57 58 59 + 60 61 62 63 64 65 66 67 68 69 + 70 71 72 73 74 75 76 77 78 79 + 80 81 82 83 84 85 86 87 88 89 + 90 91 92 93 94 95 96 97 98 99 + 100>; + default-brightness-level = <50>; + status = "disabled"; + }; + + leds { + compatible = "gpio-leds"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_gpio_leds>; + + user_led: user { + label = "Heartbeat"; + gpios = ; + linux,default-trigger = "heartbeat"; + }; + }; + + regulators { + reg_lcd0_pwr: regulator-lcd-power { + compatible = "regulator-fixed"; + regulator-name = "LCD0 RESET"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_lcd0_pwr>; + gpio = ; + enable-active-high; + regulator-boot-on; + regulator-always-on; + }; + }; +}; + +TX_CAN1 { + status = "okay"; +}; + +TX_I2C { + status = "okay"; + + polytouch: edt-ft5x06@38 { + compatible = "edt,edt-ft5x06"; + reg = <0x38>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_edt_ft5x06>; + interrupts-extended = ; + reset-gpios = ; + wake-gpios = ; + linux,wakeup; + }; +}; + +TX_LCD { +/* + * The node/alias 'display' is needed for U-Boot to be able to show a + * logo/splash image at boot time. It needs to include 'display-timings' + * as direct sub-node. + * + * Other naming is only needed for the NXP/Freescale non-mainline + * compliant/proprietary display driver in their Yocto 4.1 Kernel + * implementation. + */ + compatible = "fsl,lcd"; + ipu_id = <0>; + disp_id = <0>; + default_ifmt = "RGB565"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_ipu1>; + status = "disabled"; + display-timings { + VGA { + clock-frequency = <25200000>; + hactive = <640>; + vactive = <480>; + hback-porch = <48>; + hsync-len = <96>; + hfront-porch = <16>; + vback-porch = <31>; + vsync-len = <2>; + vfront-porch = <12>; + hsync-active = <0>; + vsync-active = <0>; + de-active = <1>; + pixelclk-active = <0>; + }; + + ETV570 { + clock-frequency = <25200000>; + hactive = <640>; + vactive = <480>; + hback-porch = <114>; + hsync-len = <30>; + hfront-porch = <16>; + vback-porch = <32>; + vsync-len = <3>; + vfront-porch = <10>; + hsync-active = <0>; + vsync-active = <0>; + de-active = <1>; + pixelclk-active = <0>; + }; + + ET0350 { + clock-frequency = <6413760>; + hactive = <320>; + vactive = <240>; + hback-porch = <34>; + hsync-len = <34>; + hfront-porch = <20>; + vback-porch = <15>; + vsync-len = <3>; + vfront-porch = <4>; + hsync-active = <0>; + vsync-active = <0>; + de-active = <1>; + pixelclk-active = <0>; + }; + + ET0430 { + clock-frequency = <9009000>; + hactive = <480>; + vactive = <272>; + hback-porch = <2>; + hsync-len = <41>; + hfront-porch = <2>; + vback-porch = <2>; + vsync-len = <10>; + vfront-porch = <2>; + hsync-active = <0>; + vsync-active = <0>; + de-active = <1>; + pixelclk-active = <1>; + }; + + ET0500 { + clock-frequency = <33264000>; + hactive = <800>; + vactive = <480>; + hback-porch = <88>; + hsync-len = <128>; + hfront-porch = <40>; + vback-porch = <33>; + vsync-len = <2>; + vfront-porch = <10>; + hsync-active = <0>; + vsync-active = <0>; + de-active = <1>; + pixelclk-active = <0>; + }; + + ET0700 { /* same as ET0500 */ + clock-frequency = <33264000>; + hactive = <800>; + vactive = <480>; + hback-porch = <88>; + hsync-len = <128>; + hfront-porch = <40>; + vback-porch = <33>; + vsync-len = <2>; + vfront-porch = <10>; + hsync-active = <0>; + vsync-active = <0>; + de-active = <1>; + pixelclk-active = <0>; + }; + + ETQ570 { + clock-frequency = <6596040>; + hactive = <320>; + vactive = <240>; + hback-porch = <38>; + hsync-len = <30>; + hfront-porch = <30>; + vback-porch = <16>; + vsync-len = <3>; + vfront-porch = <4>; + hsync-active = <0>; + vsync-active = <0>; + de-active = <1>; + pixelclk-active = <0>; + }; + }; +}; + +TX_LCD_FB { + compatible = "fsl,mxc_sdc_fb"; + disp_dev = "lcd"; + interface_pix_fmt = "RGB24"; + default_bpp = <16>; + int_clk = <0>; + late_init = <0>; + status = "disabled"; +}; + +TX_PWM { + status = "okay"; +}; + +TX_SD1 { + status = "okay"; +}; + +TX_UART1 { + status = "okay"; +}; + +TX_UART2 { + status = "okay"; + fsl,uart-has-rtscts; + uart-has-rtscts; +}; + +TX_USBH { + status = "okay"; +}; + +TX_USBOTG { + status = "okay"; +}; + +&iomuxc { + tx6 { + pinctrl_edt_ft5x06: edt-ft5x06grp { + fsl,pins = < + TX_GPIO_PAD148 /* Interrupt */ + TX_GPIO_PAD149 /* Reset */ + TX_GPIO_PAD152 /* Wake */ + >; + }; + + pinctrl_gpio_leds: gpioledsgrp { + fsl,pins = < + TX_GPIO_PAD153 /* LED Heartbeat */ + >; + }; + + pinctrl_lcd0_pwr: lcd0-pwrgrp { + fsl,pins = < + TX_GPIO_PAD150 /* LCD Reset */ + >; + }; + }; +}; diff --git a/recipes-kernel/linux/linux-karo-4.9.11/txbase/evalkit/imx6dl-tx6-emmc-evalkit.dts b/recipes-kernel/linux/linux-karo-4.9.11/txbase/evalkit/imx6dl-tx6-emmc-evalkit.dts new file mode 100755 index 0000000..a172448 --- /dev/null +++ b/recipes-kernel/linux/linux-karo-4.9.11/txbase/evalkit/imx6dl-tx6-emmc-evalkit.dts @@ -0,0 +1,107 @@ +/* + * Copyright 2016 Lothar Waßmann + * Copyright 2016 Oliver Wendt + * Copyright 2016 Michael Vyskocil + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file 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 file 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. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/* + * Please be reminded that - in general - DTSI file(s) are include files that + * are for more than one purpose (usually bound to a SoC) and as such shouldn't + * be edited. For end-user products it should be the DTS file(s) that choose + * which devices and pins are active and setup. + * + * The setup of DT files for Ka-Ro TX COM Modules under Yocto follow a + * different, non-standard, implementation to the mainline Linux kernel. + */ + +/* + * Please see the imx6*-tx6-gpio.h && imx6*-tx6.dtsi in "linux-karo-x.y.ab/tx6" + * for the definitions like TX_NAND or TX_EMMC, etc. + */ + +/dts-v1/; + +#include "imx6dl.dtsi" +#include "imx6qdl-tx6.dtsi" +#include "txbase-evalkit.dtsi" + +/ { + model = "Ka-Ro electronics TX6U Module (eMMC & RGB)"; + compatible = "karo,imx6dl-tx6dl", "fsl,imx6dl"; +}; + +/* + * Every VOU is multi parted: backlight, device, framebuffer, pwm + * Thus all parts have to be enabled before a display can be used on the + * specific port. + */ + +&backlight0 { + status = "okay"; +}; + +/* + * NVM setup + */ + +TX_EMMC { + status = "okay"; +}; + +/* + * Remaining device references in alphabetical order + */ + +TX_LCD { + status = "okay"; + /* + * Users should add their custom timing here, therewith + * overwriting the default/pre-defined timings. For more see: + * + * txbase/{BASEBOARD}-{DISPLAY-IF}/txbase-{BASEBOARD}-{DISPLAY-IF}.dtsi + * + * e.g.: + * txbase/mb7-lvds/txbase-aclavis.dtsi + */ +}; + +TX_LCD_FB { + status = "okay"; +}; diff --git a/recipes-kernel/linux/linux-karo-4.9.11/txbase/evalkit/imx6dl-tx6-nand-evalkit.dts b/recipes-kernel/linux/linux-karo-4.9.11/txbase/evalkit/imx6dl-tx6-nand-evalkit.dts new file mode 100755 index 0000000..bbff2b3 --- /dev/null +++ b/recipes-kernel/linux/linux-karo-4.9.11/txbase/evalkit/imx6dl-tx6-nand-evalkit.dts @@ -0,0 +1,107 @@ +/* + * Copyright 2016 Lothar Waßmann + * Copyright 2016 Oliver Wendt + * Copyright 2016 Michael Vyskocil + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file 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 file 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. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/* + * Please be reminded that in general DTSI file(s) are include files that are + * for more than one purpose (usually bound to a SoC) and as such shouldn't be + * edited. For end-user products it should be the DTS file(s) that choose which + * devices and pins are active and setup. + * + * The setup of DT files for Ka-Ro TX COM Modules under Yocto follow a + * different, non-standard, implementation to the mainline Linux kernel. + */ + +/* + * Please see the imx6*-tx6-gpio.h && imx6*-tx6.dtsi in "linux-karo-x.y.ab/tx6" + * for the definitions like TX_NAND or TX_EMMC, etc. + */ + +/dts-v1/; + +#include "imx6dl.dtsi" +#include "imx6qdl-tx6.dtsi" +#include "txbase-evalkit.dtsi" + +/ { + model = "Ka-Ro electronics TX6U Module (NAND & RGB)"; + compatible = "karo,imx6dl-tx6dl", "fsl,imx6dl"; +}; + +/* + * Every VOU is multi parted: backlight, device, framebuffer, pwm + * Thus all parts have to be enabled before a display can be used on the + * specific port. + */ + +&backlight0 { + status = "okay"; +}; + +/* + * NVM setup + */ + +TX_NAND { + status = "okay"; +}; + +/* + * Remaining device references in alphabetical order + */ + +TX_LCD { + status = "okay"; + /* + * Users should add their custom timing here, therewith + * overwriting the default/pre-defined timings. For more see: + * + * txbase/{BASEBOARD}-{DISPLAY-IF}/txbase-{BASEBOARD}-{DISPLAY-IF}.dtsi + * + * e.g.: + * txbase/mb7-lvds/txbase-aclavis.dtsi + */ +}; + +TX_LCD_FB { + status = "okay"; +}; diff --git a/recipes-kernel/linux/linux-karo-4.9.11/txbase/evalkit/imx6q-tx6-emmc-evalkit.dts b/recipes-kernel/linux/linux-karo-4.9.11/txbase/evalkit/imx6q-tx6-emmc-evalkit.dts new file mode 100755 index 0000000..1d63db1 --- /dev/null +++ b/recipes-kernel/linux/linux-karo-4.9.11/txbase/evalkit/imx6q-tx6-emmc-evalkit.dts @@ -0,0 +1,107 @@ +/* + * Copyright 2016 Lothar Waßmann + * Copyright 2016-2017 Oliver Wendt + * Copyright 2016 Michael Vyskocil + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file 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 file 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. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/* + * Please be reminded that - in general - DTSI file(s) are include files that + * are for more than one purpose (usually bound to a SoC) and as such shouldn't + * be edited. For end-user products it should be the DTS file(s) that choose + * which devices and pins are active and setup. + * + * The setup of DT files for Ka-Ro TX COM Modules under Yocto follow a + * different, non-standard, implementation to the mainline Linux kernel. + */ + +/* + * Please see the imx6*-tx6-gpio.h && imx6*-tx6.dtsi in "linux-karo-x.y.ab/tx6" + * for the definitions like TX_NAND or TX_EMMC, etc. + */ + +/dts-v1/; + +#include "imx6q.dtsi" +#include "imx6qdl-tx6.dtsi" +#include "txbase-evalkit.dtsi" + +/ { + model = "Ka-Ro electronics TX6Q Module (eMMC & RGB)"; + compatible = "karo,imx6q-tx6q", "fsl,imx6q"; +}; + +/* + * Every VOU is multi parted: backlight, device, framebuffer, pwm + * Thus all parts have to be enabled before a display can be used on the + * specific port. + */ + +&backlight0 { + status = "okay"; +}; + +/* + * NVM setup + */ + +TX_EMMC { + status = "okay"; +}; + +/* + * Remaining device references in alphabetical order + */ + +TX_LCD { + status = "okay"; + /* + * Users should add their custom timing here, therewith + * overwriting the default/pre-defined timings. For more see: + * + * txbase/{BASEBOARD}-{DISPLAY-IF}/txbase-{BASEBOARD}-{DISPLAY-IF}.dtsi + * + * e.g.: + * txbase/mb7-lvds/txbase-aclavis.dtsi + */ +}; + +TX_LCD_FB { + status = "okay"; +}; diff --git a/recipes-kernel/linux/linux-karo-4.9.11/txbase/evalkit/imx6q-tx6-nand-evalkit.dts b/recipes-kernel/linux/linux-karo-4.9.11/txbase/evalkit/imx6q-tx6-nand-evalkit.dts new file mode 100755 index 0000000..639fb2a --- /dev/null +++ b/recipes-kernel/linux/linux-karo-4.9.11/txbase/evalkit/imx6q-tx6-nand-evalkit.dts @@ -0,0 +1,107 @@ +/* + * Copyright 2016 Lothar Waßmann + * Copyright 2016-2017 Oliver Wendt + * Copyright 2016 Michael Vyskocil + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file 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 file 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. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/* + * Please be reminded that in general DTSI file(s) are include files that are + * for more than one purpose (usually bound to a SoC) and as such shouldn't be + * edited. For end-user products it should be the DTS file(s) that choose which + * devices and pins are active and setup. + * + * The setup of DT files for Ka-Ro TX COM Modules under Yocto follow a + * different, non-standard, implementation, which can make it necessary. + */ + +/* + * Please see the imx6*-tx6-gpio.h && imx6*-tx6.dtsi in "linux-karo-x.y.ab/tx6" + * for the definitions like TX_NAND or TX_EMMC, etc. + */ + +/dts-v1/; + +#include "imx6q.dtsi" +#include "imx6qdl-tx6.dtsi" +#include "txbase-evalkit.dtsi" + +/ { + model = "Ka-Ro electronics TX6Q Module (NAND & RGB)"; + compatible = "karo,imx6q-tx6q", "fsl,imx6q"; +}; + +/* + * Every VOU is multi parted: backlight, device, framebuffer, pwm + * Thus all parts have to be enabled before a display can be used on the + * specific port. + */ + +&backlight0 { + status = "okay"; +}; + +/* + * NVM setup + */ + +TX_NAND { + status = "okay"; +}; + +/* + * Remaining device references in alphabetical order + */ + +TX_LCD { + status = "okay"; + /* + * Users should add their custom timing here, therewith + * overwriting the default/pre-defined timings. For more see: + * + * txbase/{BASEBOARD}-{DISPLAY-IF}/txbase-{BASEBOARD}-{DISPLAY-IF}.dtsi + * + * e.g.: + * txbase/mb7-lvds/txbase-aclavis.dtsi + */ +}; + +TX_LCD_FB { + status = "okay"; +}; diff --git a/recipes-kernel/linux/linux-karo-4.9.11/txbase/evalkit/imx6qp-tx6-emmc-evalkit.dts b/recipes-kernel/linux/linux-karo-4.9.11/txbase/evalkit/imx6qp-tx6-emmc-evalkit.dts new file mode 100755 index 0000000..1819691 --- /dev/null +++ b/recipes-kernel/linux/linux-karo-4.9.11/txbase/evalkit/imx6qp-tx6-emmc-evalkit.dts @@ -0,0 +1,108 @@ +/* + * Copyright 2016 Lothar Waßmann + * Copyright 2016-2017 Oliver Wendt + * Copyright 2016 Michael Vyskocil + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file 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 file 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. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/* + * Please be reminded that - in general - DTSI file(s) are include files that + * are for more than one purpose (usually bound to a SoC) and as such shouldn't + * be edited. For end-user products it should be the DTS file(s) that choose + * which devices and pins are active and setup. + * + * The setup of DT files for Ka-Ro TX COM Modules under Yocto follow a + * different, non-standard, implementation to the mainline Linux kernel. + */ + +/* + * Please see the imx6*-tx6-gpio.h && imx6*-tx6.dtsi in "linux-karo-x.y.ab/tx6" + * for the definitions like TX_NAND or TX_EMMC, etc. + */ + +/dts-v1/; + +#include "imx6q.dtsi" +#include "imx6qp.dtsi" +#include "imx6qdl-tx6.dtsi" +#include "txbase-evalkit.dtsi" + +/ { + model = "Ka-Ro electronics TX6Q Module (eMMC & RGB)"; + compatible = "karo,imx6q-tx6q", "fsl,imx6q"; +}; + +/* + * Every VOU is multi parted: backlight, device, framebuffer, pwm + * Thus all parts have to be enabled before a display can be used on the + * specific port. + */ + +&backlight0 { + status = "okay"; +}; + +/* + * NVM setup + */ + +TX_EMMC { + status = "okay"; +}; + +/* + * Remaining device references in alphabetical order + */ + +TX_LCD { + status = "okay"; + /* + * Users should add their custom timing here, therewith + * overwriting the default/pre-defined timings. For more see: + * + * txbase/{BASEBOARD}-{DISPLAY-IF}/txbase-{BASEBOARD}-{DISPLAY-IF}.dtsi + * + * e.g.: + * txbase/mb7-lvds/txbase-aclavis.dtsi + */ +}; + +TX_LCD_FB { + status = "okay"; +}; diff --git a/recipes-kernel/linux/linux-karo-4.9.11/txbase/evalkit/imx6s-tx6-emmc-evalkit.dts b/recipes-kernel/linux/linux-karo-4.9.11/txbase/evalkit/imx6s-tx6-emmc-evalkit.dts new file mode 100755 index 0000000..ab7e70b --- /dev/null +++ b/recipes-kernel/linux/linux-karo-4.9.11/txbase/evalkit/imx6s-tx6-emmc-evalkit.dts @@ -0,0 +1,111 @@ +/* + * Copyright 2016 Lothar Waßmann + * Copyright 2016 Oliver Wendt + * Copyright 2016 Michael Vyskocil + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file 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 file 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. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/* + * Please be reminded that - in general - DTSI file(s) are include files that + * are for more than one purpose (usually bound to a SoC) and as such shouldn't + * be edited. For end-user products it should be the DTS file(s) that choose + * which devices and pins are active and setup. + * + * The setup of DT files for Ka-Ro TX COM Modules under Yocto follow a + * different, non-standard, implementation to the mainline Linux kernel. + */ + +/* + * Please see the imx6*-tx6-gpio.h && imx6*-tx6.dtsi in "linux-karo-x.y.ab/tx6" + * for the definitions like TX_NAND or TX_EMMC, etc. + */ + +/dts-v1/; + +#include "imx6dl.dtsi" +#include "imx6qdl-tx6.dtsi" +#include "txbase-evalkit.dtsi" + +/ { + model = "Ka-Ro electronics TX6S Module (eMMC & RGB)"; + compatible = "karo,imx6dl-tx6dl", "fsl,imx6dl"; + + cpus { + /delete-node/ cpu@1; + }; +}; + +/* + * Every VOU is multi parted: backlight, device, framebuffer, pwm + * Thus all parts have to be enabled before a display can be used on the + * specific port. + */ + +&backlight0 { + status = "okay"; +}; + +/* + * NVM setup + */ + +TX_EMMC { + status = "okay"; +}; + +/* + * Remaining device references in alphabetical order + */ + +TX_LCD { + status = "okay"; + /* + * Users should add their custom timing here, therewith + * therewith overwriting the default/pre-defined timings. For more see: + * + * txbase/{BASEBOARD}-{DISPLAY-IF}/txbase-{BASEBOARD}-{DISPLAY-IF}.dtsi + * + * e.g.: + * txbase/mb7-lvds/txbase-aclavis.dtsi + */ +}; + +TX_LCD_FB { + status = "okay"; +}; diff --git a/recipes-kernel/linux/linux-karo-4.9.11/txbase/evalkit/imx6s-tx6-nand-evalkit.dts b/recipes-kernel/linux/linux-karo-4.9.11/txbase/evalkit/imx6s-tx6-nand-evalkit.dts new file mode 100755 index 0000000..0a46f7a --- /dev/null +++ b/recipes-kernel/linux/linux-karo-4.9.11/txbase/evalkit/imx6s-tx6-nand-evalkit.dts @@ -0,0 +1,111 @@ +/* + * Copyright 2016 Lothar Waßmann + * Copyright 2016 Oliver Wendt + * Copyright 2016 Michael Vyskocil + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file 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 file 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. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/* + * Please be reminded that in general DTSI file(s) are include files that are + * for more than one purpose (usually bound to a SoC) and as such shouldn't be + * edited. For end-user products it should be the DTS file(s) that choose which + * devices and pins are active and setup. + * + * The setup of DT files for Ka-Ro TX COM Modules under Yocto follow a + * different, non-standard, implementation, which can make it necessary. + */ + +/* + * Please see the imx6*-tx6-gpio.h && imx6*-tx6.dtsi in "linux-karo-x.y.ab/tx6" + * for the definitions like TX_NAND or TX_EMMC, etc. + */ + +/dts-v1/; + +#include "imx6dl.dtsi" +#include "imx6qdl-tx6.dtsi" +#include "txbase-evalkit.dtsi" + +/ { + model = "Ka-Ro electronics TX6S Module (NAND & RGB)"; + compatible = "karo,imx6dl-tx6dl", "fsl,imx6dl"; + + cpus { + /delete-node/ cpu@1; + }; +}; + +/* + * Every VOU is multi parted: backlight, device, framebuffer, pwm + * Thus all parts have to be enabled before a display can be used on the + * specific port. + */ + +&backlight0 { + status = "okay"; +}; + +/* + * NVM setup + */ + +TX_NAND { + status = "okay"; +}; + +/* + * Remaining device references in alphabetical order + */ + +TX_LCD { + status = "okay"; + /* + * Users should add their custom timing here, therewith + * overwriting the default/pre-defined timings. For more see: + * + * txbase/{BASEBOARD}-{DISPLAY-IF}/txbase-{BASEBOARD}-{DISPLAY-IF}.dtsi + * + * e.g.: + * txbase/mb7-lvds/txbase-aclavis.dtsi + */ +}; + +TX_LCD_FB { + status = "okay"; +}; diff --git a/recipes-kernel/linux/linux-karo-4.9.11/txbase/evalkit/txbase-evalkit.dtsi b/recipes-kernel/linux/linux-karo-4.9.11/txbase/evalkit/txbase-evalkit.dtsi new file mode 100755 index 0000000..d8c5987 --- /dev/null +++ b/recipes-kernel/linux/linux-karo-4.9.11/txbase/evalkit/txbase-evalkit.dtsi @@ -0,0 +1,197 @@ +/* + * Copyright 2016 Lothar Waßmann + * Copyright 2016-2017 Oliver Wendt + * Copyright 2016 Michael Vyskocil + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file 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 file 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. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + + +/* + * Please be reminded that in general DTSI file(s) are include files that are + * for more than one purpose (usually bound to a SoC) and as such shouldn't be + * edited. For end-user products it should be the DTS file(s) that choose which + * devices and pins are active and setup. + * + * The setup of DT files for Ka-Ro TX COM Modules under Yocto follow a + * different, non-standard, implementation, which can make it necessary. + */ + +/* + * Please see the imx6*-tx6-gpio.h && imx6*-tx6.dtsi in "linux-karo-x.y.ab/tx6" + * for the definitions like TX_NAND or TX_EMMC, etc. + */ + +/ { + aliases { + backlight0 = &backlight0; + /* + * The node/alias 'display' is needed for U-Boot to be able to + * show a logo/splash image at boot time. It needs to include + * 'display-timings' as direct sub-node. + */ + display = TX_LCD; + mxcfb0 = TX_LCD_FB; + }; + + backlight0: backlight0 { + compatible = "pwm-backlight"; + pwms = ; + power-supply = <®_lcd0_pwr>; + /* + * a poor man's way to create a 1:1 relationship between + * the PWM value and the actual duty cycle + */ + brightness-levels = < 0 1 2 3 4 5 6 7 8 9 + 10 11 12 13 14 15 16 17 18 19 + 20 21 22 23 24 25 26 27 28 29 + 30 31 32 33 34 35 36 37 38 39 + 40 41 42 43 44 45 46 47 48 49 + 50 51 52 53 54 55 56 57 58 59 + 60 61 62 63 64 65 66 67 68 69 + 70 71 72 73 74 75 76 77 78 79 + 80 81 82 83 84 85 86 87 88 89 + 90 91 92 93 94 95 96 97 98 99 + 100>; + default-brightness-level = <50>; + status = "disabled"; + }; + + leds { + compatible = "gpio-leds"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_gpio_leds>; + + user_led: user { + label = "Heartbeat"; + gpios = ; + linux,default-trigger = "heartbeat"; + }; + }; + + reg_lcd0_pwr: regulator-lcd0-power { + compatible = "regulator-fixed"; + regulator-name = "LCD0 RESET"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_lcd0_pwr>; + gpio = ; + enable-active-high; + regulator-boot-on; + regulator-always-on; + }; +}; + +&iomuxc { + tx6 { + pinctrl_edt_ft5x06: edt-ft5x06grp { + fsl,pins = < + TX_GPIO_PAD148 /* Interrupt */ + TX_GPIO_PAD149 /* Reset */ + TX_GPIO_PAD152 /* Wake */ + >; + }; + + pinctrl_gpio_leds: gpioledsgrp { + fsl,pins = < + TX_GPIO_PAD153 /* LED Heartbeat */ + >; + }; + + pinctrl_lcd0_pwr: lcd0-pwrgrp { + fsl,pins = < + TX_GPIO_PAD150 /* LCD Reset */ + >; + }; + }; +}; + +/* + * Ka-Ro device references in alphabetical order + */ + +TX_CAN1 { + status = "okay"; +}; + +TX_I2C { + ds1339: rtc@68 { + compatible = "dallas,ds1339"; + reg = <0x68>; + }; + + polytouch: edt-ft5x06@38 { + compatible = "edt,edt-ft5x06"; + reg = <0x38>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_edt_ft5x06>; + interrupt-extended = ; + reset-gpios = ; + wake-gpios = ; + linux,wakeup; + }; +}; + +TX_LCD { + status = "okay"; +}; + +TX_PWM { + status = "okay"; +}; + +TX_UART1 { + status = "okay"; +}; + +TX_UART2 { + status = "okay"; +}; + +TX_UART3 { + status = "okay"; +}; + +TX_USBH { + status = "okay"; +}; + +TX_USBOTG { + status = "okay"; +}; diff --git a/recipes-kernel/linux/linux-karo-4.9.11/txbase/mb7-lvds/imx6dl-tx6-emmc-mb7-lvds.dts b/recipes-kernel/linux/linux-karo-4.9.11/txbase/mb7-lvds/imx6dl-tx6-emmc-mb7-lvds.dts new file mode 100755 index 0000000..0fbc8b2 --- /dev/null +++ b/recipes-kernel/linux/linux-karo-4.9.11/txbase/mb7-lvds/imx6dl-tx6-emmc-mb7-lvds.dts @@ -0,0 +1,128 @@ +/* + * Copyright 2016 Lothar Waßmann + * Copyright 2016 Oliver Wendt + * Copyright 2016 Michael Vyskocil + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file 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 file 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. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/* + * Please be reminded that - in general - DTSI file(s) are include files that + * are for more than one purpose (usually bound to a SoC) and as such shouldn't + * be edited. For end-user products it should be the DTS file(s) that choose + * which devices and pins are active and setup. + * + * The setup of DT files for Ka-Ro TX COM Modules under Yocto follow a + * different, non-standard, implementation to the mainline Linux kernel. + */ + +/* + * Please see the imx6*-tx6-gpio.h && imx6*-tx6.dtsi in "linux-karo-x.y.ab/tx6" + * for the definitions like TX_NAND or TX_EMMC, etc. + */ + +/dts-v1/; + +#include "imx6dl.dtsi" +#include "imx6qdl-tx6.dtsi" +#include "txbase-mb7-lvds.dtsi" + +/ { + model = "Ka-Ro electronics TX6U Module (eMMC & LVDS)"; + compatible = "karo,imx6dl-tx6dl", "fsl,imx6dl"; +}; + +/* + * Every VOU is multi parted: backlight, device, framebuffer, pwm + * Thus all parts have to be enabled before a display can be used on the + * specific port. + */ + +&backlight0 { + status = "okay"; +}; + +/* + * NVM setup + */ + +TX_EMMC { + status = "okay"; +}; + +/* + * Remaining device references in alphabetical order + */ + +TX_LDB { + status = "okay"; + + lvds0: lvds-channel@0 { + status = "okay"; + /* + * Users should add their custom (U-Boot) timing here, + * therewith overwriting the default/pre-defined timings. For more see: + * + * txbase/{BASEBOARD}-{DISPLAY-IF}/txbase-{BASEBOARD}-{DISPLAY-IF}.dtsi + * + * e.g.: + * txbase/mb7-lvds/txbase-aclavis.dtsi + */ + }; + + lvds1: lvds-channel@1 { + status = "disabled"; + /* + * Users should add their custom (U-Boot) timing here, + * therewith overwriting the default/pre-defined timings. For more see: + * + * txbase/{BASEBOARD}-{DISPLAY-IF}/txbase-{BASEBOARD}-{DISPLAY-IF}.dtsi + * + * e.g.: + * txbase/mb7-lvds/txbase-aclavis.dtsi + */ + }; +}; + +TX_LDB_FB1 { + status = "okay"; +}; + +TX_LDB_FB2 { + status = "disabled"; +}; diff --git a/recipes-kernel/linux/linux-karo-4.9.11/txbase/mb7-lvds/imx6dl-tx6-nand-mb7-lvds.dts b/recipes-kernel/linux/linux-karo-4.9.11/txbase/mb7-lvds/imx6dl-tx6-nand-mb7-lvds.dts new file mode 100755 index 0000000..e3372eb --- /dev/null +++ b/recipes-kernel/linux/linux-karo-4.9.11/txbase/mb7-lvds/imx6dl-tx6-nand-mb7-lvds.dts @@ -0,0 +1,128 @@ +/* + * Copyright 2016 Lothar Waßmann + * Copyright 2016 Oliver Wendt + * Copyright 2016 Michael Vyskocil + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file 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 file 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. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/* + * Please be reminded that in general DTSI file(s) are include files that are + * for more than one purpose (usually bound to a SoC) and as such shouldn't be + * edited. For end-user products it should be the DTS file(s) that choose which + * devices and pins are active and setup. + * + * The setup of DT files for Ka-Ro TX COM Modules under Yocto follow a + * different, non-standard, implementation, which can make it necessary. + */ + +/* + * Please see the imx6*-tx6-gpio.h && imx6*-tx6.dtsi in "linux-karo-x.y.ab/tx6" + * for the definitions like TX_NAND or TX_EMMC, etc. + */ + +/dts-v1/; + +#include "imx6dl.dtsi" +#include "imx6qdl-tx6.dtsi" +#include "txbase-mb7-lvds.dtsi" + +/ { + model = "Ka-Ro electronics TX6U Module (NAND & LVDS)"; + compatible = "karo,imx6dl-tx6dl", "fsl,imx6dl"; +}; + +/* + * Every VOU is multi parted: backlight, device, framebuffer, pwm + * Thus all parts have to be enabled before a display can be used on the + * specific port. + */ + +&backlight0 { + status = "okay"; +}; + +/* + * NVM setup + */ + +TX_NAND { + status = "okay"; +}; + +/* + * Remaining device references in alphabetical order + */ + +TX_LDB { + status = "okay"; + + lvds0: lvds-channel@0 { + status = "okay"; + /* + * Users should add their custom timing here, therewith + * overwriting the default/pre-defined timings. For more see: + * + * txbase/{BASEBOARD}-{DISPLAY-IF}/txbase-{BASEBOARD}-{DISPLAY-IF}.dtsi + * + * e.g.: + * txbase/mb7-lvds/txbase-aclavis.dtsi + */ + }; + + lvds1: lvds-channel@1 { + status = "disabled"; + /* + * Users should add their custom timing here, therewith + * overwriting the default/pre-defined timings. For more see: + * + * txbase/{BASEBOARD}-{DISPLAY-IF}/txbase-{BASEBOARD}-{DISPLAY-IF}.dtsi + * + * e.g.: + * txbase/mb7-lvds/txbase-aclavis.dtsi + */ + }; +}; + +TX_LDB_FB1 { + status = "okay"; +}; + +TX_LDB_FB2 { + status = "disabled"; +}; diff --git a/recipes-kernel/linux/linux-karo-4.9.11/txbase/mb7-lvds/imx6q-tx6-emmc-mb7-lvds.dts b/recipes-kernel/linux/linux-karo-4.9.11/txbase/mb7-lvds/imx6q-tx6-emmc-mb7-lvds.dts new file mode 100755 index 0000000..3dced74 --- /dev/null +++ b/recipes-kernel/linux/linux-karo-4.9.11/txbase/mb7-lvds/imx6q-tx6-emmc-mb7-lvds.dts @@ -0,0 +1,128 @@ +/* + * Copyright 2016 Lothar Waßmann + * Copyright 2016-2017 Oliver Wendt + * Copyright 2016 Michael Vyskocil + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file 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 file 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. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/* + * Please be reminded that in general DTSI file(s) are include files that are + * for more than one purpose (usually bound to a SoC) and as such shouldn't be + * edited. For end-user products it should be the DTS file(s) that choose which + * devices and pins are active and setup. + * + * The setup of DT files for Ka-Ro TX COM Modules under Yocto follow a + * different, non-standard, implementation, which can make it necessary. + */ + +/* + * Please see the imx6*-tx6-gpio.h && imx6*-tx6.dtsi in "linux-karo-x.y.ab/tx6" + * for the definitions like TX_NAND or TX_EMMC, etc. + */ + +/dts-v1/; + +#include "imx6q.dtsi" +#include "imx6qdl-tx6.dtsi" +#include "txbase-mb7-lvds.dtsi" + +/ { + model = "Ka-Ro electronics TX6Q Module (eMMC & LVDS)"; + compatible = "karo,imx6q-tx6q", "fsl,imx6q"; +}; + +/* + * Every VOU is multi parted: backlight, device, framebuffer, pwm + * Thus all parts have to be enabled before a display can be used on the + * specific port. + */ + +&backlight0 { + status = "okay"; +}; + +/* + * NVM setup + */ + +TX_EMMC { + status = "okay"; +}; + +/* + * Remaining device references in alphabetical order + */ + +TX_LDB { + status = "okay"; + + lvds0: lvds-channel@0 { + status = "okay"; + /* + * Users should add their custom (U-Boot) timing here, + * therewith overwriting the default/pre-defined timings. For more see: + * + * txbase/{BASEBOARD}-{DISPLAY-IF}/txbase-{BASEBOARD}-{DISPLAY-IF}.dtsi + * + * e.g.: + * txbase/mb7-lvds/txbase-aclavis.dtsi + */ + }; + + lvds1: lvds-channel@1 { + status = "disabled"; + /* + * Users should add their custom (U-Boot) timing here, + * therewith overwriting the default/pre-defined timings. For more see: + * + * txbase/{BASEBOARD}-{DISPLAY-IF}/txbase-{BASEBOARD}-{DISPLAY-IF}.dtsi + * + * e.g.: + * txbase/mb7-lvds/txbase-aclavis.dtsi + */ + }; +}; + +TX_LDB_FB1 { + status = "okay"; +}; + +TX_LDB_FB2 { + status = "disabled"; +}; diff --git a/recipes-kernel/linux/linux-karo-4.9.11/txbase/mb7-lvds/imx6q-tx6-nand-mb7-lvds.dts b/recipes-kernel/linux/linux-karo-4.9.11/txbase/mb7-lvds/imx6q-tx6-nand-mb7-lvds.dts new file mode 100755 index 0000000..b482354 --- /dev/null +++ b/recipes-kernel/linux/linux-karo-4.9.11/txbase/mb7-lvds/imx6q-tx6-nand-mb7-lvds.dts @@ -0,0 +1,128 @@ +/* + * Copyright 2016 Lothar Waßmann + * Copyright 2016-2017 Oliver Wendt + * Copyright 2016 Michael Vyskocil + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file 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 file 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. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/* + * Please be reminded that in general DTSI file(s) are include files that are + * for more than one purpose (usually bound to a SoC) and as such shouldn't be + * edited. For end-user products it should be the DTS file(s) that choose which + * devices and pins are active and setup. + * + * The setup of DT files for Ka-Ro TX COM Modules under Yocto follow a + * different, non-standard, implementation, which can make it necessary. + */ + +/* + * Please see the imx6*-tx6-gpio.h && imx6*-tx6.dtsi in "linux-karo-x.y.ab/tx6" + * for the definitions like TX_NAND or TX_EMMC, etc. + */ + +/dts-v1/; + +#include "imx6q.dtsi" +#include "imx6qdl-tx6.dtsi" +#include "txbase-mb7-lvds.dtsi" + +/ { + model = "Ka-Ro electronics TX6Q Module (NAND & LVDS)"; + compatible = "karo,imx6q-tx6q", "fsl,imx6q"; +}; + +/* + * Every VOU is multi parted: backlight, device, framebuffer, pwm + * Thus all parts have to be enabled before a display can be used on the + * specific port. + */ + +&backlight0 { + status = "okay"; +}; + +/* + * NVM setup + */ + +TX_NAND { + status = "okay"; +}; + +/* + * Remaining device references in alphabetical order + */ + +TX_LDB { + status = "okay"; + + lvds0: lvds-channel@0 { + status = "okay"; + /* + * Users should add their custom timing here, therewith + * overwriting the default/pre-defined timings. For more see: + * + * txbase/{BASEBOARD}-{DISPLAY-IF}/txbase-{BASEBOARD}-{DISPLAY-IF}.dtsi + * + * e.g.: + * txbase/mb7-lvds/txbase-aclavis.dtsi + */ + }; + + lvds1: lvds-channel@1 { + status = "disabled"; + /* + * Users should add their custom timing here, therewith + * overwriting the default/pre-defined timings. For more see: + * + * txbase/{BASEBOARD}-{DISPLAY-IF}/txbase-{BASEBOARD}-{DISPLAY-IF}.dtsi + * + * e.g.: + * txbase/mb7-lvds/txbase-aclavis.dtsi + */ + }; +}; + +TX_LDB_FB1 { + status = "okay"; +}; + +TX_LDB_FB2 { + status = "disabled"; +}; diff --git a/recipes-kernel/linux/linux-karo-4.9.11/txbase/mb7-lvds/imx6qp-tx6-emmc-mb7-lvds.dts b/recipes-kernel/linux/linux-karo-4.9.11/txbase/mb7-lvds/imx6qp-tx6-emmc-mb7-lvds.dts new file mode 100755 index 0000000..aa16aa0 --- /dev/null +++ b/recipes-kernel/linux/linux-karo-4.9.11/txbase/mb7-lvds/imx6qp-tx6-emmc-mb7-lvds.dts @@ -0,0 +1,129 @@ +/* + * Copyright 2016 Lothar Waßmann + * Copyright 2016-2017 Oliver Wendt + * Copyright 2016 Michael Vyskocil + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file 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 file 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. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/* + * Please be reminded that in general DTSI file(s) are include files that are + * for more than one purpose (usually bound to a SoC) and as such shouldn't be + * edited. For end-user products it should be the DTS file(s) that choose which + * devices and pins are active and setup. + * + * The setup of DT files for Ka-Ro TX COM Modules under Yocto follow a + * different, non-standard, implementation, which can make it necessary. + */ + +/* + * Please see the imx6*-tx6-gpio.h && imx6*-tx6.dtsi in "linux-karo-x.y.ab/tx6" + * for the definitions like TX_NAND or TX_EMMC, etc. + */ + +/dts-v1/; + +#include "imx6q.dtsi" +#include "imx6qp.dtsi" +#include "imx6qdl-tx6.dtsi" +#include "txbase-mb7-lvds.dtsi" + +/ { + model = "Ka-Ro electronics TX6Q Module (eMMC & LVDS)"; + compatible = "karo,imx6q-tx6q", "fsl,imx6q"; +}; + +/* + * Every VOU is multi parted: backlight, device, framebuffer, pwm + * Thus all parts have to be enabled before a display can be used on the + * specific port. + */ + +&backlight0 { + status = "okay"; +}; + +/* + * NVM setup + */ + +TX_EMMC { + status = "okay"; +}; + +/* + * Remaining device references in alphabetical order + */ + +TX_LDB { + status = "okay"; + + lvds0: lvds-channel@0 { + status = "okay"; + /* + * Users should add their custom (U-Boot) timing here, + * therewith overwriting the default/pre-defined timings. For more see: + * + * txbase/{BASEBOARD}-{DISPLAY-IF}/txbase-{BASEBOARD}-{DISPLAY-IF}.dtsi + * + * e.g.: + * txbase/mb7-lvds/txbase-aclavis.dtsi + */ + }; + + lvds1: lvds-channel@1 { + status = "disabled"; + /* + * Users should add their custom (U-Boot) timing here, + * therewith overwriting the default/pre-defined timings. For more see: + * + * txbase/{BASEBOARD}-{DISPLAY-IF}/txbase-{BASEBOARD}-{DISPLAY-IF}.dtsi + * + * e.g.: + * txbase/mb7-lvds/txbase-aclavis.dtsi + */ + }; +}; + +TX_LDB_FB1 { + status = "okay"; +}; + +TX_LDB_FB2 { + status = "disabled"; +}; diff --git a/recipes-kernel/linux/linux-karo-4.9.11/txbase/mb7-lvds/imx6s-tx6-emmc-mb7-lvds.dts b/recipes-kernel/linux/linux-karo-4.9.11/txbase/mb7-lvds/imx6s-tx6-emmc-mb7-lvds.dts new file mode 100755 index 0000000..762f6b8 --- /dev/null +++ b/recipes-kernel/linux/linux-karo-4.9.11/txbase/mb7-lvds/imx6s-tx6-emmc-mb7-lvds.dts @@ -0,0 +1,132 @@ +/* + * Copyright 2016 Lothar Waßmann + * Copyright 2016 Oliver Wendt + * Copyright 2016 Michael Vyskocil + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file 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 file 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. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/* + * Please be reminded that - in general - DTSI file(s) are include files that + * are for more than one purpose (usually bound to a SoC) and as such shouldn't + * be edited. For end-user products it should be the DTS file(s) that choose + * which devices and pins are active and setup. + * + * The setup of DT files for Ka-Ro TX COM Modules under Yocto follow a + * different, non-standard, implementation to the mainline Linux kernel. + */ + +/* + * Please see the imx6*-tx6-gpio.h && imx6*-tx6.dtsi in "linux-karo-x.y.ab/tx6" + * for the definitions like TX_NAND or TX_EMMC, etc. + */ + +/dts-v1/; + +#include "imx6dl.dtsi" +#include "imx6qdl-tx6.dtsi" +#include "txbase-mb7-lvds.dtsi" + +/ { + model = "Ka-Ro electronics TX6S Module (eMMC & LVDS)"; + compatible = "karo,imx6dl-tx6dl", "fsl,imx6dl"; + + cpus { + /delete-node/ cpu@1; + }; +}; + +/* + * Every VOU is multi parted: backlight, device, framebuffer, pwm + * Thus all parts have to be enabled before a display can be used on the + * specific port. + */ + +&backlight0 { + status = "okay"; +}; + +/* + * NVM setup + */ + +TX_EMMC { + status = "okay"; +}; + +/* + * Remaining device references in alphabetical order + */ + +TX_LDB { + status = "okay"; + + lvds0: lvds-channel@0 { + status = "okay"; + /* + * Users should add their custom (U-Boot) timing here, + * therewith overwriting the default/pre-defined timings. For more see: + * + * txbase/{BASEBOARD}-{DISPLAY-IF}/txbase-{BASEBOARD}-{DISPLAY-IF}.dtsi + * + * e.g.: + * txbase/mb7-lvds/txbase-aclavis.dtsi + */ + }; + + lvds1: lvds-channel@1 { + status = "disabled"; + /* + * Users should add their custom (U-Boot) timing here, + * therewith overwriting the default/pre-defined timings. For more see: + * + * txbase/{BASEBOARD}-{DISPLAY-IF}/txbase-{BASEBOARD}-{DISPLAY-IF}.dtsi + * + * e.g.: + * txbase/mb7-lvds/txbase-aclavis.dtsi + */ + }; +}; + +TX_LDB_FB1 { + status = "okay"; +}; + +TX_LDB_FB2 { + status = "disabled"; +}; diff --git a/recipes-kernel/linux/linux-karo-4.9.11/txbase/mb7-lvds/imx6s-tx6-nand-mb7-lvds.dts b/recipes-kernel/linux/linux-karo-4.9.11/txbase/mb7-lvds/imx6s-tx6-nand-mb7-lvds.dts new file mode 100755 index 0000000..b627111 --- /dev/null +++ b/recipes-kernel/linux/linux-karo-4.9.11/txbase/mb7-lvds/imx6s-tx6-nand-mb7-lvds.dts @@ -0,0 +1,132 @@ +/* + * Copyright 2016 Lothar Waßmann + * Copyright 2016 Oliver Wendt + * Copyright 2016 Michael Vyskocil + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file 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 file 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. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/* + * Please be reminded that in general DTSI file(s) are include files that are + * for more than one purpose (usually bound to a SoC) and as such shouldn't be + * edited. For end-user products it should be the DTS file(s) that choose which + * devices and pins are active and setup. + * + * The setup of DT files for Ka-Ro TX COM Modules under Yocto follow a + * different, non-standard, implementation, which can make it necessary. + */ + +/* + * Please see the imx6*-tx6-gpio.h && imx6*-tx6.dtsi in "linux-karo-x.y.ab/tx6" + * for the definitions like TX_NAND or TX_EMMC, etc. + */ + +/dts-v1/; + +#include "imx6dl.dtsi" +#include "imx6qdl-tx6.dtsi" +#include "txbase-mb7-lvds.dtsi" + +/ { + model = "Ka-Ro electronics TX6S Module (NAND & LVDS)"; + compatible = "karo,imx6dl-tx6dl", "fsl,imx6dl"; + + cpus { + /delete-node/ cpu@1; + }; +}; + +/* + * Every VOU is multi parted: backlight, device, framebuffer, pwm + * Thus all parts have to be enabled before a display can be used on the + * specific port. + */ + +&backlight0 { + status = "okay"; +}; + +/* + * NVM setup + */ + +TX_NAND { + status = "okay"; +}; + +/* + * Remaining device references in alphabetical order + */ + +TX_LDB { + status = "okay"; + + lvds0: lvds-channel@0 { + status = "okay"; + /* + * Users should add their custom timing here, therewith + * overwriting the default/pre-defined timings. For more see: + * + * txbase/{BASEBOARD}-{DISPLAY-IF}/txbase-{BASEBOARD}-{DISPLAY-IF}.dtsi + * + * e.g.: + * txbase/mb7-lvds/txbase-aclavis.dtsi + */ + }; + + lvds1: lvds-channel@1 { + status = "disabled"; + /* + * Users should add their custom timing here, therewith + * overwriting the default/pre-defined timings. For more see: + * + * txbase/{BASEBOARD}-{DISPLAY-IF}/txbase-{BASEBOARD}-{DISPLAY-IF}.dtsi + * + * e.g.: + * txbase/mb7-lvds/txbase-aclavis.dtsi + */ + }; +}; + +TX_LDB_FB1 { + status = "okay"; +}; + +TX_LDB_FB2 { + status = "disabled"; +}; diff --git a/recipes-kernel/linux/linux-karo-4.9.11/txbase/mb7-lvds/txbase-mb7-lvds.dtsi b/recipes-kernel/linux/linux-karo-4.9.11/txbase/mb7-lvds/txbase-mb7-lvds.dtsi new file mode 100755 index 0000000..151e6db --- /dev/null +++ b/recipes-kernel/linux/linux-karo-4.9.11/txbase/mb7-lvds/txbase-mb7-lvds.dtsi @@ -0,0 +1,295 @@ +/* + * Copyright 2016 Lothar Waßmann + * Copyright 2017 Oliver Wendt + * Copyright 2016 Michael Vyskocil + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file 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 file 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. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/* + * Please be reminded that in general DTSI file(s) are include files that are + * for more than one purpose (usually bound to a SoC) and as such shouldn't be + * edited. For end-user products it should be the DTS file(s) that choose which + * devices and pins are active and setup. + * + * The setup of DT files for Ka-Ro TX COM Modules under Yocto follow a + * different, non-standard, implementation, which can make it necessary. + */ + +/* + * Please see the imx6*-tx6-gpio.h && imx6*-tx6.dtsi in "linux-karo-x.y.ab/tx6" + * for the definitions like TX_NAND or TX_EMMC, etc. + */ + +/ { + aliases { + backlight = &backlight0; + backlight0 = &backlight0; + /* + * The node/alias 'display' is needed for U-Boot to be able to + * show a logo/splash image at boot time. It needs to include + * 'display-timings' as direct sub-node. + */ + display = &lvds0; + lvds0 = &lvds0; + lvds1 = &lvds1; + mxcfb0 = TX_LDB_FB1; + mxcfb1 = TX_LDB_FB2; + }; + + backlight0: backlight0 { + compatible = "pwm-backlight"; + pwms = ; + power-supply = <®_lcd0_pwr>; + /* + * a poor man's way to create a 1:1 relationship between + * the PWM value and the actual duty cycle + */ + brightness-levels = < 0 1 2 3 4 5 6 7 8 9 + 10 11 12 13 14 15 16 17 18 19 + 20 21 22 23 24 25 26 27 28 29 + 30 31 32 33 34 35 36 37 38 39 + 40 41 42 43 44 45 46 47 48 49 + 50 51 52 53 54 55 56 57 58 59 + 60 61 62 63 64 65 66 67 68 69 + 70 71 72 73 74 75 76 77 78 79 + 80 81 82 83 84 85 86 87 88 89 + 90 91 92 93 94 95 96 97 98 99 + 100>; + default-brightness-level = <50>; + status = "disabled"; + }; + + leds { + compatible = "gpio-leds"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_gpio_leds>; + + user_led: user { + label = "Heartbeat"; + gpios = ; + linux,default-trigger = "heartbeat"; + }; + }; + + regulators { + reg_2v5: regulator { + compatible = "regulator-fixed"; + reg = <1>; + regulator-name = "2V5"; + regulator-min-microvolt = <2500000>; + regulator-max-microvolt = <2500000>; + regulator-always-on; + }; + + reg_3v3: regulator { + compatible = "regulator-fixed"; + reg = <2>; + regulator-name = "3V3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + }; + + reg_lcd0_pwr: regulator-lcd0-power { + compatible = "regulator-fixed"; + regulator-name = "LCD0 RESET"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_lcd0_pwr>; + gpio = ; + enable-active-high; + regulator-boot-on; + regulator-always-on; + }; + }; + + sound { + compatible = "fsl,imx-audio-sgtl5000"; + model = "sgtl5000-audio"; + pinctrl-names = "default"; + pinctrl-0 = ; + ssi-controller = <&ssi1>; + audio-codec = <&sgtl5000>; + audio-routing = + "MIC_IN", "Mic Jack", + "Mic Jack", "Mic Bias", + "Headphone Jack", "HP_OUT"; + mux-int-port = <1>; + mux-ext-port = <5>; + }; +}; + +TX_CAN1 { + status = "okay"; +}; + +TX_I2C { + status = "okay"; + + sgtl5000: sgtl5000@0a { + compatible = "fsl,sgtl5000"; + reg = <0x0a>; + VDDA-supply = <®_2v5>; + VDDIO-supply = <®_3v3>; + clocks = <&mclk>; + }; +}; + +TX_LDB { +/* + * The node/alias 'display' is needed for U-Boot to be able to show a + * logo/splash image at boot time. It needs to include 'display-timings' + * as direct sub-node. + * + * Other naming is only needed for the NXP/Freescale non-mainline + * compliant/proprietary display driver in their Yocto 4.1 Kernel + * implementation. + */ + lvds0: lvds-channel@0 { + crtc = "ipu1-di0"; + fsl,data-mapping = "spwg"; + fsl,data-width = <18>; + primary; + status = "disabled"; + + display-timings { + /* + * The naitive mode has to be named seperately between + * lvds0 & lvds1, otherwise it will be overwritten. + */ + native-mode = <&timing0>; + timing0: hsd100pxn1 { + clock-frequency = <65000000>; + hactive = <1024>; + vactive = <768>; + hback-porch = <220>; + hfront-porch = <40>; + vback-porch = <21>; + vfront-porch = <7>; + hsync-len = <60>; + vsync-len = <10>; + }; + }; + }; + + lvds1: lvds-channel@1 { + crtc = "ipu1-di1"; + fsl,data-mapping = "spwg"; + fsl,data-width = <18>; + status = "disabled"; + + display-timings { + /* + * The naitive mode has to be named seperately between + * lvds0 & lvds1, otherwise it will be overwritten. + */ + native-mode = <&timing1>; + timing1: hsd100pxn1 { + clock-frequency = <65000000>; + hactive = <1024>; + vactive = <768>; + hback-porch = <220>; + hfront-porch = <40>; + vback-porch = <21>; + vfront-porch = <7>; + hsync-len = <60>; + vsync-len = <10>; + }; + }; + }; +}; + +TX_LDB_FB1 { + status = "okay"; +}; + +TX_LDB_FB2 { + status = "okay"; +}; + +TX_PWM { + status = "okay"; +}; + +TX_SD1 { + status = "okay"; +}; + +TX_SSI1 { + status = "okay"; +}; + +TX_UART1 { + status = "okay"; +}; + +TX_UART2 { + status = "okay"; + fsl,uart-has-rtscts; + uart-has-rtscts; +}; + +TX_UART3 { + status = "okay"; +}; + +TX_USBH { + status = "okay"; +}; + +TX_USBOTG { + status = "okay"; +}; + +&iomuxc { + tx6 { + pinctrl_gpio_leds: gpioledsgrp { + fsl,pins = < + TX_GPIO_PAD153 /* LED Heartbeat */ + >; + }; + + pinctrl_lcd0_pwr: lcd0-pwrgrp { + fsl,pins = < + TX_GPIO_PAD150 /* LCD Reset */ + >; + }; + }; +}; diff --git a/recipes-kernel/linux/linux-karo-4.9.11/txbase/mb7/imx6dl-tx6-emmc-mb7.dts b/recipes-kernel/linux/linux-karo-4.9.11/txbase/mb7/imx6dl-tx6-emmc-mb7.dts new file mode 100755 index 0000000..b978516 --- /dev/null +++ b/recipes-kernel/linux/linux-karo-4.9.11/txbase/mb7/imx6dl-tx6-emmc-mb7.dts @@ -0,0 +1,107 @@ +/* + * Copyright 2016 Lothar Waßmann + * Copyright 2016 Oliver Wendt + * Copyright 2016 Michael Vyskocil + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file 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 file 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. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/* + * Please be reminded that - in general - DTSI file(s) are include files that + * are for more than one purpose (usually bound to a SoC) and as such shouldn't + * be edited. For end-user products it should be the DTS file(s) that choose + * which devices and pins are active and setup. + * + * The setup of DT files for Ka-Ro TX COM Modules under Yocto follow a + * different, non-standard, implementation to the mainline Linux kernel. + */ + +/* + * Please see the imx6*-tx6-gpio.h && imx6*-tx6.dtsi in "linux-karo-x.y.ab/tx6" + * for the definitions like TX_NAND or TX_EMMC, etc. + */ + +/dts-v1/; + +#include "imx6dl.dtsi" +#include "imx6qdl-tx6.dtsi" +#include "txbase-mb7.dtsi" + +/ { + model = "Ka-Ro electronics TX6U Module (eMMC & RGB)"; + compatible = "karo,imx6dl-tx6dl", "fsl,imx6dl"; +}; + +/* + * Every VOU is multi parted: backlight, device, framebuffer, pwm + * Thus all parts have to be enabled before a display can be used on the + * specific port. + */ + +&backlight0 { + status = "okay"; +}; + +/* + * NVM setup + */ + +TX_EMMC { + status = "okay"; +}; + +/* + * Remaining device references in alphabetical order + */ + +TX_LCD { + status = "okay"; + /* + * Users should add their custom timing here, therewith + * therewith overwriting the default/pre-defined timings. For more see: + * + * txbase/{BASEBOARD}-{DISPLAY-IF}/txbase-{BASEBOARD}-{DISPLAY-IF}.dtsi + * + * e.g.: + * txbase/mb7-lvds/txbase-aclavis.dtsi + */ +}; + +TX_LCD_FB { + status = "okay"; +}; diff --git a/recipes-kernel/linux/linux-karo-4.9.11/txbase/mb7/imx6dl-tx6-nand-mb7.dts b/recipes-kernel/linux/linux-karo-4.9.11/txbase/mb7/imx6dl-tx6-nand-mb7.dts new file mode 100755 index 0000000..01dda19 --- /dev/null +++ b/recipes-kernel/linux/linux-karo-4.9.11/txbase/mb7/imx6dl-tx6-nand-mb7.dts @@ -0,0 +1,107 @@ +/* + * Copyright 2016 Lothar Waßmann + * Copyright 2016 Oliver Wendt + * Copyright 2016 Michael Vyskocil + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file 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 file 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. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/* + * Please be reminded that in general DTSI file(s) are include files that are + * for more than one purpose (usually bound to a SoC) and as such shouldn't be + * edited. For end-user products it should be the DTS file(s) that choose which + * devices and pins are active and setup. + * + * The setup of DT files for Ka-Ro TX COM Modules under Yocto follow a + * different, non-standard, implementation, which can make it necessary. + */ + +/* + * Please see the imx6*-tx6-gpio.h && imx6*-tx6.dtsi in "linux-karo-x.y.ab/tx6" + * for the definitions like TX_NAND or TX_EMMC, etc. + */ + +/dts-v1/; + +#include "imx6dl.dtsi" +#include "imx6qdl-tx6.dtsi" +#include "txbase-mb7.dtsi" + +/ { + model = "Ka-Ro electronics TX6U Module (NAND & RGB)"; + compatible = "karo,imx6dl-tx6dl", "fsl,imx6dl"; +}; + +/* + * Every VOU is multi parted: backlight, device, framebuffer, pwm + * Thus all parts have to be enabled before a display can be used on the + * specific port. + */ + +&backlight0 { + status = "okay"; +}; + +/* + * NVM setup + */ + +TX_NAND { + status = "okay"; +}; + +/* + * Remaining device references in alphabetical order + */ + +TX_LCD { + status = "okay"; + /* + * Users should add their custom timing here, therewith + * overwriting the default/pre-defined timings. For more see: + * + * txbase/{BASEBOARD}-{DISPLAY-IF}/txbase-{BASEBOARD}-{DISPLAY-IF}.dtsi + * + * e.g.: + * txbase/mb7-lvds/txbase-aclavis.dtsi + */ +}; + +TX_LCD_FB { + status = "okay"; +}; diff --git a/recipes-kernel/linux/linux-karo-4.9.11/txbase/mb7/imx6q-tx6-emmc-mb7.dts b/recipes-kernel/linux/linux-karo-4.9.11/txbase/mb7/imx6q-tx6-emmc-mb7.dts new file mode 100755 index 0000000..5020ecb --- /dev/null +++ b/recipes-kernel/linux/linux-karo-4.9.11/txbase/mb7/imx6q-tx6-emmc-mb7.dts @@ -0,0 +1,107 @@ +/* + * Copyright 2016 Lothar Waßmann + * Copyright 2016-2017 Oliver Wendt + * Copyright 2016 Michael Vyskocil + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file 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 file 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. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/* + * Please be reminded that - in general - DTSI file(s) are include files that + * are for more than one purpose (usually bound to a SoC) and as such shouldn't + * be edited. For end-user products it should be the DTS file(s) that choose + * which devices and pins are active and setup. + * + * The setup of DT files for Ka-Ro TX COM Modules under Yocto follow a + * different, non-standard, implementation to the mainline Linux kernel. + */ + +/* + * Please see the imx6*-tx6-gpio.h && imx6*-tx6.dtsi in "linux-karo-x.y.ab/tx6" + * for the definitions like TX_NAND or TX_EMMC, etc. + */ + +/dts-v1/; + +#include "imx6q.dtsi" +#include "imx6qdl-tx6.dtsi" +#include "txbase-mb7.dtsi" + +/ { + model = "Ka-Ro electronics TX6Q Module (eMMC & RGB)"; + compatible = "karo,imx6q-tx6q", "fsl,imx6q"; +}; + +/* + * Every VOU is multi parted: backlight, device, framebuffer, pwm + * Thus all parts have to be enabled before a display can be used on the + * specific port. + */ + +&backlight0 { + status = "okay"; +}; + +/* + * NVM setup + */ + +TX_EMMC { + status = "okay"; +}; + +/* + * Remaining device references in alphabetical order + */ + +TX_LCD { + status = "okay"; + /* + * Users should add their custom timing here, therewith + * overwriting the default/pre-defined timings. For more see: + * + * txbase/{BASEBOARD}-{DISPLAY-IF}/txbase-{BASEBOARD}-{DISPLAY-IF}.dtsi + * + * e.g.: + * txbase/mb7-lvds/txbase-aclavis.dtsi + */ +}; + +TX_LCD_FB { + status = "okay"; +}; diff --git a/recipes-kernel/linux/linux-karo-4.9.11/txbase/mb7/imx6q-tx6-nand-mb7.dts b/recipes-kernel/linux/linux-karo-4.9.11/txbase/mb7/imx6q-tx6-nand-mb7.dts new file mode 100755 index 0000000..ec2a67c --- /dev/null +++ b/recipes-kernel/linux/linux-karo-4.9.11/txbase/mb7/imx6q-tx6-nand-mb7.dts @@ -0,0 +1,107 @@ +/* + * Copyright 2016 Lothar Waßmann + * Copyright 2016-2017 Oliver Wendt + * Copyright 2016 Michael Vyskocil + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file 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 file 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. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/* + * Please be reminded that in general DTSI file(s) are include files that are + * for more than one purpose (usually bound to a SoC) and as such shouldn't be + * edited. For end-user products it should be the DTS file(s) that choose which + * devices and pins are active and setup. + * + * The setup of DT files for Ka-Ro TX COM Modules under Yocto follow a + * different, non-standard, implementation, which can make it necessary. + */ + +/* + * Please see the imx6*-tx6-gpio.h && imx6*-tx6.dtsi in "linux-karo-x.y.ab/tx6" + * for the definitions like TX_NAND or TX_EMMC, etc. + */ + +/dts-v1/; + +#include "imx6q.dtsi" +#include "imx6qdl-tx6.dtsi" +#include "txbase-mb7.dtsi" + +/ { + model = "Ka-Ro electronics TX6Q Module (NAND & RGB)"; + compatible = "karo,imx6q-tx6q", "fsl,imx6q"; +}; + +/* + * Every VOU is multi parted: backlight, device, framebuffer, pwm + * Thus all parts have to be enabled before a display can be used on the + * specific port. + */ + +&backlight0 { + status = "okay"; +}; + +/* + * NVM setup + */ + +TX_NAND { + status = "okay"; +}; + +/* + * Remaining device references in alphabetical order + */ + +TX_LCD { + status = "okay"; + /* + * Users should add their custom timing here, therewith + * overwriting the default/pre-defined timings. For more see: + * + * txbase/{BASEBOARD}-{DISPLAY-IF}/txbase-{BASEBOARD}-{DISPLAY-IF}.dtsi + * + * e.g.: + * txbase/mb7-lvds/txbase-aclavis.dtsi + */ +}; + +TX_LCD_FB { + status = "okay"; +}; diff --git a/recipes-kernel/linux/linux-karo-4.9.11/txbase/mb7/imx6qp-tx6-emmc-mb7.dts b/recipes-kernel/linux/linux-karo-4.9.11/txbase/mb7/imx6qp-tx6-emmc-mb7.dts new file mode 100755 index 0000000..4988ac5 --- /dev/null +++ b/recipes-kernel/linux/linux-karo-4.9.11/txbase/mb7/imx6qp-tx6-emmc-mb7.dts @@ -0,0 +1,108 @@ +/* + * Copyright 2016 Lothar Waßmann + * Copyright 2016-2017 Oliver Wendt + * Copyright 2016 Michael Vyskocil + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file 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 file 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. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/* + * Please be reminded that - in general - DTSI file(s) are include files that + * are for more than one purpose (usually bound to a SoC) and as such shouldn't + * be edited. For end-user products it should be the DTS file(s) that choose + * which devices and pins are active and setup. + * + * The setup of DT files for Ka-Ro TX COM Modules under Yocto follow a + * different, non-standard, implementation to the mainline Linux kernel. + */ + +/* + * Please see the imx6*-tx6-gpio.h && imx6*-tx6.dtsi in "linux-karo-x.y.ab/tx6" + * for the definitions like TX_NAND or TX_EMMC, etc. + */ + +/dts-v1/; + +#include "imx6q.dtsi" +#include "imx6qp.dtsi" +#include "imx6qdl-tx6.dtsi" +#include "txbase-mb7.dtsi" + +/ { + model = "Ka-Ro electronics TX6QP Module (eMMC & RGB)"; + compatible = "karo,imx6qp-tx6qp", "karo,imx6q-tx6q", "fsl,imx6q"; +}; + +/* + * Every VOU is multi parted: backlight, device, framebuffer, pwm + * Thus all parts have to be enabled before a display can be used on the + * specific port. + */ + +&backlight0 { + status = "okay"; +}; + +/* + * NVM setup + */ + +TX_EMMC { + status = "okay"; +}; + +/* + * Remaining device references in alphabetical order + */ + +TX_LCD { + status = "okay"; + /* + * Users should add their custom timing here, therewith + * overwriting the default/pre-defined timings. For more see: + * + * txbase/{BASEBOARD}-{DISPLAY-IF}/txbase-{BASEBOARD}.dtsi + * + * e.g.: + * txbase/mb7-lvds/txbase-aclavis.dtsi + */ +}; + +TX_LCD_FB { + status = "okay"; +}; diff --git a/recipes-kernel/linux/linux-karo-4.9.11/txbase/mb7/imx6s-tx6-emmc-mb7.dts b/recipes-kernel/linux/linux-karo-4.9.11/txbase/mb7/imx6s-tx6-emmc-mb7.dts new file mode 100755 index 0000000..394890a --- /dev/null +++ b/recipes-kernel/linux/linux-karo-4.9.11/txbase/mb7/imx6s-tx6-emmc-mb7.dts @@ -0,0 +1,111 @@ +/* + * Copyright 2016 Lothar Waßmann + * Copyright 2016 Oliver Wendt + * Copyright 2016 Michael Vyskocil + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file 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 file 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. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/* + * Please be reminded that - in general - DTSI file(s) are include files that + * are for more than one purpose (usually bound to a SoC) and as such shouldn't + * be edited. For end-user products it should be the DTS file(s) that choose + * which devices and pins are active and setup. + * + * The setup of DT files for Ka-Ro TX COM Modules under Yocto follow a + * different, non-standard, implementation to the mainline Linux kernel. + */ + +/* + * Please see the imx6*-tx6-gpio.h && imx6*-tx6.dtsi in "linux-karo-x.y.ab/tx6" + * for the definitions like TX_NAND or TX_EMMC, etc. + */ + +/dts-v1/; + +#include "imx6dl.dtsi" +#include "imx6qdl-tx6.dtsi" +#include "txbase-mb7.dtsi" + +/ { + model = "Ka-Ro electronics TX6S Module (eMMC & RGB)"; + compatible = "karo,imx6dl-tx6dl", "fsl,imx6dl"; + + cpus { + /delete-node/ cpu@1; + }; +}; + +/* + * Every VOU is multi parted: backlight, device, framebuffer, pwm + * Thus all parts have to be enabled before a display can be used on the + * specific port. + */ + +&backlight0 { + status = "okay"; +}; + +/* + * NVM setup + */ + +TX_EMMC { + status = "okay"; +}; + +/* + * Remaining device references in alphabetical order + */ + +TX_LCD { + status = "okay"; + /* + * Users should add their custom timing here, therewith + * overwriting the default/pre-defined timings. For more see: + * + * txbase/{BASEBOARD}-{DISPLAY-IF}/txbase-{BASEBOARD}-{DISPLAY-IF}.dtsi + * + * e.g.: + * txbase/mb7-lvds/txbase-aclavis.dtsi + */ +}; + +TX_LCD_FB { + status = "okay"; +}; diff --git a/recipes-kernel/linux/linux-karo-4.9.11/txbase/mb7/imx6s-tx6-nand-mb7.dts b/recipes-kernel/linux/linux-karo-4.9.11/txbase/mb7/imx6s-tx6-nand-mb7.dts new file mode 100755 index 0000000..9e4ff16 --- /dev/null +++ b/recipes-kernel/linux/linux-karo-4.9.11/txbase/mb7/imx6s-tx6-nand-mb7.dts @@ -0,0 +1,111 @@ +/* + * Copyright 2016 Lothar Waßmann + * Copyright 2016 Oliver Wendt + * Copyright 2016 Michael Vyskocil + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file 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 file 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. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/* + * Please be reminded that in general DTSI file(s) are include files that are + * for more than one purpose (usually bound to a SoC) and as such shouldn't be + * edited. For end-user products it should be the DTS file(s) that choose which + * devices and pins are active and setup. + * + * The setup of DT files for Ka-Ro TX COM Modules under Yocto follow a + * different, non-standard, implementation, which can make it necessary. + */ + +/* + * Please see the imx6*-tx6-gpio.h && imx6*-tx6.dtsi in "linux-karo-x.y.ab/tx6" + * for the definitions like TX_NAND or TX_EMMC, etc. + */ + +/dts-v1/; + +#include "imx6dl.dtsi" +#include "imx6qdl-tx6.dtsi" +#include "txbase-mb7.dtsi" + +/ { + model = "Ka-Ro electronics TX6S Module (NAND & RGB)"; + compatible = "karo,imx6dl-tx6dl", "fsl,imx6dl"; + + cpus { + /delete-node/ cpu@1; + }; +}; + +/* + * Every VOU is multi parted: backlight, device, framebuffer, pwm + * Thus all parts have to be enabled before a display can be used on the + * specific port. + */ + +&backlight0 { + status = "okay"; +}; + +/* + * NVM setup + */ + +TX_NAND { + status = "okay"; +}; + +/* + * Remaining device references in alphabetical order + */ + +TX_LCD { + status = "okay"; + /* + * Users should add their custom timing here, therewith + * overwriting the default/pre-defined timings. For more see: + * + * txbase/{BASEBOARD}-{DISPLAY-IF}/txbase-{BASEBOARD}-{DISPLAY-IF}.dtsi + * + * e.g.: + * txbase/mb7-lvds/txbase-aclavis.dtsi + */ +}; + +TX_LCD_FB { + status = "okay"; +}; diff --git a/recipes-kernel/linux/linux-karo-4.9.11/txbase/mb7/txbase-mb7.dtsi b/recipes-kernel/linux/linux-karo-4.9.11/txbase/mb7/txbase-mb7.dtsi new file mode 100755 index 0000000..582bd35 --- /dev/null +++ b/recipes-kernel/linux/linux-karo-4.9.11/txbase/mb7/txbase-mb7.dtsi @@ -0,0 +1,382 @@ +/* + * Copyright 2016 Lothar Waßmann + * Copyright 2017 Oliver Wendt + * Copyright 2016 Michael Vyskocil + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file 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 file 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. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/* + * Please be reminded that in general DTSI file(s) are include files that are + * for more than one purpose (usually bound to a SoC) and as such shouldn't be + * edited. For end-user products it should be the DTS file(s) that choose which + * devices and pins are active and setup. + * + * The setup of DT files for Ka-Ro TX COM Modules under Yocto follow a + * different, non-standard, implementation, which can make it necessary. + */ + +/* + * Please see the imx6*-tx6-gpio.h && imx6*-tx6.dtsi in "linux-karo-x.y.ab/tx6" + * for the definitions like TX_NAND or TX_EMMC, etc. + */ + +/ { + aliases { + backlight = &backlight0; + backlight0 = &backlight0; + /* + * The node/alias 'display' is needed for U-Boot to be able to + * show a logo/splash image at boot time. It needs to include + * 'display-timings' as direct sub-node. + */ + display = TX_LCD; + mxcfb0 = TX_LCD_FB; + }; + + backlight0: backlight0 { + compatible = "pwm-backlight"; + pwms = ; + power-supply = <®_lcd0_pwr>; + /* + * a poor man's way to create a 1:1 relationship between + * the PWM value and the actual duty cycle + */ + brightness-levels = < 0 1 2 3 4 5 6 7 8 9 + 10 11 12 13 14 15 16 17 18 19 + 20 21 22 23 24 25 26 27 28 29 + 30 31 32 33 34 35 36 37 38 39 + 40 41 42 43 44 45 46 47 48 49 + 50 51 52 53 54 55 56 57 58 59 + 60 61 62 63 64 65 66 67 68 69 + 70 71 72 73 74 75 76 77 78 79 + 80 81 82 83 84 85 86 87 88 89 + 90 91 92 93 94 95 96 97 98 99 + 100>; + default-brightness-level = <50>; + status = "disabled"; + }; + + leds { + compatible = "gpio-leds"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_gpio_leds>; + + user_led: user { + label = "Heartbeat"; + gpios = ; + linux,default-trigger = "heartbeat"; + }; + }; + + regulators { + reg_2v5: regulator { + compatible = "regulator-fixed"; + reg = <1>; + regulator-name = "2V5"; + regulator-min-microvolt = <2500000>; + regulator-max-microvolt = <2500000>; + regulator-always-on; + }; + + reg_3v3: regulator { + compatible = "regulator-fixed"; + reg = <2>; + regulator-name = "3V3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + }; + + reg_lcd0_pwr: regulator-lcd-power { + compatible = "regulator-fixed"; + regulator-name = "LCD0 RESET"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_lcd0_pwr>; + gpio = ; + enable-active-high; + regulator-boot-on; + regulator-always-on; + }; + }; + + sound { + compatible = "fsl,imx-audio-sgtl5000"; + model = "sgtl5000-audio"; + pinctrl-names = "default"; + pinctrl-0 = ; + ssi-controller = <&ssi1>; + audio-codec = <&sgtl5000>; + audio-routing = + "MIC_IN", "Mic Jack", + "Mic Jack", "Mic Bias", + "Headphone Jack", "HP_OUT"; + mux-int-port = <1>; + mux-ext-port = <5>; + status = "okay"; + }; +}; + +TX_CAN1 { + status = "okay"; +}; + +TX_I2C { + status = "okay"; + + sgtl5000: sgtl5000@0a { + compatible = "fsl,sgtl5000"; + reg = <0x0a>; + VDDA-supply = <®_2v5>; + VDDIO-supply = <®_3v3>; + clocks = <&mclk>; + }; + + polytouch: edt-ft5x06@38 { + compatible = "edt,edt-ft5x06"; + reg = <0x38>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_edt_ft5x06>; + interrupts-extended = ; + reset-gpios = ; + wake-gpios = ; + linux,wakeup; + }; +}; + +TX_LCD { +/* + * The node/alias 'display' is needed for U-Boot to be able to show a + * logo/splash image at boot time. It needs to include 'display-timings' + * as direct sub-node. + * + * Other naming is only needed for the NXP/Freescale non-mainline + * compliant/proprietary display driver in their Yocto 4.1 Kernel + * implementation. + */ + compatible = "fsl,lcd"; + ipu_id = <0>; + disp_id = <0>; + default_ifmt = "RGB565"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_ipu1>; + status = "disabled"; + display-timings { + VGA { + clock-frequency = <25200000>; + hactive = <640>; + vactive = <480>; + hback-porch = <48>; + hsync-len = <96>; + hfront-porch = <16>; + vback-porch = <31>; + vsync-len = <2>; + vfront-porch = <12>; + hsync-active = <0>; + vsync-active = <0>; + de-active = <1>; + pixelclk-active = <0>; + }; + + ETV570 { + clock-frequency = <25200000>; + hactive = <640>; + vactive = <480>; + hback-porch = <114>; + hsync-len = <30>; + hfront-porch = <16>; + vback-porch = <32>; + vsync-len = <3>; + vfront-porch = <10>; + hsync-active = <0>; + vsync-active = <0>; + de-active = <1>; + pixelclk-active = <0>; + }; + + ET0350 { + clock-frequency = <6413760>; + hactive = <320>; + vactive = <240>; + hback-porch = <34>; + hsync-len = <34>; + hfront-porch = <20>; + vback-porch = <15>; + vsync-len = <3>; + vfront-porch = <4>; + hsync-active = <0>; + vsync-active = <0>; + de-active = <1>; + pixelclk-active = <0>; + }; + + ET0430 { + clock-frequency = <9009000>; + hactive = <480>; + vactive = <272>; + hback-porch = <2>; + hsync-len = <41>; + hfront-porch = <2>; + vback-porch = <2>; + vsync-len = <10>; + vfront-porch = <2>; + hsync-active = <0>; + vsync-active = <0>; + de-active = <1>; + pixelclk-active = <1>; + }; + + ET0500 { + clock-frequency = <33264000>; + hactive = <800>; + vactive = <480>; + hback-porch = <88>; + hsync-len = <128>; + hfront-porch = <40>; + vback-porch = <33>; + vsync-len = <2>; + vfront-porch = <10>; + hsync-active = <0>; + vsync-active = <0>; + de-active = <1>; + pixelclk-active = <0>; + }; + + ET0700 { /* same as ET0500 */ + clock-frequency = <33264000>; + hactive = <800>; + vactive = <480>; + hback-porch = <88>; + hsync-len = <128>; + hfront-porch = <40>; + vback-porch = <33>; + vsync-len = <2>; + vfront-porch = <10>; + hsync-active = <0>; + vsync-active = <0>; + de-active = <1>; + pixelclk-active = <0>; + }; + + ETQ570 { + clock-frequency = <6596040>; + hactive = <320>; + vactive = <240>; + hback-porch = <38>; + hsync-len = <30>; + hfront-porch = <30>; + vback-porch = <16>; + vsync-len = <3>; + vfront-porch = <4>; + hsync-active = <0>; + vsync-active = <0>; + de-active = <1>; + pixelclk-active = <0>; + }; + }; +}; + +TX_LCD_FB { + compatible = "fsl,mxc_sdc_fb"; + disp_dev = "lcd"; + interface_pix_fmt = "RGB24"; + default_bpp = <16>; + int_clk = <0>; + late_init = <0>; + status = "disabled"; +}; + +TX_PWM { + status = "okay"; +}; + +TX_SD1 { + status = "okay"; +}; + +TX_SSI1 { + status = "okay"; +}; + +TX_UART1 { + status = "okay"; +}; + +TX_UART2 { + status = "okay"; + fsl,uart-has-rtscts; + uart-has-rtscts; +}; + +TX_UART3 { + status = "okay"; +}; + +TX_USBH { + status = "okay"; +}; + +TX_USBOTG { + status = "okay"; +}; + +&iomuxc { + tx6 { + pinctrl_edt_ft5x06: edt-ft5x06grp { + fsl,pins = < + TX_GPIO_PAD148 /* Interrupt */ + TX_GPIO_PAD149 /* Reset */ + TX_GPIO_PAD152 /* Wake */ + >; + }; + + pinctrl_gpio_leds: gpioledsgrp { + fsl,pins = < + TX_GPIO_PAD153 /* LED Heartbeat */ + >; + }; + + pinctrl_lcd0_pwr: lcd0-pwrgrp { + fsl,pins = < + TX_GPIO_PAD150 /* LCD Reset */ + >; + }; + }; +}; diff --git a/recipes-kernel/linux/linux-karo-4.9.11/txbase/myboard/imx6s-tx6-emmc-myboard.dts b/recipes-kernel/linux/linux-karo-4.9.11/txbase/myboard/imx6s-tx6-emmc-myboard.dts new file mode 100755 index 0000000..10b1570 --- /dev/null +++ b/recipes-kernel/linux/linux-karo-4.9.11/txbase/myboard/imx6s-tx6-emmc-myboard.dts @@ -0,0 +1,111 @@ +/* + * Copyright 2016 Lothar Waßmann + * Copyright 2016 Oliver Wendt + * Copyright 2016 Michael Vyskocil + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file 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 file 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. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/* + * Please be reminded that - in general - DTSI file(s) are include files that + * are for more than one purpose (usually bound to a SoC) and as such shouldn't + * be edited. For end-user products it should be the DTS file(s) that choose + * which devices and pins are active and setup. + * + * The setup of DT files for Ka-Ro TX COM Modules under Yocto follow a + * different, non-standard, implementation to the mainline Linux kernel. + */ + +/* + * Please see the imx6*-tx6-gpio.h && imx6*-tx6.dtsi in "linux-karo-x.y.ab/tx6" + * for the definitions like TX_NAND or TX_EMMC, etc. + */ + +/dts-v1/; + +#include "imx6dl.dtsi" +#include "imx6qdl-tx6.dtsi" +#include "txbase-mb7.dtsi" + +/ { + model = "Ka-Ro electronics TX6S Module (eMMC & RGB)"; + compatible = "karo,imx6dl-tx6dl", "fsl,imx6dl"; + + cpus { + /delete-node/ cpu@1; + }; +}; + +/* + * Every VOU is multi parted: backlight, device, framebuffer, pwm + * Thus all parts have to be enabled before a display can be used on the + * specific port. + */ + +&backlight0 { + status = "okay"; +}; + +/* + * NVM setup + */ + +TX_EMMC { + status = "okay"; +}; + +/* + * Remaining device references in alphabetical order + */ + +TX_LCD { + status = "okay"; + /* + * Users should add their custom timing here, therewith + * overwriting the default/pre-defined timings. For more see + * + * txbase/{BASEBOARD}-{DISPLAY-IF}/txbase-{BASEBOARD}-{DISPLAY-IF}.dtsi + * + * e.g.: + * txbase/mb7-lvds/txbase-aclavis.dtsi + */ +}; + +TX_LCD_FB { + status = "okay"; +}; diff --git a/recipes-kernel/linux/linux-karo-4.9.11/txbase/myboard/txbase-myboard.dtsi b/recipes-kernel/linux/linux-karo-4.9.11/txbase/myboard/txbase-myboard.dtsi new file mode 100755 index 0000000..04337e5 --- /dev/null +++ b/recipes-kernel/linux/linux-karo-4.9.11/txbase/myboard/txbase-myboard.dtsi @@ -0,0 +1,383 @@ +/* + * Copyright 2016 Lothar Waßmann + * Copyright 2016-2017 Oliver Wendt + * Copyright 2016 Michael Vyskocil + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file 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 file 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. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/* + * Please be reminded that in general DTSI file(s) are include files that are + * for more than one purpose (usually bound to a SoC) and as such shouldn't be + * edited. For end-user products it should be the DTS file(s) that choose which + * devices and pins are active and setup. + * + * The setup of DT files for Ka-Ro TX COM Modules under Yocto follow a + * different, non-standard, implementation, which can make it necessary. + */ + +/* + * Please see the imx6*-tx6-gpio.h && imx6*-tx6.dtsi in "linux-karo-x.y.ab/tx6" + * for the definitions like TX_NAND or TX_EMMC, etc. + */ + +/ { + aliases { + backlight = &backlight0; + backlight0 = &backlight0; + /* + * The node/alias 'display' is needed for U-Boot to be able to + * show a logo/splash image at boot time. It needs to include + * 'display-timings' as direct sub-node. + */ + display = TX_LCD; + mxcfb0 = TX_LCD_FB; + }; + + backlight0: backlight0 { + compatible = "pwm-backlight"; + pwms = ; + power-supply = <®_lcd0_pwr>; + /* + * a poor man's way to create a 1:1 relationship between + * the PWM value and the actual duty cycle + */ + brightness-levels = < 0 1 2 3 4 5 6 7 8 9 + 10 11 12 13 14 15 16 17 18 19 + 20 21 22 23 24 25 26 27 28 29 + 30 31 32 33 34 35 36 37 38 39 + 40 41 42 43 44 45 46 47 48 49 + 50 51 52 53 54 55 56 57 58 59 + 60 61 62 63 64 65 66 67 68 69 + 70 71 72 73 74 75 76 77 78 79 + 80 81 82 83 84 85 86 87 88 89 + 90 91 92 93 94 95 96 97 98 99 + 100>; + default-brightness-level = <50>; + status = "disabled"; + }; + + leds { + compatible = "gpio-leds"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_gpio_leds>; + + user_led: user { + label = "Heartbeat"; + gpios = ; + linux,default-trigger = "heartbeat"; + }; + }; + + regulators { + reg_2v5: regulator { + compatible = "regulator-fixed"; + reg = <1>; + regulator-name = "2V5"; + regulator-min-microvolt = <2500000>; + regulator-max-microvolt = <2500000>; + regulator-always-on; + }; + + reg_3v3: regulator { + compatible = "regulator-fixed"; + reg = <2>; + regulator-name = "3V3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + }; + + reg_lcd0_pwr: regulator-lcd0-power { + compatible = "regulator-fixed"; + regulator-name = "LCD0 RESET"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_lcd0_pwr>; + gpio = ; + enable-active-high; + regulator-boot-on; + regulator-always-on; + }; + }; + + sound { + compatible = "fsl,imx-audio-sgtl5000"; + model = "sgtl5000-audio"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_ssi1>; + ssi-controller = <&ssi1>; + audio-codec = <&sgtl5000>; + audio-routing = + "MIC_IN", "Mic Jack", + "Mic Jack", "Mic Bias", + "Headphone Jack", "HP_OUT"; + mux-int-port = <1>; + mux-ext-port = <5>; + status = "okay"; + }; +}; + +TX_LCD { +/* + * The node/alias 'display' is needed for U-Boot to be able to show a + * logo/splash image at boot time. It needs to include 'display-timings' + * as direct sub-node. + * + * Other naming is only needed for the NXP/Freescale non-mainline + * compliant/proprietary display driver in their Yocto 4.1 Kernel + * implementation. + */ + compatible = "fsl,lcd"; + ipu_id = <0>; + disp_id = <0>; + default_ifmt = "RGB565"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_ipu1>; + status = "disabled"; + display-timings { + VGA { + clock-frequency = <25200000>; + hactive = <640>; + vactive = <480>; + hback-porch = <48>; + hsync-len = <96>; + hfront-porch = <16>; + vback-porch = <31>; + vsync-len = <2>; + vfront-porch = <12>; + hsync-active = <0>; + vsync-active = <0>; + de-active = <1>; + pixelclk-active = <0>; + }; + + ETV570 { + clock-frequency = <25200000>; + hactive = <640>; + vactive = <480>; + hback-porch = <114>; + hsync-len = <30>; + hfront-porch = <16>; + vback-porch = <32>; + vsync-len = <3>; + vfront-porch = <10>; + hsync-active = <0>; + vsync-active = <0>; + de-active = <1>; + pixelclk-active = <0>; + }; + + ET0350 { + clock-frequency = <6413760>; + hactive = <320>; + vactive = <240>; + hback-porch = <34>; + hsync-len = <34>; + hfront-porch = <20>; + vback-porch = <15>; + vsync-len = <3>; + vfront-porch = <4>; + hsync-active = <0>; + vsync-active = <0>; + de-active = <1>; + pixelclk-active = <0>; + }; + + ET0430 { + clock-frequency = <9009000>; + hactive = <480>; + vactive = <272>; + hback-porch = <2>; + hsync-len = <41>; + hfront-porch = <2>; + vback-porch = <2>; + vsync-len = <10>; + vfront-porch = <2>; + hsync-active = <0>; + vsync-active = <0>; + de-active = <1>; + pixelclk-active = <1>; + }; + + ET0500 { + clock-frequency = <33264000>; + hactive = <800>; + vactive = <480>; + hback-porch = <88>; + hsync-len = <128>; + hfront-porch = <40>; + vback-porch = <33>; + vsync-len = <2>; + vfront-porch = <10>; + hsync-active = <0>; + vsync-active = <0>; + de-active = <1>; + pixelclk-active = <0>; + }; + + ET0700 { /* same as ET0500 */ + clock-frequency = <33264000>; + hactive = <800>; + vactive = <480>; + hback-porch = <88>; + hsync-len = <128>; + hfront-porch = <40>; + vback-porch = <33>; + vsync-len = <2>; + vfront-porch = <10>; + hsync-active = <0>; + vsync-active = <0>; + de-active = <1>; + pixelclk-active = <0>; + }; + + ETQ570 { + clock-frequency = <6596040>; + hactive = <320>; + vactive = <240>; + hback-porch = <38>; + hsync-len = <30>; + hfront-porch = <30>; + vback-porch = <16>; + vsync-len = <3>; + vfront-porch = <4>; + hsync-active = <0>; + vsync-active = <0>; + de-active = <1>; + pixelclk-active = <0>; + }; + }; +}; + +TX_LCD_FB { + compatible = "fsl,mxc_sdc_fb"; + disp_dev = "lcd"; + interface_pix_fmt = "RGB24"; + default_bpp = <16>; + int_clk = <0>; + late_init = <0>; + status = "disabled"; +}; + +TX_I2C { + status = "okay"; + + sgtl5000: sgtl5000@0a { + compatible = "fsl,sgtl5000"; + reg = <0x0a>; + VDDA-supply = <®_2v5>; + VDDIO-supply = <®_3v3>; + clocks = <&mclk>; + }; + + polytouch: edt-ft5x06@38 { + compatible = "edt,edt-ft5x06"; + reg = <0x38>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_edt_ft5x06>; + interrupts-extended = ; + reset-gpios = ; + wake-gpios = ; + linux,wakeup; + }; +}; + +TX_CAN1 { + status = "okay"; +}; + + +TX_PWM { + status = "okay"; +}; + +TX_SD1 { + status = "okay"; +}; + +TX_SSI1 { + status = "okay"; +}; + +TX_UART1 { + status = "okay"; +}; + +TX_UART2 { + status = "okay"; + fsl,uart-has-rtscts; + uart-has-rtscts; +}; + +TX_UART3 { + status = "okay"; +}; + +TX_USBOTG { + status = "okay"; +}; + +TX_USBH { + status = "okay"; +}; + +&iomuxc { + tx6 { + pinctrl_edt_ft5x06: edt-ft5x06grp { + fsl,pins = < + TX_GPIO_PAD148 /* Interrupt */ + TX_GPIO_PAD149 /* Reset */ + TX_GPIO_PAD152 /* Wake */ + >; + }; + + pinctrl_gpio_leds: gpioledsgrp { + fsl,pins = < + TX_GPIO_PAD153 /* LED Heartbeat */ + >; + }; + + pinctrl_lcd0_pwr: lcd0-pwrgrp { + fsl,pins = < + TX_GPIO_PAD150 /* LCD Reset */ + >; + }; + }; +}; diff --git a/recipes-kernel/linux/linux-karo_4.9.11.bb b/recipes-kernel/linux/linux-karo_4.9.11.bb new file mode 100644 index 0000000..0fad9fb --- /dev/null +++ b/recipes-kernel/linux/linux-karo_4.9.11.bb @@ -0,0 +1,63 @@ +# Copyright (C) 2013-2016 Freescale Semiconductor +# Copyright 2017 NXP +# Copyright 2018 kernel concepts GmbH +# Released under the MIT license (see COPYING.MIT for the terms) + +SUMMARY = "Linux Kernel provided and supported by NXP" +DESCRIPTION = "Linux Kernel provided and supported by NXP with focus on \ +i.MX Family Reference Boards. It includes support for many IPs such as GPU, VPU and IPU." + +require recipes-kernel/linux/linux-imx.inc + +SRC_URI = "git://source.codeaurora.org/external/imx/linux-imx;protocol=https;branch=${SRCBRANCH} \ + file://set-enet_ref_clk-to-50-mhz.patch \ + file://edt-ft5x06-make-distinction-between.patch \ + file://edt-ft5x06-fixes.patch \ + file://add-support-for-edt-m12-touch.patch \ + file://ethernet-update-driver.patch \ + file://defconfig \ +" + +DEPENDS += "lzop-native bc-native" + +SRCBRANCH = "imx_4.9.11_1.0.0_ga" +LOCALVERSION = "-1.0.0" +SRCREV = "c27010d99a3d91703ea2d1a3f9630a9dedc3f86f" + +KERNEL_EXTRA_ARGS += "LOADADDR=${UBOOT_ENTRYPOINT}" + +COMPATIBLE_MACHINE = "(tx6[qus]-.*)" + +FILESEXTRAPATHS_prepend = "${THISDIR}/${P}/txbase/${TXBASE}:" + +KERNEL_IMAGETYPE = "uImage" + +# Add NXP binary blob driver for the Vivante GPU to the kernel image. +# Otherwise settings in the Kernel defconfig are actively delete or ignored and +# the required external LKM ([RFS]/lib/modules//extra) is not +# available at all ( exception being if specific images are being "bitbaked" +# like: fsl-image-multimedia-full ) + +# Add Vivante GPU driver support +# Handle Vivante kernel driver setting: +# 0 - machine does not have Vivante GPU driver support +# 1 - machine has Vivante GPU driver support +MACHINE_HAS_VIVANTE_KERNEL_DRIVER_SUPPORT ?= "1" + +# Use Vivante kernel driver module: +# 0 - enable the builtin kernel driver module +# 1 - enable the external kernel module +MACHINE_USES_VIVANTE_KERNEL_DRIVER_MODULE ?= "0" + +# Add TX6 module specific DT file(s) +SRC_URI += "file://imx6qdl-tx6.dtsi;subdir=git/arch/arm/boot/dts \ + file://imx6qdl-tx6-gpio.h;subdir=git/include/dt-bindings/gpio \ + " + +# Add baseboard dtsi file(s) +SRC_URI += "file://txbase-${TXBASE}.dtsi;subdir=git/arch/arm/boot/dts" + +# Add TX6 (machine) specific DTS file(s) +SRC_URI += "file://${TXTYPE}-${TXNVM}-${TXBASE}.dts;subdir=git/arch/arm/boot/dts" + +KERNEL_DEVICETREE = "${TXTYPE}-${TXNVM}-${TXBASE}.dtb" -- 2.39.2