ccimx6ul: Remove remaining files

When removing the machine we ended not removing all files. This removes
all the related ones.

Fixes: e50d808 "ccimx6ul*: Drop unbuildable boards"
Signed-off-by: Otavio Salvador <otavio@ossystems.com.br>
This commit is contained in:
Otavio Salvador 2020-08-21 11:41:12 -03:00
parent 9000d8b388
commit cf2ab8d76c
20 changed files with 0 additions and 1955 deletions

View File

@ -1,42 +0,0 @@
#@TYPE: Machine
#@NAME: ConnecCore 6UL SOM
#@SOC: i.MX6UL
#@DESCRIPTION: Machine configuration for ConnectCore 6UL System-On-Module.
#@MAINTAINER: Alex Gonzalez <alex.gonzalez@digi.com>
MACHINEOVERRIDES =. "mx6:mx6ul:ccimx6ul:use-mainline-bsp:"
include conf/machine/include/imx-base.inc
include conf/machine/include/tune-cortexa7.inc
PREFERRED_PROVIDER_virtual/bootloader = "u-boot-digi"
PREFERRED_PROVIDER_u-boot = "u-boot-digi"
UBOOT_BOOTSCRIPT = "boot.scr"
UBOOT_CONFIG ??= "ccimx6ulstarter1GB ccimx6ulstarter"
UBOOT_CONFIG[ccimx6ulstarter1GB] = "ccimx6ulstarter1GB_defconfig"
UBOOT_CONFIG[ccimx6ulstarter] = "ccimx6ulstarter_defconfig"
MACHINE_EXTRA_RDEPENDS += " \
mtd-utils-ubifs \
"
MACHINE_FEATURES += " wifi bluetooth"
MACHINE_EXTRA_RRECOMMENDS += " \
${@bb.utils.contains('MACHINE_FEATURES', 'wifi', 'kernel-module-qca6564 linux-firmware-qca6564-wifi', '', d)} \
${@bb.utils.contains('MACHINE_FEATURES', 'bluetooth', 'linux-firmware-qca6564-bt', '', d)} \
"
# mkfs.ubifs parameters for boot partition (the one holding kernel and device tree files)
# Max LEB count (-c 255) calculated for a partition of up to 32 MiB considering 128 KiB erase-block size.
MKUBIFS_BOOT_ARGS ?= "-m 2048 -e 126976 -c 255"
# mkfs.ubifs parameters for rootfs partition
# Max LEB count (-c 8191) calculated for a partition of up to 1 GiB considering 128 KiB erase-block size.
MKUBIFS_ARGS ?= "-m 2048 -e 126976 -c 8191"
IMAGE_CLASSES += "image_types_digi"
# Overwrite the defaults in imx-base not to include wic images
IMAGE_FSTYPES = "tar.bz2 ubifs boot.ubifs"

View File

@ -1,25 +0,0 @@
# Copyright (C) 2019 Digi International.
DESCRIPTION = "udev rules for Digi International SOMs"
LICENSE = "MIT"
LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302"
SRC_URI_ccimx6ul = " \
file://81-qcom-wifi.rules \
file://qca6564-init-wifi.sh \
file://81-qcom-bt.rules \
file://qca6564-attach.sh \
"
S = "${WORKDIR}"
do_install_ccimx6ul () {
install -d ${D}${sysconfdir}/udev/rules.d
install -m 0644 ${WORKDIR}/81-qcom-wifi.rules ${D}${sysconfdir}/udev/rules.d/
install -m 0644 ${WORKDIR}/81-qcom-bt.rules ${D}${sysconfdir}/udev/rules.d/
install -d ${D}${sysconfdir}/udev/scripts/
install -m 0755 ${WORKDIR}/qca6564-init-wifi.sh ${D}${sysconfdir}/udev/scripts/
install -m 0755 ${WORKDIR}/qca6564-attach.sh ${D}${sysconfdir}/udev/scripts/
}
COMPATIBLE_MACHINE = "(ccimx6ul)"

View File

@ -1,2 +0,0 @@
# Attach QCA6564 Bluetooth (uart)
SUBSYSTEM=="tty", KERNEL=="ttymxc0", ACTION=="add", RUN="/etc/udev/scripts/qca6564-attach.sh start"

View File

@ -1,2 +0,0 @@
# Load Qualcomm wireless module (sdio)
SUBSYSTEM=="sdio", ACTION=="add", ENV{MODALIAS}=="sdio:c00v0271d050A", RUN="/etc/udev/scripts/qca6564-init-wifi.sh"

View File

@ -1,97 +0,0 @@
#!/bin/sh
#===============================================================================
#
# Copyright (C) 2019 by Digi International Inc.
# All rights reserved.
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License version 2 as published by
# the Free Software Foundation.
#
#
# !Description: Initialize bluetooth hardware
#
#===============================================================================
# Bluetooth power GPIO
BT_EN_QCA_GPIO_NR="137"
# set_gpio_value <gpio_nr> <value>
set_gpio_value() {
local SG_GPIONR="${1}"
local SG_GPIOVAL="${2}"
local SG_GPIOPATH="/sys/class/gpio/gpio${SG_GPIONR}"
[ -d "${SG_GPIOPATH}" ] || printf "%s" "${SG_GPIONR}" > /sys/class/gpio/export
printf out > "${SG_GPIOPATH}/direction" && sleep .2
printf "${SG_GPIOVAL}" > "${SG_GPIOPATH}/value" && sleep .2
[ -d "${SG_GPIOPATH}" ] && printf "%s" "${SG_GPIONR}" > /sys/class/gpio/unexport
}
# powercycle_gpio <gpio_nr>
powercycle_gpio() {
set_gpio_value "${1}" 0
set_gpio_value "${1}" 1
}
set_mac_address() {
# Get MAC address from the device tree. Use a default value if it has not been set.
BT_MACADDR="$(hexdump -ve '1/1 "%02X" ":"' /proc/device-tree/bluetooth/mac-address 2>/dev/null | sed 's/:$//g')"
if [ -z "${BT_MACADDR}" ] || [ "${BT_MACADDR}" = "00:00:00:00:00:00" ]; then
BT_MACADDR="00:04:F3:FF:FF:BB"
fi
# Convert the BT address to the hcitool command format.
# Example: "00:04:F3:11:22:33" coverted to "33 22 11 F3 04 00"
HCI_BT_ADDR="$(echo ${BT_MACADDR} | sed -e 's,^\(..\):\(..\):\(..\):\(..\):\(..\):\(..\)$,\6 \5 \4 \3 \2 \1,g')"
# Up the interface to be able to send hci commands
hciconfig hci0 up || echo "Cannot bring up bluetooth interface after initial attach" || exit 1
# Set the MAC address
hcitool -i hci0 cmd 3F 000B 01 02 06 ${HCI_BT_ADDR} > /dev/null || echo "Unable to set BT MAC Address" || exit 1
# Bring the interface down/up to apply the MAC change
hciconfig hci0 down || echo "Cannot bring down bluetooth interface after setting MAC" || exit 1
hciconfig hci0 up || echo "Cannot bring up bluetooth interface after setting MAC" || exit 1
}
bluetooth_init() {
# Start the Bluetooth driver and bring up the interface
killproc hciattach
powercycle_gpio "${BT_EN_QCA_GPIO_NR}"
hciattach ttymxc0 qualcomm 115200 -t3 flow unused > /dev/null 2>&1 || BT_ERROR="FAIL (hciattach)"
set_mac_address || BT_ERROR="Unable to set MAC address"
}
# Source function library
. /etc/init.d/functions
case "$1" in
start)
if [ -d "/proc/device-tree/bluetooth" ]; then
echo -n "Starting bluetooth hardware: "
bluetooth_init
echo "${BT_ERROR:-done.}"
fi
;;
stop)
if [ -d "/sys/class/bluetooth/hci0" ]; then
echo -n "Stopping bluetooth hardware: "
killproc hciattach
# Power down bluetooth
set_gpio_value "${BT_EN_QCA_GPIO_NR}" 0
echo "done."
fi
;;
restart)
$0 stop
sleep 1
$0 start
;;
*)
echo "Usage: $0 {start|stop|restart}"
exit 1
;;
esac

View File

@ -1,121 +0,0 @@
#!/bin/sh
#
# Copyright (c) 2019 Digi International Inc.
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, you can obtain one at http://mozilla.org/MPL/2.0/.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#
# At this point of the boot (udev script), the system log (syslog) is not
# available yet, so use the kernel log buffer from userspace.
log() {
printf "<$1>qca6564: $2\n" >/dev/kmsg
}
# Do nothing if the module is already loaded
grep -qws 'wlan' /proc/modules && exit 0
FIRMWARE_DIR="/lib/firmware"
MACFILE="${FIRMWARE_DIR}/wlan/wlan_mac.bin"
TMP_MACFILE="$(mktemp -t wlan_mac.XXXXXX)"
# Read the MACs from DeviceTree. We can have up to four wireless interfaces
# The only required one is wlan0 that is mapped with device tree mac address
# without suffix.
for index in $(seq 0 3); do
MAC_ADDR="$(hexdump -ve '1/1 "%02X"' /proc/device-tree/wireless/mac-address${index%0} 2>/dev/null)"
if [ "${index}" = "0" ] && { [ -z "${MAC_ADDR}" ] || [ "${MAC_ADDR}" = "00:00:00:00:00:00" ]; }; then
# Set a default MAC for wlan0
MAC_ADDR="0004F3FFFFFB"
fi
# Add the MAC address to the firmware file with the expected format
echo "Intf${index}MacAddress=${MAC_ADDR}" >> ${TMP_MACFILE}
done
# Override the MAC firmware file only if the MAC file has changed.
if ! cmp -s ${TMP_MACFILE} ${MACFILE}; then
cp ${TMP_MACFILE} ${MACFILE}
fi
rm -f "${TMP_MACFILE}"
OTP_REGION_CODE="$(cat /proc/device-tree/digi,hwid,cert 2>/dev/null | tr -d '\0')"
DTB_REGION_CODE="$(cat /proc/device-tree/wireless/regulatory-domain 2>/dev/null | tr -d '\0')"
US_CODE="0x0"
WW_CODE="0x1"
JP_CODE="0x2"
# Check if the DTB_REGION_CODE is in the list of valid codes,
# if not use the OTP programmed value.
case "${DTB_REGION_CODE}" in
${US_CODE} | ${WW_CODE} | ${JP_CODE})
REGULATORY_DOMAIN="${DTB_REGION_CODE}";;
*)
if [ -n "${DTB_REGION_CODE}" ]; then
log "5" "[WARN] Invalid region code in device tree, using OTP value"
fi
REGULATORY_DOMAIN="${OTP_REGION_CODE}";;
esac
# Create symbolic links to the proper FW files depending on the country region
# Use a sub-shell here to change to firmware directory
(
cd "${FIRMWARE_DIR}"
BDATA_SOURCE="bdwlan30_US.bin"
case "${REGULATORY_DOMAIN}" in
${US_CODE})
log "5" "Setting US wireless region";;
${WW_CODE}|${JP_CODE})
if [ -f "bdwlan30_World.bin" ]; then
log "5" "Setting WW (world wide) wireless region"
BDATA_SOURCE="bdwlan30_World.bin"
else
log "5" "[WARN] No WW (worldwide) board data file, using US"
fi
;;
"")
log "5" "[WARN] region code not found, using US";;
*)
log "5" "[WARN] Invalid region code, using US";;
esac
# We don't want to rewrite NAND every time we boot so only
# change the links if they are wrong.
BDATA_LINK="bdwlan30.bin"
UTFBDATA_LINK="utfbd30.bin"
if [ ! -e "${BDATA_LINK}" ] || ! cmp -s "${BDATA_LINK}" "${BDATA_SOURCE}"; then
ln -sf "${BDATA_SOURCE}" "${BDATA_LINK}"
ln -sf "${BDATA_SOURCE}" "${UTFBDATA_LINK}"
fi
)
# Load the wireless module with the params defined in modprobe.d/qca6564.conf
# and reduce the console log level to avoid debug messages at boot time
LOGLEVEL="$(sed -ne 's,^kernel.printk[^=]*=[[:blank:]]*\(.*\)$,\1,g;T;p' /etc/sysctl.conf 2>/dev/null)"
[ -n "${LOGLEVEL}" ] && sysctl -q -w kernel.printk="${LOGLEVEL}"
modprobe wlan
# Verify the interface is present
if [ -d "/sys/class/net/wlan0" ]; then
# Create 'wlan1' virtual interface
if [ -s "/proc/device-tree/wireless/mac-address1" ] &&
[ -s "/proc/device-tree/wireless/mac-address2" ] &&
[ -s "/proc/device-tree/wireless/mac-address3" ]; then
:
else
echo "[WARN] Using default MAC addresses for virtual interfaces."
fi
iw dev wlan0 interface add wlan1 type __ap
else
log "3" "[ERROR] Loading qca6564 module"
fi

View File

@ -1,4 +0,0 @@
# Load the wlan module with values for SDIO3.0.
options wlan asyncintdelay=0x2 writecccr1=0xf2 writecccr1value=0xf \
writecccr2=0xf1 writecccr2value=0xa8 writecccr3=0xf0 \
writecccr3value=0xa1 writecccr4=0x15 writecccr4value=0x30

View File

@ -1,57 +0,0 @@
# Copyright (C) 2019 Digi International Inc.
SUMMARY = "Qualcomm QCA6564 wireless driver module"
LICENSE = "ISC"
LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/ISC;md5=f3b90e78ea0cffb20bf5cca7947a896d"
# Reference Qualcomm tag/version
PV = "v4.2.89.63+${SRCPV}"
SRCBRANCH = "qca6564/master"
SRCREV = "fef49841fd1b4f3fee3b2193f9927c09d59df7de"
SRC_URI = "\
git://github.com/digi-embedded/qcacld-2.0.git;protocol=git;branch=${SRCBRANCH} \
file://modprobe-qca6564.conf \
"
S = "${WORKDIR}/git"
inherit module
EXTRA_OEMAKE += "CONFIG_LINUX_QCMBR=y WLAN_OPEN_SOURCE=1"
# Explicity state it is not a QC platform, if not the driver will try to remap
# memory that is not allowed in ARMv6
EXTRA_OEMAKE += "CONFIG_NON_QC_PLATFORM=y"
# Flag to compile the debug version (1 - enabled, rest of values - disabled)
EXTRA_OEMAKE += "BUILD_DEBUG_VERSION=0"
# Flags for SDIO interface
EXTRA_OEMAKE += "CONFIG_CLD_HL_SDIO_CORE=y"
do_compile_prepend() {
export BUILD_VER=${PV}
}
do_install_prepend() {
sed -i -e "s/gVhtTxMCS=2/gVhtTxMCS=0/g" ${WORKDIR}/git/firmware_bin/WCNSS_qcom_cfg.ini
}
do_install_append() {
install -d ${D}${sysconfdir}/modprobe.d
install -m 0644 ${WORKDIR}/modprobe-qca6564.conf ${D}${sysconfdir}/modprobe.d/qca6564.conf
install -d ${D}${base_libdir}/firmware/wlan/
install -m 0644 ${WORKDIR}/git/firmware_bin/WCNSS_cfg.dat ${D}${base_libdir}/firmware/wlan/cfg.dat
install -m 0644 ${WORKDIR}/git/firmware_bin/WCNSS_qcom_cfg.ini ${D}${base_libdir}/firmware/wlan/qcom_cfg.ini
sed -i -e "s/gVhtTxMCS=2/gVhtTxMCS=0/g" ${D}${base_libdir}/firmware/wlan/qcom_cfg.ini
}
FILES_${PN} += " \
${sysconfdir}/modprobe.d/qca6564.conf \
${base_libdir}/firmware/wlan/cfg.dat \
${base_libdir}/firmware/wlan/qcom_cfg.ini \
"
RRECOMMENDS_${PN} = "hostapd iw crda wireless-regdb udev-rules-digi"
COMPATIBLE_MACHINE = "(ccimx6ul)"

View File

@ -1,31 +0,0 @@
# Copyright (C) 2019 Digi International Inc.
SUMMARY = "Firmware files for Qualcomm's QCA6564 wireless chip"
SECTION = "base"
LICENSE = "Proprietary"
LIC_FILES_CHKSUM = "file://LICENCE.atheros_firmware;md5=30a14c7823beedac9fa39c64fdd01a13"
SRC_URI = "ftp://ftp1.digi.com/support/digiembeddedyocto/source/${BPN}-${PV}.tar.gz"
SRC_URI[md5sum] = "7400b74881ac499517b6ad761a54f8fc"
SRC_URI[sha256sum] = "be3a56334764e21ee297260b6648075b7fada6f55e24a287a24e7c7d128e27ef"
S = "${WORKDIR}/linux-firmware-qca6564/"
do_install() {
install -d ${D}${base_libdir}/firmware/qca
install -m 0644 nvm_tlv_3.2.bin ${D}${base_libdir}/firmware/qca
install -m 0644 rampatch_tlv_3.2.tlv ${D}${base_libdir}/firmware/qca
install -m 0644 bdwlan30_US.bin ${D}${base_libdir}/firmware
install -m 0644 LICENCE.atheros_firmware ${D}${base_libdir}/firmware
install -m 0644 otp30.bin ${D}${base_libdir}/firmware
install -m 0644 qwlan30.bin ${D}${base_libdir}/firmware
install -m 0644 utf30.bin ${D}${base_libdir}/firmware
}
PACKAGES = "${PN}-bt ${PN}-wifi"
FILES_${PN}-bt = "/lib/firmware/qca"
FILES_${PN}-wifi = "/lib/firmware"
PACKAGE_ARCH = "${MACHINE_ARCH}"
COMPATIBLE_MACHINE = "(ccimx6ul)"

View File

@ -8,12 +8,6 @@ SRC_URI_append_imx6qdl-variscite-som_use-mainline-bsp = " \
file://imx6q-var-som-vsc.dts \
"
SRC_URI_append_ccimx6ul = " \
file://0001-MLK-11719-4-mtd-gpmi-change-the-BCH-layout-setting-f.patch \
file://0002-cpufreq-imx6q-read-OCOTP-through-nvmem-for-imx6ul-im.patch \
file://0003-ARM-dts-imx6ul-use-nvmem-cells-for-cpu-speed-grading.patch \
"
do_configure_prepend_imx6qdl-variscite-som() {
cp ${WORKDIR}/imx6*-var*.dts* ${S}/arch/arm/boot/dts
}

View File

@ -1,552 +0,0 @@
From: Alex Gonzalez <alex.gonzalez@digi.com>
Date: Fri, 24 Aug 2018 18:53:40 +0200
Subject: [PATCH] MLK-11719-4: mtd: gpmi: change the BCH layout setting for
large oob NAND
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The cod change updated the NAND driver BCH ECC layout algorithm to
support large oob size NAND chips(oob > 1024 bytes) and proposed a new
way to set ECC layout.
Current implementation requires each chunk size larger than oob size so
the bad block marker (BBM) can be guaranteed located in data chunk. The
ECC layout always using the unbalanced layout(Ecc for both meta and
Data0 chunk), but for the NAND chips with oob larger than 1k, the driver
cannot support because BCH doesnt support GF 15 for 2K chunk.
The change keeps the data chunk no larger than 1k and adjust the ECC
strength or ECC layout to locate the BBM in data chunk. General idea for
large oob NAND chips is
1.Try all ECC strength from the minimum value required by NAND spec to
the maximum one that works, any ECC makes the BBM locate in data chunk
can be chosen.
2.If none of them works, using separate ECC for meta, which will add one
extra ecc with the same ECC strength as other data chunks. This extra
ECC can guarantee BBM located in data chunk, of course, we need to check
if oob can afford it.
Previous code has two methods for ECC layout setting, the
legacy_set_geometry and set_geometry_by_ecc_info, the difference
between these two methods is, legacy_set_geometry set the chunk size
larger chan oob size and then set the maximum ECC strength that oob can
afford. While the set_geometry_by_ecc_info set chunk size and ECC
strength according to NAND spec. It has been proved that the first
method cannot provide safe ECC strength for some modern NAND chips, so
in current code,
1. Driver read NAND parameters first and then chose the proper ECC
layout setting method.
2. If the oob is large or NAND required data chunk larger than oob size,
chose set_geometry_for_large_oob, otherwise use set_geometry_by_ecc_info
3. legacy_set_geometry only used for some NAND chips does not contains
necessary information. So this is only a backup plan, it is NOT
recommended to use these NAND chips.
Signed-off-by: Han Xu <b45815@freescale.com>
(cherry picked from commit 78e8beff734adb72185405ae2cb55e0097eb96cb)
Signed-off-by: Alex Gonzalez <alex.gonzalez@digi.com>
---
drivers/mtd/nand/raw/gpmi-nand/gpmi-lib.c | 16 +-
drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c | 269 ++++++++++++++++++++++++-----
drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.h | 12 +-
3 files changed, 248 insertions(+), 49 deletions(-)
diff --git a/drivers/mtd/nand/raw/gpmi-nand/gpmi-lib.c b/drivers/mtd/nand/raw/gpmi-nand/gpmi-lib.c
index 88ea2203e263..a4cd9523e220 100644
--- a/drivers/mtd/nand/raw/gpmi-nand/gpmi-lib.c
+++ b/drivers/mtd/nand/raw/gpmi-nand/gpmi-lib.c
@@ -212,7 +212,8 @@ void gpmi_dump_info(struct gpmi_nand_data *this)
"ECC Strength : %u\n"
"Page Size in Bytes : %u\n"
"Metadata Size in Bytes : %u\n"
- "ECC Chunk Size in Bytes: %u\n"
+ "ECC Chunk0 Size in Bytes: %u\n"
+ "ECC Chunkn Size in Bytes: %u\n"
"ECC Chunk Count : %u\n"
"Payload Size in Bytes : %u\n"
"Auxiliary Size in Bytes: %u\n"
@@ -223,7 +224,8 @@ void gpmi_dump_info(struct gpmi_nand_data *this)
geo->ecc_strength,
geo->page_size,
geo->metadata_size,
- geo->ecc_chunk_size,
+ geo->ecc_chunk0_size,
+ geo->ecc_chunkn_size,
geo->ecc_chunk_count,
geo->payload_size,
geo->auxiliary_size,
@@ -238,7 +240,8 @@ int bch_set_geometry(struct gpmi_nand_data *this)
struct resources *r = &this->resources;
struct bch_geometry *bch_geo = &this->bch_geometry;
unsigned int block_count;
- unsigned int block_size;
+ unsigned int block0_size;
+ unsigned int blockn_size;
unsigned int metadata_size;
unsigned int ecc_strength;
unsigned int page_size;
@@ -250,7 +253,8 @@ int bch_set_geometry(struct gpmi_nand_data *this)
return ret;
block_count = bch_geo->ecc_chunk_count - 1;
- block_size = bch_geo->ecc_chunk_size;
+ block0_size = bch_geo->ecc_chunk0_size;
+ blockn_size = bch_geo->ecc_chunkn_size;
metadata_size = bch_geo->metadata_size;
ecc_strength = bch_geo->ecc_strength >> 1;
page_size = bch_geo->page_size;
@@ -277,13 +281,13 @@ int bch_set_geometry(struct gpmi_nand_data *this)
| BF_BCH_FLASH0LAYOUT0_META_SIZE(metadata_size)
| BF_BCH_FLASH0LAYOUT0_ECC0(ecc_strength, this)
| BF_BCH_FLASH0LAYOUT0_GF(gf_len, this)
- | BF_BCH_FLASH0LAYOUT0_DATA0_SIZE(block_size, this),
+ | BF_BCH_FLASH0LAYOUT0_DATA0_SIZE(block0_size, this),
r->bch_regs + HW_BCH_FLASH0LAYOUT0);
writel(BF_BCH_FLASH0LAYOUT1_PAGE_SIZE(page_size)
| BF_BCH_FLASH0LAYOUT1_ECCN(ecc_strength, this)
| BF_BCH_FLASH0LAYOUT1_GF(gf_len, this)
- | BF_BCH_FLASH0LAYOUT1_DATAN_SIZE(block_size, this),
+ | BF_BCH_FLASH0LAYOUT1_DATAN_SIZE(blockn_size, this),
r->bch_regs + HW_BCH_FLASH0LAYOUT1);
/* Set *all* chip selects to use layout 0. */
diff --git a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
index 1c1ebbc82824..bc4a364e5696 100644
--- a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
+++ b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
@@ -179,6 +179,36 @@ static inline bool gpmi_check_ecc(struct gpmi_nand_data *this)
return geo->ecc_strength <= this->devdata->bch_max_ecc_strength;
}
+static inline bool bbm_in_data_chunk(struct gpmi_nand_data *this,
+ unsigned int *chunk_num)
+{
+ struct bch_geometry *geo = &this->bch_geometry;
+ struct mtd_info *mtd = &this->nand.mtd;
+ unsigned int i, j;
+
+ if (geo->ecc_chunk0_size != geo->ecc_chunkn_size) {
+ dev_err(this->dev, "The size of chunk0 must equal to chunkn\n");
+ return false;
+ }
+
+ i = (mtd->writesize * 8 - geo->metadata_size * 8) /
+ (geo->gf_len * geo->ecc_strength +
+ geo->ecc_chunkn_size * 8);
+
+ j = (mtd->writesize * 8 - geo->metadata_size * 8) -
+ (geo->gf_len * geo->ecc_strength +
+ geo->ecc_chunkn_size * 8) * i;
+
+ if (j < geo->ecc_chunkn_size * 8) {
+ *chunk_num = i+1;
+ dev_dbg(this->dev, "Set ecc to %d and bbm in chunk %d\n",
+ geo->ecc_strength, *chunk_num);
+ return true;
+ }
+
+ return false;
+}
+
/*
* If we can get the ECC information from the nand chip, we do not
* need to calculate them ourselves.
@@ -207,13 +237,14 @@ static int set_geometry_by_ecc_info(struct gpmi_nand_data *this,
chip->ecc_strength_ds, chip->ecc_step_ds);
return -EINVAL;
}
- geo->ecc_chunk_size = ecc_step;
- geo->ecc_strength = round_up(ecc_strength, 2);
+ geo->ecc_chunk0_size = chip->ecc_step_ds;
+ geo->ecc_chunkn_size = chip->ecc_step_ds;
+ geo->ecc_strength = round_up(chip->ecc_strength_ds, 2);
if (!gpmi_check_ecc(this))
return -EINVAL;
/* Keep the C >= O */
- if (geo->ecc_chunk_size < mtd->oobsize) {
+ if (geo->ecc_chunkn_size < mtd->oobsize) {
dev_err(this->dev,
"unsupported nand chip. ecc size: %d, oob size : %d\n",
ecc_step, mtd->oobsize);
@@ -223,7 +254,7 @@ static int set_geometry_by_ecc_info(struct gpmi_nand_data *this,
/* The default value, see comment in the legacy_set_geometry(). */
geo->metadata_size = 10;
- geo->ecc_chunk_count = mtd->writesize / geo->ecc_chunk_size;
+ geo->ecc_chunk_count = mtd->writesize / geo->ecc_chunkn_size;
/*
* Now, the NAND chip with 2K page(data chunk is 512byte) shows below:
@@ -295,6 +326,129 @@ static int set_geometry_by_ecc_info(struct gpmi_nand_data *this,
return 0;
}
+static int set_geometry_for_large_oob(struct gpmi_nand_data *this)
+{
+ struct bch_geometry *geo = &this->bch_geometry;
+ struct mtd_info *mtd = &this->nand.mtd;
+ struct nand_chip *chip = mtd->priv;
+ unsigned int block_mark_bit_offset;
+ unsigned int max_ecc;
+ unsigned int bbm_chunk;
+ unsigned int i;
+
+
+ /* sanity check for the minimum ecc nand required */
+ if (!(chip->ecc_strength_ds > 0 && chip->ecc_step_ds > 0))
+ return -EINVAL;
+ geo->ecc_strength = chip->ecc_strength_ds;
+
+ /* check if platform can support this nand */
+ if (!gpmi_check_ecc(this)) {
+ dev_err(this->dev, "unsupported NAND chip, minimum ecc required %d\n"
+ , geo->ecc_strength);
+ return -EINVAL;
+ }
+
+ /* calculate the maximum ecc platform can support*/
+ geo->metadata_size = 10;
+ geo->gf_len = 14;
+ geo->ecc_chunk0_size = 1024;
+ geo->ecc_chunkn_size = 1024;
+ geo->ecc_chunk_count = mtd->writesize / geo->ecc_chunkn_size;
+ max_ecc = min(get_ecc_strength(this),
+ this->devdata->bch_max_ecc_strength);
+
+ /* search a supported ecc strength that makes bbm */
+ /* located in data chunk */
+ geo->ecc_strength = chip->ecc_strength_ds;
+ while (!(geo->ecc_strength > max_ecc)) {
+ if (bbm_in_data_chunk(this, &bbm_chunk))
+ goto geo_setting;
+ geo->ecc_strength += 2;
+ }
+
+ /* if none of them works, keep using the minimum ecc */
+ /* nand required but changing ecc page layout */
+ geo->ecc_strength = chip->ecc_strength_ds;
+ /* add extra ecc for meta data */
+ geo->ecc_chunk0_size = 0;
+ geo->ecc_chunk_count = (mtd->writesize / geo->ecc_chunkn_size) + 1;
+ geo->ecc_for_meta = 1;
+ /* check if oob can afford this extra ecc chunk */
+ if (mtd->oobsize * 8 < geo->metadata_size * 8 +
+ geo->gf_len * geo->ecc_strength
+ * geo->ecc_chunk_count) {
+ dev_err(this->dev, "unsupported NAND chip with new layout\n");
+ return -EINVAL;
+ }
+
+ /* calculate in which chunk bbm located */
+ bbm_chunk = (mtd->writesize * 8 - geo->metadata_size * 8 -
+ geo->gf_len * geo->ecc_strength) /
+ (geo->gf_len * geo->ecc_strength +
+ geo->ecc_chunkn_size * 8) + 1;
+
+geo_setting:
+
+ geo->page_size = mtd->writesize + mtd->oobsize;
+ geo->payload_size = mtd->writesize;
+
+ /*
+ * The auxiliary buffer contains the metadata and the ECC status. The
+ * metadata is padded to the nearest 32-bit boundary. The ECC status
+ * contains one byte for every ECC chunk, and is also padded to the
+ * nearest 32-bit boundary.
+ */
+ geo->auxiliary_status_offset = ALIGN(geo->metadata_size, 4);
+ geo->auxiliary_size = ALIGN(geo->metadata_size, 4)
+ + ALIGN(geo->ecc_chunk_count, 4);
+
+ if (!this->swap_block_mark)
+ return 0;
+
+ /* calculate the number of ecc chunk behind the bbm */
+ i = (mtd->writesize / geo->ecc_chunkn_size) - bbm_chunk + 1;
+
+ block_mark_bit_offset = mtd->writesize * 8 -
+ (geo->ecc_strength * geo->gf_len * (geo->ecc_chunk_count - i)
+ + geo->metadata_size * 8);
+
+ geo->block_mark_byte_offset = block_mark_bit_offset / 8;
+ geo->block_mark_bit_offset = block_mark_bit_offset % 8;
+
+ dev_dbg(this->dev, "BCH Geometry :\n"
+ "GF length : %u\n"
+ "ECC Strength : %u\n"
+ "Page Size in Bytes : %u\n"
+ "Metadata Size in Bytes : %u\n"
+ "ECC Chunk0 Size in Bytes: %u\n"
+ "ECC Chunkn Size in Bytes: %u\n"
+ "ECC Chunk Count : %u\n"
+ "Payload Size in Bytes : %u\n"
+ "Auxiliary Size in Bytes: %u\n"
+ "Auxiliary Status Offset: %u\n"
+ "Block Mark Byte Offset : %u\n"
+ "Block Mark Bit Offset : %u\n"
+ "Block Mark in chunk : %u\n"
+ "Ecc for Meta data : %u\n",
+ geo->gf_len,
+ geo->ecc_strength,
+ geo->page_size,
+ geo->metadata_size,
+ geo->ecc_chunk0_size,
+ geo->ecc_chunkn_size,
+ geo->ecc_chunk_count,
+ geo->payload_size,
+ geo->auxiliary_size,
+ geo->auxiliary_status_offset,
+ geo->block_mark_byte_offset,
+ geo->block_mark_bit_offset,
+ bbm_chunk,
+ geo->ecc_for_meta);
+
+ return 0;
+}
+
static int legacy_set_geometry(struct gpmi_nand_data *this)
{
struct bch_geometry *geo = &this->bch_geometry;
@@ -314,13 +468,15 @@ static int legacy_set_geometry(struct gpmi_nand_data *this)
geo->gf_len = 13;
/* The default for chunk size. */
- geo->ecc_chunk_size = 512;
- while (geo->ecc_chunk_size < mtd->oobsize) {
- geo->ecc_chunk_size *= 2; /* keep C >= O */
+ geo->ecc_chunk0_size = 512;
+ geo->ecc_chunkn_size = 512;
+ while (geo->ecc_chunkn_size < mtd->oobsize) {
+ geo->ecc_chunk0_size *= 2; /* keep C >= O */
+ geo->ecc_chunkn_size *= 2; /* keep C >= O */
geo->gf_len = 14;
}
- geo->ecc_chunk_count = mtd->writesize / geo->ecc_chunk_size;
+ geo->ecc_chunk_count = mtd->writesize / geo->ecc_chunkn_size;
/* We use the same ECC strength for all chunks. */
geo->ecc_strength = get_ecc_strength(this);
@@ -409,22 +565,25 @@ static int legacy_set_geometry(struct gpmi_nand_data *this)
int common_nfc_set_geometry(struct gpmi_nand_data *this)
{
- struct nand_chip *chip = &this->nand;
+ struct mtd_info *mtd = &this->nand.mtd;
+ struct nand_chip *chip = mtd_to_nand(mtd);
- if (chip->ecc.strength > 0 && chip->ecc.size > 0)
- return set_geometry_by_ecc_info(this, chip->ecc.strength,
- chip->ecc.size);
+ if (chip->ecc_strength_ds > this->devdata->bch_max_ecc_strength) {
+ dev_err(this->dev,
+ "unsupported NAND chip, minimum ecc required %d\n"
+ , chip->ecc_strength_ds);
+ return -EINVAL;
+ }
- if ((of_property_read_bool(this->dev->of_node, "fsl,use-minimum-ecc"))
- || legacy_set_geometry(this)) {
- if (!(chip->ecc_strength_ds > 0 && chip->ecc_step_ds > 0))
- return -EINVAL;
+ if (!(chip->ecc_strength_ds > 0 && chip->ecc_step_ds > 0) &&
+ !(mtd->oobsize > 1024))
+ return legacy_set_geometry(this);
- return set_geometry_by_ecc_info(this, chip->ecc_strength_ds,
- chip->ecc_step_ds);
- }
+ if (mtd->oobsize > 1024 || chip->ecc_step_ds < mtd->oobsize)
+ return set_geometry_for_large_oob(this);
- return 0;
+ return set_geometry_by_ecc_info(this, chip->ecc_strength_ds,
+ chip->ecc_step_ds);
}
struct dma_chan *get_dma_chan(struct gpmi_nand_data *this)
@@ -997,7 +1156,8 @@ static int gpmi_ecc_read_page_data(struct nand_chip *chip,
/* Read ECC bytes into our internal raw_buffer */
offset = nfc_geo->metadata_size * 8;
- offset += ((8 * nfc_geo->ecc_chunk_size) + eccbits) * (i + 1);
+ offset += ((8 * nfc_geo->ecc_chunkn_size) + eccbits) *
+ (i + 1);
offset -= eccbits;
bitoffset = offset % 8;
eccbytes = DIV_ROUND_UP(offset + eccbits, 8);
@@ -1034,19 +1194,19 @@ static int gpmi_ecc_read_page_data(struct nand_chip *chip,
if (i == 0) {
/* The first block includes metadata */
flips = nand_check_erased_ecc_chunk(
- buf + i * nfc_geo->ecc_chunk_size,
- nfc_geo->ecc_chunk_size,
- eccbuf, eccbytes,
- this->auxiliary_virt,
- nfc_geo->metadata_size,
- nfc_geo->ecc_strength);
+ buf + i * nfc_geo->ecc_chunkn_size,
+ nfc_geo->ecc_chunkn_size,
+ eccbuf, eccbytes,
+ this->payload_virt,
+ nfc_geo->metadata_size,
+ nfc_geo->ecc_strength);
} else {
flips = nand_check_erased_ecc_chunk(
- buf + i * nfc_geo->ecc_chunk_size,
- nfc_geo->ecc_chunk_size,
- eccbuf, eccbytes,
- NULL, 0,
- nfc_geo->ecc_strength);
+ buf + i * nfc_geo->ecc_chunkn_size,
+ nfc_geo->ecc_chunkn_size,
+ eccbuf, eccbytes,
+ NULL, 0,
+ nfc_geo->ecc_strength);
}
if (flips > 0) {
@@ -1134,9 +1294,24 @@ static int gpmi_ecc_read_subpage(struct mtd_info *mtd, struct nand_chip *chip,
}
}
+ /*
+ * if there is an ECC dedicate for meta:
+ * - need to add an extra ECC size when calculating col and page_size,
+ * if the meta size is NOT zero.
+ *
+ * - chunk0 size need to set to the same size as other chunks,
+ * if the meta size is zero.
+ */
+
meta = geo->metadata_size;
if (first) {
- col = meta + (size + ecc_parity_size) * first;
+ if (geo->ecc_for_meta)
+ col = meta + ecc_parity_size
+ + (size + ecc_parity_size) * first;
+ else
+ col = meta + (size + ecc_parity_size) * first;
+
+ chip->cmdfunc(mtd, NAND_CMD_RNDOUT, col, -1);
meta = 0;
buf = buf + first * size;
}
@@ -1149,21 +1324,37 @@ static int gpmi_ecc_read_subpage(struct mtd_info *mtd, struct nand_chip *chip,
/* change the BCH registers and bch_geometry{} */
n = last - first + 1;
- page_size = meta + (size + ecc_parity_size) * n;
+
+ if (geo->ecc_for_meta && meta)
+ page_size = meta + ecc_parity_size
+ + (size + ecc_parity_size) * n;
+ else
+ page_size = meta + (size + ecc_parity_size) * n;
r1_new &= ~(BM_BCH_FLASH0LAYOUT0_NBLOCKS |
BM_BCH_FLASH0LAYOUT0_META_SIZE);
- r1_new |= BF_BCH_FLASH0LAYOUT0_NBLOCKS(n - 1)
+ r1_new |= BF_BCH_FLASH0LAYOUT0_NBLOCKS(
+ (geo->ecc_for_meta && meta) ? n : n - 1)
| BF_BCH_FLASH0LAYOUT0_META_SIZE(meta);
+
+ /* set chunk0 size if meta size is 0 */
+ if (!meta) {
+ if (GPMI_IS_MX6(this))
+ r1_new &= ~MX6Q_BM_BCH_FLASH0LAYOUT0_DATA0_SIZE;
+ else
+ r1_new &= ~BM_BCH_FLASH0LAYOUT0_DATA0_SIZE;
+ r1_new |= BF_BCH_FLASH0LAYOUT0_DATA0_SIZE(size, this);
+ }
writel(r1_new, bch_regs + HW_BCH_FLASH0LAYOUT0);
r2_new &= ~BM_BCH_FLASH0LAYOUT1_PAGE_SIZE;
r2_new |= BF_BCH_FLASH0LAYOUT1_PAGE_SIZE(page_size);
writel(r2_new, bch_regs + HW_BCH_FLASH0LAYOUT1);
- geo->ecc_chunk_count = n;
+ geo->ecc_chunk_count = (geo->ecc_for_meta && meta) ? n + 1 : n;
geo->payload_size = n * size;
geo->page_size = page_size;
+ geo->metadata_size = meta;
geo->auxiliary_status_offset = ALIGN(meta, 4);
dev_dbg(this->dev, "page:%d(%d:%d)%d, chunk:(%d:%d), BCH PG size:%d\n",
@@ -1386,7 +1577,7 @@ static int gpmi_ecc_read_page_raw(struct mtd_info *mtd,
{
struct gpmi_nand_data *this = nand_get_controller_data(chip);
struct bch_geometry *nfc_geo = &this->bch_geometry;
- int eccsize = nfc_geo->ecc_chunk_size;
+ int eccsize = nfc_geo->ecc_chunkn_size;
int eccbits = nfc_geo->ecc_strength * nfc_geo->gf_len;
u8 *tmp_buf = this->raw_buffer;
size_t src_bit_off;
@@ -1471,7 +1662,7 @@ static int gpmi_ecc_write_page_raw(struct mtd_info *mtd,
{
struct gpmi_nand_data *this = nand_get_controller_data(chip);
struct bch_geometry *nfc_geo = &this->bch_geometry;
- int eccsize = nfc_geo->ecc_chunk_size;
+ int eccsize = nfc_geo->ecc_chunkn_size;
int eccbits = nfc_geo->ecc_strength * nfc_geo->gf_len;
u8 *tmp_buf = this->raw_buffer;
uint8_t *oob = chip->oob_poi;
@@ -1847,7 +2038,7 @@ static int gpmi_init_last(struct gpmi_nand_data *this)
ecc->read_oob_raw = gpmi_ecc_read_oob_raw;
ecc->write_oob_raw = gpmi_ecc_write_oob_raw;
ecc->mode = NAND_ECC_HW;
- ecc->size = bch_geo->ecc_chunk_size;
+ ecc->size = bch_geo->ecc_chunkn_size;
ecc->strength = bch_geo->ecc_strength;
mtd_set_ooblayout(mtd, &gpmi_ooblayout_ops);
diff --git a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.h b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.h
index 69cd0cbde4f2..ef4e57256d30 100644
--- a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.h
+++ b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.h
@@ -30,9 +30,9 @@ struct resources {
* @page_size: The size, in bytes, of a physical page, including
* both data and OOB.
* @metadata_size: The size, in bytes, of the metadata.
- * @ecc_chunk_size: The size, in bytes, of a single ECC chunk. Note
- * the first chunk in the page includes both data and
- * metadata, so it's a bit larger than this value.
+ * @ecc_chunk0_size: The size, in bytes, of a first ECC chunk.
+ * @ecc_chunkn_size: The size, in bytes, of a single ECC chunk after
+ * the first chunk in the page.
* @ecc_chunk_count: The number of ECC chunks in the page,
* @payload_size: The size, in bytes, of the payload buffer.
* @auxiliary_size: The size, in bytes, of the auxiliary buffer.
@@ -42,19 +42,23 @@ struct resources {
* which the underlying physical block mark appears.
* @block_mark_bit_offset: The bit offset into the ECC-based page view at
* which the underlying physical block mark appears.
+ * @ecc_for_meta: The flag to indicate if there is a dedicate ecc
+ * for meta.
*/
struct bch_geometry {
unsigned int gf_len;
unsigned int ecc_strength;
unsigned int page_size;
unsigned int metadata_size;
- unsigned int ecc_chunk_size;
+ unsigned int ecc_chunk0_size;
+ unsigned int ecc_chunkn_size;
unsigned int ecc_chunk_count;
unsigned int payload_size;
unsigned int auxiliary_size;
unsigned int auxiliary_status_offset;
unsigned int block_mark_byte_offset;
unsigned int block_mark_bit_offset;
+ unsigned int ecc_for_meta; /* ECC for meta data */
};
/**

View File

@ -1,113 +0,0 @@
From: Anson Huang <Anson.Huang@nxp.com>
Date: Mon, 8 Oct 2018 14:07:34 +0800
Subject: [PATCH] cpufreq: imx6q: read OCOTP through nvmem for imx6ul/imx6ull
On i.MX6UL/i.MX6ULL, accessing OCOTP directly is wrong because
the ocotp clock needs to be enabled first. Add support for reading
OCOTP through the nvmem API, and keep the old method there to
support old dtb.
Signed-off-by: Anson Huang <Anson.Huang@nxp.com>
Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
(cherry picked from commit 2733fb0d0699246711cf622e0e2faf02a05b69dc)
---
drivers/cpufreq/imx6q-cpufreq.c | 52 +++++++++++++++++++++++++++--------------
1 file changed, 35 insertions(+), 17 deletions(-)
diff --git a/drivers/cpufreq/imx6q-cpufreq.c b/drivers/cpufreq/imx6q-cpufreq.c
index b2ff423ad7f8..8cfee0ab804b 100644
--- a/drivers/cpufreq/imx6q-cpufreq.c
+++ b/drivers/cpufreq/imx6q-cpufreq.c
@@ -12,6 +12,7 @@
#include <linux/cpu_cooling.h>
#include <linux/err.h>
#include <linux/module.h>
+#include <linux/nvmem-consumer.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/pm_opp.h>
@@ -290,20 +291,32 @@ static void imx6q_opp_check_speed_grading(struct device *dev)
#define OCOTP_CFG3_6ULL_SPEED_792MHZ 0x2
#define OCOTP_CFG3_6ULL_SPEED_900MHZ 0x3
-static void imx6ul_opp_check_speed_grading(struct device *dev)
+static int imx6ul_opp_check_speed_grading(struct device *dev)
{
- struct device_node *np;
- void __iomem *base;
u32 val;
+ int ret = 0;
- np = of_find_compatible_node(NULL, NULL, "fsl,imx6ul-ocotp");
- if (!np)
- return;
+ if (of_find_property(dev->of_node, "nvmem-cells", NULL)) {
+ ret = nvmem_cell_read_u32(dev, "speed_grade", &val);
+ if (ret)
+ return ret;
+ } else {
+ struct device_node *np;
+ void __iomem *base;
+
+ np = of_find_compatible_node(NULL, NULL, "fsl,imx6ul-ocotp");
+ if (!np)
+ return -ENOENT;
+
+ base = of_iomap(np, 0);
+ of_node_put(np);
+ if (!base) {
+ dev_err(dev, "failed to map ocotp\n");
+ return -EFAULT;
+ }
- base = of_iomap(np, 0);
- if (!base) {
- dev_err(dev, "failed to map ocotp\n");
- goto put_node;
+ val = readl_relaxed(base + OCOTP_CFG3);
+ iounmap(base);
}
/*
@@ -314,7 +327,6 @@ static void imx6ul_opp_check_speed_grading(struct device *dev)
* 2b'11: 900000000Hz on i.MX6ULL only;
* We need to set the max speed of ARM according to fuse map.
*/
- val = readl_relaxed(base + OCOTP_CFG3);
val >>= OCOTP_CFG3_SPEED_SHIFT;
val &= 0x3;
@@ -334,9 +346,7 @@ static void imx6ul_opp_check_speed_grading(struct device *dev)
dev_warn(dev, "failed to disable 900MHz OPP\n");
}
- iounmap(base);
-put_node:
- of_node_put(np);
+ return ret;
}
static int imx6q_cpufreq_probe(struct platform_device *pdev)
@@ -394,10 +404,18 @@ static int imx6q_cpufreq_probe(struct platform_device *pdev)
}
if (of_machine_is_compatible("fsl,imx6ul") ||
- of_machine_is_compatible("fsl,imx6ull"))
- imx6ul_opp_check_speed_grading(cpu_dev);
- else
+ of_machine_is_compatible("fsl,imx6ull")) {
+ ret = imx6ul_opp_check_speed_grading(cpu_dev);
+ if (ret == -EPROBE_DEFER)
+ return ret;
+ if (ret) {
+ dev_err(cpu_dev, "failed to read ocotp: %d\n",
+ ret);
+ return ret;
+ }
+ } else {
imx6q_opp_check_speed_grading(cpu_dev);
+ }
/* Because we have added the OPPs here, we must free them */
free_opp = true;

View File

@ -1,38 +0,0 @@
From: Anson Huang <Anson.Huang@nxp.com>
Date: Fri, 14 Sep 2018 10:59:21 +0800
Subject: [PATCH] ARM: dts: imx6ul: use nvmem-cells for cpu speed grading
On i.MX6UL, accessing OCOTP directly is wrong because the ocotp clock
needs to be enabled first, so use the nvmem-cells binding instead.
Signed-off-by: Anson Huang <Anson.Huang@nxp.com>
Signed-off-by: Shawn Guo <shawnguo@kernel.org>
(cherry picked from commit 92f0eb08c66a73594cf200e65689e767f7f0da5e)
---
arch/arm/boot/dts/imx6ul.dtsi | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/arch/arm/boot/dts/imx6ul.dtsi b/arch/arm/boot/dts/imx6ul.dtsi
index 6dc0b569acdf..c670d8e4e0a9 100644
--- a/arch/arm/boot/dts/imx6ul.dtsi
+++ b/arch/arm/boot/dts/imx6ul.dtsi
@@ -89,6 +89,8 @@
"pll1_sys";
arm-supply = <&reg_arm>;
soc-supply = <&reg_soc>;
+ nvmem-cells = <&cpu_speed_grade>;
+ nvmem-cell-names = "speed_grade";
};
};
@@ -932,6 +934,10 @@
tempmon_temp_grade: temp-grade@20 {
reg = <0x20 4>;
};
+
+ cpu_speed_grade: speed-grade@10 {
+ reg = <0x10 4>;
+ };
};
lcdif: lcdif@21c8000 {

View File

@ -1,552 +0,0 @@
From: Alex Gonzalez <alex.gonzalez@digi.com>
Date: Fri, 24 Aug 2018 18:53:40 +0200
Subject: [PATCH] MLK-11719-4: mtd: gpmi: change the BCH layout setting for
large oob NAND
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The cod change updated the NAND driver BCH ECC layout algorithm to
support large oob size NAND chips(oob > 1024 bytes) and proposed a new
way to set ECC layout.
Current implementation requires each chunk size larger than oob size so
the bad block marker (BBM) can be guaranteed located in data chunk. The
ECC layout always using the unbalanced layout(Ecc for both meta and
Data0 chunk), but for the NAND chips with oob larger than 1k, the driver
cannot support because BCH doesnt support GF 15 for 2K chunk.
The change keeps the data chunk no larger than 1k and adjust the ECC
strength or ECC layout to locate the BBM in data chunk. General idea for
large oob NAND chips is
1.Try all ECC strength from the minimum value required by NAND spec to
the maximum one that works, any ECC makes the BBM locate in data chunk
can be chosen.
2.If none of them works, using separate ECC for meta, which will add one
extra ecc with the same ECC strength as other data chunks. This extra
ECC can guarantee BBM located in data chunk, of course, we need to check
if oob can afford it.
Previous code has two methods for ECC layout setting, the
legacy_set_geometry and set_geometry_by_ecc_info, the difference
between these two methods is, legacy_set_geometry set the chunk size
larger chan oob size and then set the maximum ECC strength that oob can
afford. While the set_geometry_by_ecc_info set chunk size and ECC
strength according to NAND spec. It has been proved that the first
method cannot provide safe ECC strength for some modern NAND chips, so
in current code,
1. Driver read NAND parameters first and then chose the proper ECC
layout setting method.
2. If the oob is large or NAND required data chunk larger than oob size,
chose set_geometry_for_large_oob, otherwise use set_geometry_by_ecc_info
3. legacy_set_geometry only used for some NAND chips does not contains
necessary information. So this is only a backup plan, it is NOT
recommended to use these NAND chips.
Signed-off-by: Han Xu <b45815@freescale.com>
(cherry picked from commit 78e8beff734adb72185405ae2cb55e0097eb96cb)
Signed-off-by: Alex Gonzalez <alex.gonzalez@digi.com>
---
drivers/mtd/nand/raw/gpmi-nand/gpmi-lib.c | 16 +-
drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c | 269 ++++++++++++++++++++++++-----
drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.h | 12 +-
3 files changed, 248 insertions(+), 49 deletions(-)
diff --git a/drivers/mtd/nand/raw/gpmi-nand/gpmi-lib.c b/drivers/mtd/nand/raw/gpmi-nand/gpmi-lib.c
index a4768df5083f..72ace805f8c6 100644
--- a/drivers/mtd/nand/raw/gpmi-nand/gpmi-lib.c
+++ b/drivers/mtd/nand/raw/gpmi-nand/gpmi-lib.c
@@ -213,7 +213,8 @@ void gpmi_dump_info(struct gpmi_nand_data *this)
"ECC Strength : %u\n"
"Page Size in Bytes : %u\n"
"Metadata Size in Bytes : %u\n"
- "ECC Chunk Size in Bytes: %u\n"
+ "ECC Chunk0 Size in Bytes: %u\n"
+ "ECC Chunkn Size in Bytes: %u\n"
"ECC Chunk Count : %u\n"
"Payload Size in Bytes : %u\n"
"Auxiliary Size in Bytes: %u\n"
@@ -224,7 +225,8 @@ void gpmi_dump_info(struct gpmi_nand_data *this)
geo->ecc_strength,
geo->page_size,
geo->metadata_size,
- geo->ecc_chunk_size,
+ geo->ecc_chunk0_size,
+ geo->ecc_chunkn_size,
geo->ecc_chunk_count,
geo->payload_size,
geo->auxiliary_size,
@@ -239,7 +241,8 @@ int bch_set_geometry(struct gpmi_nand_data *this)
struct resources *r = &this->resources;
struct bch_geometry *bch_geo = &this->bch_geometry;
unsigned int block_count;
- unsigned int block_size;
+ unsigned int block0_size;
+ unsigned int blockn_size;
unsigned int metadata_size;
unsigned int ecc_strength;
unsigned int page_size;
@@ -251,7 +254,8 @@ int bch_set_geometry(struct gpmi_nand_data *this)
return ret;
block_count = bch_geo->ecc_chunk_count - 1;
- block_size = bch_geo->ecc_chunk_size;
+ block0_size = bch_geo->ecc_chunk0_size;
+ blockn_size = bch_geo->ecc_chunkn_size;
metadata_size = bch_geo->metadata_size;
ecc_strength = bch_geo->ecc_strength >> 1;
page_size = bch_geo->page_size;
@@ -276,13 +280,13 @@ int bch_set_geometry(struct gpmi_nand_data *this)
| BF_BCH_FLASH0LAYOUT0_META_SIZE(metadata_size)
| BF_BCH_FLASH0LAYOUT0_ECC0(ecc_strength, this)
| BF_BCH_FLASH0LAYOUT0_GF(gf_len, this)
- | BF_BCH_FLASH0LAYOUT0_DATA0_SIZE(block_size, this),
+ | BF_BCH_FLASH0LAYOUT0_DATA0_SIZE(block0_size, this),
r->bch_regs + HW_BCH_FLASH0LAYOUT0);
writel(BF_BCH_FLASH0LAYOUT1_PAGE_SIZE(page_size)
| BF_BCH_FLASH0LAYOUT1_ECCN(ecc_strength, this)
| BF_BCH_FLASH0LAYOUT1_GF(gf_len, this)
- | BF_BCH_FLASH0LAYOUT1_DATAN_SIZE(block_size, this),
+ | BF_BCH_FLASH0LAYOUT1_DATAN_SIZE(blockn_size, this),
r->bch_regs + HW_BCH_FLASH0LAYOUT1);
/* Set *all* chip selects to use layout 0. */
diff --git a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
index ed405c9434fe..0dd9d586a934 100644
--- a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
+++ b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
@@ -179,6 +179,36 @@ static inline bool gpmi_check_ecc(struct gpmi_nand_data *this)
return geo->ecc_strength <= this->devdata->bch_max_ecc_strength;
}
+static inline bool bbm_in_data_chunk(struct gpmi_nand_data *this,
+ unsigned int *chunk_num)
+{
+ struct bch_geometry *geo = &this->bch_geometry;
+ struct mtd_info *mtd = &this->nand.mtd;
+ unsigned int i, j;
+
+ if (geo->ecc_chunk0_size != geo->ecc_chunkn_size) {
+ dev_err(this->dev, "The size of chunk0 must equal to chunkn\n");
+ return false;
+ }
+
+ i = (mtd->writesize * 8 - geo->metadata_size * 8) /
+ (geo->gf_len * geo->ecc_strength +
+ geo->ecc_chunkn_size * 8);
+
+ j = (mtd->writesize * 8 - geo->metadata_size * 8) -
+ (geo->gf_len * geo->ecc_strength +
+ geo->ecc_chunkn_size * 8) * i;
+
+ if (j < geo->ecc_chunkn_size * 8) {
+ *chunk_num = i+1;
+ dev_dbg(this->dev, "Set ecc to %d and bbm in chunk %d\n",
+ geo->ecc_strength, *chunk_num);
+ return true;
+ }
+
+ return false;
+}
+
/*
* If we can get the ECC information from the nand chip, we do not
* need to calculate them ourselves.
@@ -207,13 +237,14 @@ static int set_geometry_by_ecc_info(struct gpmi_nand_data *this,
chip->ecc_strength_ds, chip->ecc_step_ds);
return -EINVAL;
}
- geo->ecc_chunk_size = ecc_step;
- geo->ecc_strength = round_up(ecc_strength, 2);
+ geo->ecc_chunk0_size = chip->ecc_step_ds;
+ geo->ecc_chunkn_size = chip->ecc_step_ds;
+ geo->ecc_strength = round_up(chip->ecc_strength_ds, 2);
if (!gpmi_check_ecc(this))
return -EINVAL;
/* Keep the C >= O */
- if (geo->ecc_chunk_size < mtd->oobsize) {
+ if (geo->ecc_chunkn_size < mtd->oobsize) {
dev_err(this->dev,
"unsupported nand chip. ecc size: %d, oob size : %d\n",
ecc_step, mtd->oobsize);
@@ -223,7 +254,7 @@ static int set_geometry_by_ecc_info(struct gpmi_nand_data *this,
/* The default value, see comment in the legacy_set_geometry(). */
geo->metadata_size = 10;
- geo->ecc_chunk_count = mtd->writesize / geo->ecc_chunk_size;
+ geo->ecc_chunk_count = mtd->writesize / geo->ecc_chunkn_size;
/*
* Now, the NAND chip with 2K page(data chunk is 512byte) shows below:
@@ -295,6 +326,129 @@ static int set_geometry_by_ecc_info(struct gpmi_nand_data *this,
return 0;
}
+static int set_geometry_for_large_oob(struct gpmi_nand_data *this)
+{
+ struct bch_geometry *geo = &this->bch_geometry;
+ struct mtd_info *mtd = &this->nand.mtd;
+ struct nand_chip *chip = mtd->priv;
+ unsigned int block_mark_bit_offset;
+ unsigned int max_ecc;
+ unsigned int bbm_chunk;
+ unsigned int i;
+
+
+ /* sanity check for the minimum ecc nand required */
+ if (!(chip->ecc_strength_ds > 0 && chip->ecc_step_ds > 0))
+ return -EINVAL;
+ geo->ecc_strength = chip->ecc_strength_ds;
+
+ /* check if platform can support this nand */
+ if (!gpmi_check_ecc(this)) {
+ dev_err(this->dev, "unsupported NAND chip, minimum ecc required %d\n"
+ , geo->ecc_strength);
+ return -EINVAL;
+ }
+
+ /* calculate the maximum ecc platform can support*/
+ geo->metadata_size = 10;
+ geo->gf_len = 14;
+ geo->ecc_chunk0_size = 1024;
+ geo->ecc_chunkn_size = 1024;
+ geo->ecc_chunk_count = mtd->writesize / geo->ecc_chunkn_size;
+ max_ecc = min(get_ecc_strength(this),
+ this->devdata->bch_max_ecc_strength);
+
+ /* search a supported ecc strength that makes bbm */
+ /* located in data chunk */
+ geo->ecc_strength = chip->ecc_strength_ds;
+ while (!(geo->ecc_strength > max_ecc)) {
+ if (bbm_in_data_chunk(this, &bbm_chunk))
+ goto geo_setting;
+ geo->ecc_strength += 2;
+ }
+
+ /* if none of them works, keep using the minimum ecc */
+ /* nand required but changing ecc page layout */
+ geo->ecc_strength = chip->ecc_strength_ds;
+ /* add extra ecc for meta data */
+ geo->ecc_chunk0_size = 0;
+ geo->ecc_chunk_count = (mtd->writesize / geo->ecc_chunkn_size) + 1;
+ geo->ecc_for_meta = 1;
+ /* check if oob can afford this extra ecc chunk */
+ if (mtd->oobsize * 8 < geo->metadata_size * 8 +
+ geo->gf_len * geo->ecc_strength
+ * geo->ecc_chunk_count) {
+ dev_err(this->dev, "unsupported NAND chip with new layout\n");
+ return -EINVAL;
+ }
+
+ /* calculate in which chunk bbm located */
+ bbm_chunk = (mtd->writesize * 8 - geo->metadata_size * 8 -
+ geo->gf_len * geo->ecc_strength) /
+ (geo->gf_len * geo->ecc_strength +
+ geo->ecc_chunkn_size * 8) + 1;
+
+geo_setting:
+
+ geo->page_size = mtd->writesize + mtd->oobsize;
+ geo->payload_size = mtd->writesize;
+
+ /*
+ * The auxiliary buffer contains the metadata and the ECC status. The
+ * metadata is padded to the nearest 32-bit boundary. The ECC status
+ * contains one byte for every ECC chunk, and is also padded to the
+ * nearest 32-bit boundary.
+ */
+ geo->auxiliary_status_offset = ALIGN(geo->metadata_size, 4);
+ geo->auxiliary_size = ALIGN(geo->metadata_size, 4)
+ + ALIGN(geo->ecc_chunk_count, 4);
+
+ if (!this->swap_block_mark)
+ return 0;
+
+ /* calculate the number of ecc chunk behind the bbm */
+ i = (mtd->writesize / geo->ecc_chunkn_size) - bbm_chunk + 1;
+
+ block_mark_bit_offset = mtd->writesize * 8 -
+ (geo->ecc_strength * geo->gf_len * (geo->ecc_chunk_count - i)
+ + geo->metadata_size * 8);
+
+ geo->block_mark_byte_offset = block_mark_bit_offset / 8;
+ geo->block_mark_bit_offset = block_mark_bit_offset % 8;
+
+ dev_dbg(this->dev, "BCH Geometry :\n"
+ "GF length : %u\n"
+ "ECC Strength : %u\n"
+ "Page Size in Bytes : %u\n"
+ "Metadata Size in Bytes : %u\n"
+ "ECC Chunk0 Size in Bytes: %u\n"
+ "ECC Chunkn Size in Bytes: %u\n"
+ "ECC Chunk Count : %u\n"
+ "Payload Size in Bytes : %u\n"
+ "Auxiliary Size in Bytes: %u\n"
+ "Auxiliary Status Offset: %u\n"
+ "Block Mark Byte Offset : %u\n"
+ "Block Mark Bit Offset : %u\n"
+ "Block Mark in chunk : %u\n"
+ "Ecc for Meta data : %u\n",
+ geo->gf_len,
+ geo->ecc_strength,
+ geo->page_size,
+ geo->metadata_size,
+ geo->ecc_chunk0_size,
+ geo->ecc_chunkn_size,
+ geo->ecc_chunk_count,
+ geo->payload_size,
+ geo->auxiliary_size,
+ geo->auxiliary_status_offset,
+ geo->block_mark_byte_offset,
+ geo->block_mark_bit_offset,
+ bbm_chunk,
+ geo->ecc_for_meta);
+
+ return 0;
+}
+
static int legacy_set_geometry(struct gpmi_nand_data *this)
{
struct bch_geometry *geo = &this->bch_geometry;
@@ -314,13 +468,15 @@ static int legacy_set_geometry(struct gpmi_nand_data *this)
geo->gf_len = 13;
/* The default for chunk size. */
- geo->ecc_chunk_size = 512;
- while (geo->ecc_chunk_size < mtd->oobsize) {
- geo->ecc_chunk_size *= 2; /* keep C >= O */
+ geo->ecc_chunk0_size = 512;
+ geo->ecc_chunkn_size = 512;
+ while (geo->ecc_chunkn_size < mtd->oobsize) {
+ geo->ecc_chunk0_size *= 2; /* keep C >= O */
+ geo->ecc_chunkn_size *= 2; /* keep C >= O */
geo->gf_len = 14;
}
- geo->ecc_chunk_count = mtd->writesize / geo->ecc_chunk_size;
+ geo->ecc_chunk_count = mtd->writesize / geo->ecc_chunkn_size;
/* We use the same ECC strength for all chunks. */
geo->ecc_strength = get_ecc_strength(this);
@@ -409,22 +565,25 @@ static int legacy_set_geometry(struct gpmi_nand_data *this)
int common_nfc_set_geometry(struct gpmi_nand_data *this)
{
- struct nand_chip *chip = &this->nand;
+ struct mtd_info *mtd = &this->nand.mtd;
+ struct nand_chip *chip = mtd_to_nand(mtd);
- if (chip->ecc.strength > 0 && chip->ecc.size > 0)
- return set_geometry_by_ecc_info(this, chip->ecc.strength,
- chip->ecc.size);
+ if (chip->ecc_strength_ds > this->devdata->bch_max_ecc_strength) {
+ dev_err(this->dev,
+ "unsupported NAND chip, minimum ecc required %d\n"
+ , chip->ecc_strength_ds);
+ return -EINVAL;
+ }
- if ((of_property_read_bool(this->dev->of_node, "fsl,use-minimum-ecc"))
- || legacy_set_geometry(this)) {
- if (!(chip->ecc_strength_ds > 0 && chip->ecc_step_ds > 0))
- return -EINVAL;
+ if (!(chip->ecc_strength_ds > 0 && chip->ecc_step_ds > 0) &&
+ !(mtd->oobsize > 1024))
+ return legacy_set_geometry(this);
- return set_geometry_by_ecc_info(this, chip->ecc_strength_ds,
- chip->ecc_step_ds);
- }
+ if (mtd->oobsize > 1024 || chip->ecc_step_ds < mtd->oobsize)
+ return set_geometry_for_large_oob(this);
- return 0;
+ return set_geometry_by_ecc_info(this, chip->ecc_strength_ds,
+ chip->ecc_step_ds);
}
struct dma_chan *get_dma_chan(struct gpmi_nand_data *this)
@@ -991,7 +1150,8 @@ static int gpmi_ecc_read_page_data(struct nand_chip *chip,
/* Read ECC bytes into our internal raw_buffer */
offset = nfc_geo->metadata_size * 8;
- offset += ((8 * nfc_geo->ecc_chunk_size) + eccbits) * (i + 1);
+ offset += ((8 * nfc_geo->ecc_chunkn_size) + eccbits) *
+ (i + 1);
offset -= eccbits;
bitoffset = offset % 8;
eccbytes = DIV_ROUND_UP(offset + eccbits, 8);
@@ -1028,19 +1188,19 @@ static int gpmi_ecc_read_page_data(struct nand_chip *chip,
if (i == 0) {
/* The first block includes metadata */
flips = nand_check_erased_ecc_chunk(
- buf + i * nfc_geo->ecc_chunk_size,
- nfc_geo->ecc_chunk_size,
- eccbuf, eccbytes,
- this->auxiliary_virt,
- nfc_geo->metadata_size,
- nfc_geo->ecc_strength);
+ buf + i * nfc_geo->ecc_chunkn_size,
+ nfc_geo->ecc_chunkn_size,
+ eccbuf, eccbytes,
+ this->payload_virt,
+ nfc_geo->metadata_size,
+ nfc_geo->ecc_strength);
} else {
flips = nand_check_erased_ecc_chunk(
- buf + i * nfc_geo->ecc_chunk_size,
- nfc_geo->ecc_chunk_size,
- eccbuf, eccbytes,
- NULL, 0,
- nfc_geo->ecc_strength);
+ buf + i * nfc_geo->ecc_chunkn_size,
+ nfc_geo->ecc_chunkn_size,
+ eccbuf, eccbytes,
+ NULL, 0,
+ nfc_geo->ecc_strength);
}
if (flips > 0) {
@@ -1128,9 +1288,24 @@ static int gpmi_ecc_read_subpage(struct nand_chip *chip, uint32_t offs,
}
}
+ /*
+ * if there is an ECC dedicate for meta:
+ * - need to add an extra ECC size when calculating col and page_size,
+ * if the meta size is NOT zero.
+ *
+ * - chunk0 size need to set to the same size as other chunks,
+ * if the meta size is zero.
+ */
+
meta = geo->metadata_size;
if (first) {
- col = meta + (size + ecc_parity_size) * first;
+ if (geo->ecc_for_meta)
+ col = meta + ecc_parity_size
+ + (size + ecc_parity_size) * first;
+ else
+ col = meta + (size + ecc_parity_size) * first;
+
+ chip->legacy.cmdfunc(chip, NAND_CMD_RNDOUT, col, -1);
meta = 0;
buf = buf + first * size;
}
@@ -1143,21 +1318,37 @@ static int gpmi_ecc_read_subpage(struct nand_chip *chip, uint32_t offs,
/* change the BCH registers and bch_geometry{} */
n = last - first + 1;
- page_size = meta + (size + ecc_parity_size) * n;
+
+ if (geo->ecc_for_meta && meta)
+ page_size = meta + ecc_parity_size
+ + (size + ecc_parity_size) * n;
+ else
+ page_size = meta + (size + ecc_parity_size) * n;
r1_new &= ~(BM_BCH_FLASH0LAYOUT0_NBLOCKS |
BM_BCH_FLASH0LAYOUT0_META_SIZE);
- r1_new |= BF_BCH_FLASH0LAYOUT0_NBLOCKS(n - 1)
+ r1_new |= BF_BCH_FLASH0LAYOUT0_NBLOCKS(
+ (geo->ecc_for_meta && meta) ? n : n - 1)
| BF_BCH_FLASH0LAYOUT0_META_SIZE(meta);
+
+ /* set chunk0 size if meta size is 0 */
+ if (!meta) {
+ if (GPMI_IS_MX6(this))
+ r1_new &= ~MX6Q_BM_BCH_FLASH0LAYOUT0_DATA0_SIZE;
+ else
+ r1_new &= ~BM_BCH_FLASH0LAYOUT0_DATA0_SIZE;
+ r1_new |= BF_BCH_FLASH0LAYOUT0_DATA0_SIZE(size, this);
+ }
writel(r1_new, bch_regs + HW_BCH_FLASH0LAYOUT0);
r2_new &= ~BM_BCH_FLASH0LAYOUT1_PAGE_SIZE;
r2_new |= BF_BCH_FLASH0LAYOUT1_PAGE_SIZE(page_size);
writel(r2_new, bch_regs + HW_BCH_FLASH0LAYOUT1);
- geo->ecc_chunk_count = n;
+ geo->ecc_chunk_count = (geo->ecc_for_meta && meta) ? n + 1 : n;
geo->payload_size = n * size;
geo->page_size = page_size;
+ geo->metadata_size = meta;
geo->auxiliary_status_offset = ALIGN(meta, 4);
dev_dbg(this->dev, "page:%d(%d:%d)%d, chunk:(%d:%d), BCH PG size:%d\n",
@@ -1381,7 +1572,7 @@ static int gpmi_ecc_read_page_raw(struct nand_chip *chip, uint8_t *buf,
struct mtd_info *mtd = nand_to_mtd(chip);
struct gpmi_nand_data *this = nand_get_controller_data(chip);
struct bch_geometry *nfc_geo = &this->bch_geometry;
- int eccsize = nfc_geo->ecc_chunk_size;
+ int eccsize = nfc_geo->ecc_chunkn_size;
int eccbits = nfc_geo->ecc_strength * nfc_geo->gf_len;
u8 *tmp_buf = this->raw_buffer;
size_t src_bit_off;
@@ -1465,7 +1656,7 @@ static int gpmi_ecc_write_page_raw(struct nand_chip *chip, const uint8_t *buf,
struct mtd_info *mtd = nand_to_mtd(chip);
struct gpmi_nand_data *this = nand_get_controller_data(chip);
struct bch_geometry *nfc_geo = &this->bch_geometry;
- int eccsize = nfc_geo->ecc_chunk_size;
+ int eccsize = nfc_geo->ecc_chunkn_size;
int eccbits = nfc_geo->ecc_strength * nfc_geo->gf_len;
u8 *tmp_buf = this->raw_buffer;
uint8_t *oob = chip->oob_poi;
@@ -1845,7 +2036,7 @@ static int gpmi_init_last(struct gpmi_nand_data *this)
ecc->read_oob_raw = gpmi_ecc_read_oob_raw;
ecc->write_oob_raw = gpmi_ecc_write_oob_raw;
ecc->mode = NAND_ECC_HW;
- ecc->size = bch_geo->ecc_chunk_size;
+ ecc->size = bch_geo->ecc_chunkn_size;
ecc->strength = bch_geo->ecc_strength;
mtd_set_ooblayout(mtd, &gpmi_ooblayout_ops);
diff --git a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.h b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.h
index d0b79bac2728..4a9dab7c0859 100644
--- a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.h
+++ b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.h
@@ -30,9 +30,9 @@ struct resources {
* @page_size: The size, in bytes, of a physical page, including
* both data and OOB.
* @metadata_size: The size, in bytes, of the metadata.
- * @ecc_chunk_size: The size, in bytes, of a single ECC chunk. Note
- * the first chunk in the page includes both data and
- * metadata, so it's a bit larger than this value.
+ * @ecc_chunk0_size: The size, in bytes, of a first ECC chunk.
+ * @ecc_chunkn_size: The size, in bytes, of a single ECC chunk after
+ * the first chunk in the page.
* @ecc_chunk_count: The number of ECC chunks in the page,
* @payload_size: The size, in bytes, of the payload buffer.
* @auxiliary_size: The size, in bytes, of the auxiliary buffer.
@@ -42,19 +42,23 @@ struct resources {
* which the underlying physical block mark appears.
* @block_mark_bit_offset: The bit offset into the ECC-based page view at
* which the underlying physical block mark appears.
+ * @ecc_for_meta: The flag to indicate if there is a dedicate ecc
+ * for meta.
*/
struct bch_geometry {
unsigned int gf_len;
unsigned int ecc_strength;
unsigned int page_size;
unsigned int metadata_size;
- unsigned int ecc_chunk_size;
+ unsigned int ecc_chunk0_size;
+ unsigned int ecc_chunkn_size;
unsigned int ecc_chunk_count;
unsigned int payload_size;
unsigned int auxiliary_size;
unsigned int auxiliary_status_offset;
unsigned int block_mark_byte_offset;
unsigned int block_mark_bit_offset;
+ unsigned int ecc_for_meta; /* ECC for meta data */
};
/**

View File

@ -1,32 +0,0 @@
From: Alex Gonzalez <alex.gonzalez@digi.com>
Date: Fri, 14 Sep 2018 12:32:41 +0200
Subject: [PATCH] ARM: dts: imx6ul: ccimx6ulsom: Add empty wireless and
bluetooth placeholders
The vendor provided U-Boot will use these empty nodes to populate the
MAC addresses used for both the Bluetooth and the Wireless chips.
Upstream-Status: Inappropriate [vendor specific]
Signed-off-by: Alex Gonzalez <alex.gonzalez@digi.com>
---
arch/arm/boot/dts/imx6ul-ccimx6ulsom.dtsi | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/arch/arm/boot/dts/imx6ul-ccimx6ulsom.dtsi b/arch/arm/boot/dts/imx6ul-ccimx6ulsom.dtsi
index b5781c3656d1..82fa176bf138 100644
--- a/arch/arm/boot/dts/imx6ul-ccimx6ulsom.dtsi
+++ b/arch/arm/boot/dts/imx6ul-ccimx6ulsom.dtsi
@@ -24,6 +24,12 @@
linux,cma-default;
};
};
+
+ bluetooth {
+ };
+
+ wireless {
+ };
};
&adc1 {

View File

@ -1,77 +0,0 @@
From: Alex Gonzalez <alex.gonzalez@digi.com>
Date: Mon, 10 Sep 2018 13:38:40 +0200
Subject: [PATCH] net: wireless: Export regulatory_hint_user()
The QCA6564 driver makes use of this kernel API when built with
the QCA_VENDOR_KERNEL flag.
Signed-off-by: Alex Gonzalez <alex.gonzalez@digi.com>
---
include/net/cfg80211.h | 26 ++++++++++++++++++++++++++
net/wireless/reg.c | 1 +
net/wireless/reg.h | 3 ---
3 files changed, 27 insertions(+), 3 deletions(-)
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index e0c41eb1c860..84d47ac0cea4 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -5111,6 +5111,32 @@ int regulatory_set_wiphy_regd_sync_rtnl(struct wiphy *wiphy,
struct ieee80211_regdomain *rd);
/**
+ * regulatory_hint_user - hint to the wireless core a regulatory domain
+ * which the driver has received from an application
+ * @alpha2: the ISO/IEC 3166 alpha2 the driver claims its regulatory domain
+ * should be in. If @rd is set this should be NULL. Note that if you
+ * set this to NULL you should still set rd->alpha2 to some accepted
+ * alpha2.
+ * @user_reg_hint_type: the type of user regulatory hint.
+ *
+ * Wireless drivers can use this function to hint to the wireless core
+ * the current regulatory domain as specified by trusted applications,
+ * it is the driver's responsibilty to estbalish which applications it
+ * trusts.
+ *
+ * The wiphy should be registered to cfg80211 prior to this call.
+ * For cfg80211 drivers this means you must first use wiphy_register(),
+ * for mac80211 drivers you must first use ieee80211_register_hw().
+ *
+ * Drivers should check the return value, its possible you can get
+ * an -ENOMEM or an -EINVAL.
+ *
+ * Return: 0 on success. -ENOMEM, -EINVAL.
+ */
+int regulatory_hint_user(const char *alpha2,
+ enum nl80211_user_reg_hint_type user_reg_hint_type);
+
+/**
* wiphy_apply_custom_regulatory - apply a custom driver regulatory domain
* @wiphy: the wireless device we want to process the regulatory domain on
* @regd: the custom regulatory domain to use for this wiphy
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index dd58b9909ac9..816a8a25b06f 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -2912,6 +2912,7 @@ int regulatory_hint_user(const char *alpha2,
return 0;
}
+EXPORT_SYMBOL(regulatory_hint_user);
int regulatory_hint_indoor(bool is_indoor, u32 portid)
{
diff --git a/net/wireless/reg.h b/net/wireless/reg.h
index 9ceeb5f3a7cb..92de47dec466 100644
--- a/net/wireless/reg.h
+++ b/net/wireless/reg.h
@@ -31,9 +31,6 @@ bool is_world_regdom(const char *alpha2);
bool reg_supported_dfs_region(enum nl80211_dfs_regions dfs_region);
enum nl80211_dfs_regions reg_get_dfs_region(struct wiphy *wiphy);
-int regulatory_hint_user(const char *alpha2,
- enum nl80211_user_reg_hint_type user_reg_hint_type);
-
/**
* regulatory_hint_indoor - hint operation in indoor env. or not
* @is_indoor: if true indicates that user space thinks that the

View File

@ -1,62 +0,0 @@
From: Alex Gonzalez <alex.gonzalez@digi.com>
Date: Fri, 7 Sep 2018 13:12:14 +0200
Subject: [PATCH] net: wireless: Allow for firmware to handle DFS
The QCA6564 driver makes use of this functionality when compiled with
the QCA_VENDOR_KERNEL flag.
Signed-off-by: Alex Gonzalez <alex.gonzalez@digi.com>
---
include/net/cfg80211.h | 2 ++
net/wireless/chan.c | 3 ++-
net/wireless/nl80211.c | 3 +++
3 files changed, 7 insertions(+), 1 deletion(-)
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 84d47ac0cea4..3082f6bf047d 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -3740,6 +3740,7 @@ struct cfg80211_ops {
* beaconing mode (AP, IBSS, Mesh, ...).
* @WIPHY_FLAG_HAS_STATIC_WEP: The device supports static WEP key installation
* before connection.
+ * @WIPHY_FLAG_DFS_OFFLOAD: The driver handles all the DFS related operations.
*/
enum wiphy_flags {
/* use hole at 0 */
@@ -3766,6 +3767,7 @@ enum wiphy_flags {
WIPHY_FLAG_SUPPORTS_5_10_MHZ = BIT(22),
WIPHY_FLAG_HAS_CHANNEL_SWITCH = BIT(23),
WIPHY_FLAG_HAS_STATIC_WEP = BIT(24),
+ WIPHY_FLAG_DFS_OFFLOAD = BIT(25),
};
/**
diff --git a/net/wireless/chan.c b/net/wireless/chan.c
index 7dc1bbd0888f..2ef1f908408f 100644
--- a/net/wireless/chan.c
+++ b/net/wireless/chan.c
@@ -321,7 +321,8 @@ static int cfg80211_get_chans_dfs_required(struct wiphy *wiphy,
if (!c)
return -EINVAL;
- if (c->flags & IEEE80211_CHAN_RADAR)
+ if ((c->flags & IEEE80211_CHAN_RADAR) &&
+ !(wiphy->flags & WIPHY_FLAG_DFS_OFFLOAD))
return 1;
}
return 0;
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index d91a408db113..930670ccfa59 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -7956,6 +7956,9 @@ static int nl80211_start_radar_detection(struct sk_buff *skb,
if (netif_carrier_ok(dev))
return -EBUSY;
+ if (rdev->wiphy.flags & WIPHY_FLAG_DFS_OFFLOAD)
+ return -EOPNOTSUPP;
+
if (wdev->cac_started)
return -EBUSY;

View File

@ -1,95 +0,0 @@
From: Alex Gonzalez <alex.gonzalez@digi.com>
Date: Fri, 7 Sep 2018 13:01:54 +0200
Subject: [PATCH] net: wireless: Add
cfg80211_is_gratuitous_arp_unsolicited_na()
The QCA6564 driver makes use of this call when compiled with the
QCA_VENDOR_KERNEL flag.
Signed-off-by: Alex Gonzalez <alex.gonzalez@digi.com>
---
include/net/cfg80211.h | 10 ++++++++++
net/wireless/util.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 62 insertions(+)
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 3082f6bf047d..42445bd1c26a 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -6736,6 +6736,16 @@ void cfg80211_crit_proto_stopped(struct wireless_dev *wdev, gfp_t gfp);
unsigned int ieee80211_get_num_supported_channels(struct wiphy *wiphy);
/**
+ * cfg80211_is_gratuitous_arp_unsolicited_na - packet is grat. ARP/unsol. NA
+ * @skb: the input packet, must be an ethernet frame already
+ *
+ * Return: %true if the packet is a gratuitous ARP or unsolicited NA packet.
+ * This is used to drop packets that shouldn't occur because the AP implements
+ * a proxy service.
+ */
+bool cfg80211_is_gratuitous_arp_unsolicited_na(struct sk_buff *skb);
+
+/**
* cfg80211_check_combinations - check interface combinations
*
* @wiphy: the wiphy
diff --git a/net/wireless/util.c b/net/wireless/util.c
index ec30e3732c7b..abcefae39e81 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -2061,3 +2061,55 @@ int ieee80211_get_vht_max_nss(struct ieee80211_vht_cap *cap,
return max_vht_nss;
}
EXPORT_SYMBOL(ieee80211_get_vht_max_nss);
+
+bool cfg80211_is_gratuitous_arp_unsolicited_na(struct sk_buff *skb)
+{
+ const struct ethhdr *eth = (void *)skb->data;
+
+ const struct {
+ struct arphdr hdr;
+ u8 ar_sha[ETH_ALEN];
+ u8 ar_sip[4];
+ u8 ar_tha[ETH_ALEN];
+ u8 ar_tip[4];
+ } __packed * arp;
+
+ const struct ipv6hdr *ipv6;
+ const struct icmp6hdr *icmpv6;
+
+ switch (eth->h_proto) {
+ case cpu_to_be16(ETH_P_ARP):
+ /* can't say - but will probably be dropped later anyway */
+ if (!pskb_may_pull(skb, sizeof(*eth) + sizeof(*arp)))
+ return false;
+
+ arp = (void *)(eth + 1);
+
+ if ((arp->hdr.ar_op == cpu_to_be16(ARPOP_REPLY) ||
+ arp->hdr.ar_op == cpu_to_be16(ARPOP_REQUEST)) &&
+ !memcmp(arp->ar_sip, arp->ar_tip, sizeof(arp->ar_sip)))
+ return true;
+ break;
+ case cpu_to_be16(ETH_P_IPV6):
+ /* can't say - but will probably be dropped later anyway */
+ if (!pskb_may_pull(skb, sizeof(*eth) + sizeof(*ipv6) +
+ sizeof(*icmpv6)))
+ return false;
+
+ ipv6 = (void *)(eth + 1);
+ icmpv6 = (void *)(ipv6 + 1);
+
+ if (icmpv6->icmp6_type == NDISC_NEIGHBOUR_ADVERTISEMENT &&
+ !memcmp(&ipv6->saddr, &ipv6->daddr, sizeof(ipv6->saddr)))
+ return true;
+ break;
+ default:
+ /* no need to support other protocols, proxy service isn't
+ * specified for any others
+ */
+ break;
+ }
+
+ return false;
+}
+EXPORT_SYMBOL(cfg80211_is_gratuitous_arp_unsolicited_na);

View File

@ -1,26 +0,0 @@
From: Jose Diaz de Grenu <Jose.DiazdeGrenu@digi.com>
Date: Wed, 27 Jun 2018 17:39:11 +0200
Subject: [PATCH] linux: crypto: caam set hwrng quality
According to the i.MX6 Security Reference Manual it is a NIST
certifiable RNG, so set high quality to let the HWRNG framework
automatically use it.
Signed-off-by: Jose Diaz de Grenu <Jose.DiazdeGrenu@digi.com>
Signed-off-by: Alex Gonzalez <alex.gonzalez@digi.com>
---
drivers/crypto/caam/caamrng.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/crypto/caam/caamrng.c b/drivers/crypto/caam/caamrng.c
index fde07d4ff019..ddca16941640 100644
--- a/drivers/crypto/caam/caamrng.c
+++ b/drivers/crypto/caam/caamrng.c
@@ -292,6 +292,7 @@ static struct hwrng caam_rng = {
.name = "rng-caam",
.cleanup = caam_cleanup,
.read = caam_read,
+ .quality = 1024,
};
static void __exit caam_rng_exit(void)

View File

@ -8,27 +8,6 @@ SRC_URI_append_imx6qdl-variscite-som_use-mainline-bsp = " \
file://imx6q-var-som-vsc.dts \
"
SRC_URI_append_ccimx6ul = " \
file://0001-MLK-11719-4-mtd-gpmi-change-the-BCH-layout-setting-f.patch \
${@bb.utils.contains('MACHINE_FEATURES', 'wifi', 'file://0002-ARM-dts-imx6ul-ccimx6ulsom-Add-empty-wireless-and-bl.patch', '', d)} \
${@bb.utils.contains('MACHINE_FEATURES', 'wifi', 'file://0003-net-wireless-Export-regulatory_hint_user.patch', '', d)} \
${@bb.utils.contains('MACHINE_FEATURES', 'wifi', 'file://0004-net-wireless-Allow-for-firmware-to-handle-DFS.patch', '', d)} \
${@bb.utils.contains('MACHINE_FEATURES', 'wifi', 'file://0005-net-wireless-Add-cfg80211_is_gratuitous_arp_unsolici.patch', '', d)} \
file://0006-linux-crypto-caam-set-hwrng-quality.patch \
"
do_configure_prepend_ccimx6ul() {
if ${@bb.utils.contains('MACHINE_FEATURES', 'wifi', 'true', 'false', d)}; then
kernel_conf_variable HOSTAP m
kernel_conf_variable PROVE_LOCKING n
sed -e "${CONF_SED_SCRIPT}" < '${WORKDIR}/defconfig' >> '${B}/.config'
fi
if ${@bb.utils.contains('MACHINE_FEATURES', 'bluetooth', 'true', 'false', d)}; then
kernel_conf_variable BT_RFCOMM y
sed -e "${CONF_SED_SCRIPT}" < '${WORKDIR}/defconfig' >> '${B}/.config'
fi
}
do_configure_prepend_imx6qdl-variscite-som() {
cp ${WORKDIR}/imx6*-var*.dts* ${S}/arch/arm/boot/dts
}