mirror of
https://github.com/Freescale/meta-freescale-3rdparty.git
synced 2025-07-19 12:09:01 +02:00
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:
parent
9000d8b388
commit
cf2ab8d76c
|
@ -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"
|
|
@ -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)"
|
|
@ -1,2 +0,0 @@
|
|||
# Attach QCA6564 Bluetooth (uart)
|
||||
SUBSYSTEM=="tty", KERNEL=="ttymxc0", ACTION=="add", RUN="/etc/udev/scripts/qca6564-attach.sh start"
|
|
@ -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"
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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)"
|
|
@ -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)"
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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 doesn’t 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 */
|
||||
};
|
||||
|
||||
/**
|
|
@ -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;
|
|
@ -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 = <®_arm>;
|
||||
soc-supply = <®_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 {
|
|
@ -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 doesn’t 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 */
|
||||
};
|
||||
|
||||
/**
|
|
@ -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 {
|
|
@ -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
|
|
@ -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;
|
||||
|
|
@ -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);
|
|
@ -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)
|
|
@ -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
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user